@goodfellow-cms/admin 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,745 @@
1
+ import { ContentStore, GitHost, GoodfellowConfig, SignInError } from "@goodfellow-cms/core";
2
+ import "react";
3
+ import "@puckeditor/core";
4
+ //#region src/admin-context.d.ts
5
+ /** How previews load the site's styles. Provided by the dev server or build that serves the admin panel. */
6
+ interface PreviewOptions {
7
+ /** The site's compiled stylesheets. */
8
+ stylesheets: string[];
9
+ /** `@goodfellow-cms/react/theme.css`, so Tailwind in the preview knows the theme's classes. */
10
+ themeCss: string;
11
+ /** URL of `@tailwindcss/browser`, which styles classes typed in the editor before the site is rebuilt. */
12
+ tailwindBrowserUrl?: string;
13
+ }
14
+ //#endregion
15
+ //#region src/strings.d.ts
16
+ /**
17
+ * Every piece of text the admin panel shows, so it can be reworded or
18
+ * translated. `{name}` placeholders are filled in when the text is used.
19
+ * Puck's own editor text is translated separately, with its `dictionary`.
20
+ */
21
+ export declare const defaultStrings: {
22
+ readonly "app.title": "Site admin";
23
+ readonly "app.viewSite": "View site";
24
+ readonly "nav.pages": "Pages";
25
+ readonly "nav.collections": "Collections";
26
+ readonly "nav.media": "Media";
27
+ readonly "nav.blocks": "Blocks";
28
+ readonly "nav.layout": "Header & Footer";
29
+ readonly "nav.settings": "Site Settings";
30
+ readonly loading: "Loading…";
31
+ readonly "setup.noBackend": "This site's settings don't say where the site is stored, so the admin panel can't open it. A developer needs to add a backend to goodfellow.config.tsx.";
32
+ readonly "signIn.title": "Sign in to edit this site";
33
+ readonly "signIn.intro": "The site is stored on {host}. Sign in with a {host} account that's allowed to change it.";
34
+ readonly "signIn.redirect": "Sign in with {host}";
35
+ readonly "signIn.orToken": "Or sign in with an access token";
36
+ readonly "signIn.token.title": "Sign in with an access token";
37
+ readonly "signIn.token.step1": "Create an access token on {host}. This link opens {host} with the right settings already chosen:";
38
+ readonly "signIn.token.create": "Create a token on {host}";
39
+ readonly "signIn.token.createBroad": "Create a broader token instead";
40
+ readonly "signIn.token.createBroadHint": "Use this if the site belongs to someone else and the first link doesn't let you choose it. This kind of token can change everything your account can.";
41
+ readonly "signIn.token.chooseSite": "If {host} asks what the token can access, choose this site.";
42
+ readonly "signIn.token.step2": "Copy the token and paste it here:";
43
+ readonly "signIn.token.label": "Access token";
44
+ readonly "signIn.remember": "Stay signed in on this device";
45
+ readonly "signIn.rememberHint": "Leave this off on shared or public computers.";
46
+ readonly "signIn.submit": "Sign in";
47
+ readonly "signIn.checking": "Signing in…";
48
+ readonly "signIn.error.invalid": "That sign-in didn't work. Check that the whole token was copied and that it hasn't expired.";
49
+ readonly "signIn.error.no-access": "That account can't see this site. Make sure the token was given access to it.";
50
+ readonly "signIn.error.cant-publish": "That account can see the site but isn't allowed to change it. Ask the site's owner to give it permission.";
51
+ readonly "signIn.error.redirect-failed": "Signing in didn't finish. Try again.";
52
+ readonly "signIn.error.expired": "You were signed out because your sign-in expired. Sign in again to keep editing.";
53
+ readonly "signIn.error.other": "Couldn't reach {host}. Check your connection and try again.";
54
+ readonly "account.signedInAs": "Signed in as {name}";
55
+ readonly "account.signOut": "Sign out";
56
+ readonly "deploy.building": "Updating the live site…";
57
+ readonly "deploy.live": "The live site is up to date";
58
+ readonly "deploy.failed": "The live site couldn't be updated";
59
+ readonly "build.why": "What went wrong?";
60
+ readonly "build.title": "Why the live site wasn't updated";
61
+ readonly "build.saved": "Your changes are published and saved. Visitors see the site as it was until it's rebuilt, which every publish tries again.";
62
+ readonly "build.notStarted": "{host} didn't start rebuilding the site. That usually means the account the site belongs to has used up its free build minutes for the month, or its billing on {host} needs attention. One of the site's owners can check the account's billing settings on {host}.";
63
+ readonly "build.install": "The site's packages couldn't be installed, so it couldn't be rebuilt. That's sometimes a passing problem with the service the packages come from, so publishing again later may work. If it keeps happening, a developer needs to look at the details.";
64
+ readonly "build.pages": "{host} Pages isn't set up for the site, so there's nowhere to put it online. One of the site's owners needs to turn it on in the site's settings on {host}, under Pages.";
65
+ readonly "build.deploy": "The site was rebuilt, but {host} couldn't put it online. That's usually a passing problem, so the next publish may work. If it keeps happening, check the site's Pages settings on {host}.";
66
+ readonly "build.host": "A problem on {host}'s side stopped the rebuild. That's usually a passing problem, so the next publish may work.";
67
+ readonly "build.content": "The site couldn't be rebuilt, because {file} has a problem. Fix it in the admin panel, or put back a version that worked from its version history.";
68
+ readonly "build.contentHistory": "Version history of {file}";
69
+ readonly "build.codeChanged": "The site couldn't be rebuilt after its blocks changed. Undo the change under Blocks, by removing what was just added or adding back what was removed, and ask a developer to look at the details.";
70
+ readonly "build.blocks": "Go to Blocks";
71
+ readonly "build.codeFile": "The site's code couldn't be rebuilt: there's a problem in {file}. A developer needs to look at the details.";
72
+ readonly "build.code": "The site couldn't be rebuilt. A developer needs to look at the details.";
73
+ readonly "build.unknown": "{host} didn't say why the rebuild failed. Its details may help a developer.";
74
+ readonly "build.hostDetails": "See the details on {host}";
75
+ readonly "loadError.title": "The admin panel couldn't open this site";
76
+ readonly "loadError.contentProblems": "Some of the site's files have problems, so they can't be edited until they're fixed.";
77
+ readonly "loadError.other": "Something went wrong while loading the site. Check your connection and try again.";
78
+ readonly "action.tryAgain": "Try again";
79
+ readonly "action.cancel": "Cancel";
80
+ readonly "action.close": "Close";
81
+ readonly "action.reload": "Reload";
82
+ readonly "action.undo": "Undo";
83
+ readonly "action.redo": "Redo";
84
+ readonly "action.undoHint": "Undo the last change (Ctrl+Z, or ⌘Z on a Mac)";
85
+ readonly "action.redoHint": "Redo what you undid (Ctrl+Shift+Z, or ⇧⌘Z on a Mac)";
86
+ readonly "details.show": "Details";
87
+ readonly "publish.button": "Publish";
88
+ readonly "publish.publishing": "Publishing…";
89
+ readonly "publish.done": "Published.";
90
+ readonly "publish.conflict": "Someone else changed the site since you opened this page, so your changes weren't published. Reload to see their changes, then make yours again.";
91
+ readonly "publish.error": "Your changes couldn't be published. Check your connection and try again.";
92
+ readonly "publish.invalid": "Fix the highlighted problems before publishing.";
93
+ readonly "unsaved.confirm": "You have changes that aren't published yet. Leave anyway and lose them?";
94
+ readonly "unsaved.label": "Unpublished changes";
95
+ readonly "pages.title": "Pages";
96
+ readonly "pages.new": "New page";
97
+ readonly "pages.empty": "This site has no pages yet.";
98
+ readonly "pages.column.title": "Title";
99
+ readonly "pages.column.address": "Address";
100
+ readonly "pages.edit": "Edit";
101
+ readonly "pages.move": "Change address";
102
+ readonly "pages.delete": "Delete";
103
+ readonly "pages.view": "View";
104
+ readonly "pages.homeCantDelete": "The home page can't be deleted.";
105
+ readonly "newPage.title": "New page";
106
+ readonly "newPage.pageTitle": "Page title";
107
+ readonly "newPage.address": "Address";
108
+ readonly "newPage.addressHint": "The part of the web address after the site's name, such as /about or /events/picnic.";
109
+ readonly "newPage.create": "Create page";
110
+ readonly "newPage.message": 'Add page "{title}"';
111
+ readonly "movePage.title": "Change the address of {title}";
112
+ readonly "movePage.address": "New address";
113
+ readonly "movePage.updateLinks": "Update menu links to this page";
114
+ readonly "movePage.redirect": "Keep {from} working by sending visitors on to the page";
115
+ readonly "movePage.redirectHint": "Links to the old address elsewhere, such as on other websites, keep working. Site Settings → Redirects lists it.";
116
+ readonly "movePage.warning": "Links to the old address elsewhere, such as in page text or on other websites, will stop working.";
117
+ readonly "movePage.submit": "Change address";
118
+ readonly "movePage.message": 'Move page "{title}" from {from} to {to}';
119
+ readonly "deletePage.title": "Delete {title}?";
120
+ readonly "deletePage.body": "The page at {path} will be removed from the site. Menu links to it will stop working.";
121
+ readonly "deletePage.submit": "Delete page";
122
+ readonly "deletePage.message": 'Delete page "{title}"';
123
+ readonly "address.invalid": "Use lowercase letters, numbers and hyphens, with / between parts, such as /about-us.";
124
+ readonly "address.reserved": "This address is used by the admin panel. Choose another.";
125
+ readonly "address.taken": "Another page already uses this address.";
126
+ readonly "field.required": "This can't be empty.";
127
+ readonly "editPage.message": 'Update page "{title}"';
128
+ readonly "editPage.notFound": "This page doesn't exist. It may have been moved or deleted.";
129
+ readonly "editPage.backToPages": "Back to pages";
130
+ readonly "versions.button": "Version history";
131
+ readonly "versions.title": "Version history: {title}";
132
+ readonly "versions.back": "Back to editing";
133
+ readonly "versions.intro": "Every version that's been published, newest first. Choose one to see it, then restore it to put it back. Something that was moved to a new address starts a new history there.";
134
+ readonly "versions.notFound": "There's no history to show here. It may have been moved or deleted.";
135
+ readonly "versions.local": "Version history is in the published site's admin panel, where you sign in with GitHub or GitLab.";
136
+ readonly "versions.demo": "Version history isn't kept in a demo.";
137
+ readonly "versions.loading": "Loading versions…";
138
+ readonly "versions.loadingVersion": "Loading this version…";
139
+ readonly "versions.error": "The versions couldn't be loaded. Check your connection and try again.";
140
+ readonly "versions.empty": "Nothing has been published here yet.";
141
+ readonly "versions.current": "Current version";
142
+ readonly "versions.by": "{date}, by {author}";
143
+ readonly "versions.more": "Show older versions";
144
+ readonly "versions.preview": "The version from {date}";
145
+ readonly "versions.noPreview": "This item has no page of its own, so there's nothing to preview.";
146
+ readonly "versions.restore": "Restore this version";
147
+ readonly "versions.restoreTitle": "Restore the version from {date}?";
148
+ readonly "versions.restoreBody": "{title} goes back to how it was then, and that's published straight away. The current version stays in the history, so you can restore it later.";
149
+ readonly "versions.restoring": "Restoring…";
150
+ readonly "versions.restoreMessage": 'Restore "{title}" to the version from {date}';
151
+ readonly "versions.restored": "Restored the version from {date}.";
152
+ readonly "versions.readError": "This version couldn't be loaded. Check your connection and try again.";
153
+ readonly "versions.unfit": "This version can't be restored, because it doesn't fit the site as it is now, for example because the choices for one of its fields have changed.";
154
+ readonly "versions.unknownBlocks": "This version can't be restored, because it uses blocks the site doesn't have any more: {blocks}.";
155
+ readonly "layout.header": "Header";
156
+ readonly "layout.footer": "Footer";
157
+ readonly "layout.headerMessage": "Update the header";
158
+ readonly "layout.footerMessage": "Update the footer";
159
+ readonly "collections.title": "Collections";
160
+ readonly "collections.intro": "Collections are groups of similar items, such as videos, events or staff. Each collection has its own fields, and can give every item a page that shares one design.";
161
+ readonly "collections.new": "New collection";
162
+ readonly "collections.empty": "There are no collections yet.";
163
+ readonly "collections.column.name": "Name";
164
+ readonly "collections.column.count": "Items";
165
+ readonly "collections.column.address": "Pages";
166
+ readonly "collections.noPages": "No pages of their own";
167
+ readonly "newCollection.title": "New collection";
168
+ readonly "newCollection.kind": "Start with";
169
+ readonly "newCollection.kindBlank": "A title and text";
170
+ readonly "newCollection.kindEvents": "Events";
171
+ readonly "newCollection.kindEventsHint": "Each item has a date and time, which can repeat, a place and a summary. Calendar blocks show them, and visitors can add them to their own calendars.";
172
+ readonly "newCollection.eventsName": "Events";
173
+ readonly "newCollection.eventsEntryName": "Event";
174
+ readonly "newCollection.timeZone": "The site's time zone will be set to {zone}. You can change it in Site Settings.";
175
+ readonly "newCollection.name": "Name";
176
+ readonly "newCollection.nameHint": "What the whole collection is called, such as Videos or Events.";
177
+ readonly "newCollection.nameTaken": "Another collection already has a name like this. Choose another.";
178
+ readonly "newCollection.entryName": "One item is called";
179
+ readonly "newCollection.entryNameHint": "Such as Video or Event.";
180
+ readonly "newCollection.pages": "Give each item its own page";
181
+ readonly "newCollection.address": "Address of the pages";
182
+ readonly "newCollection.addressHint": "Each item's page goes inside this address, such as /videos/easter-vigil.";
183
+ readonly "newCollection.create": "Create collection";
184
+ readonly "newCollection.message": 'Add collection "{name}"';
185
+ readonly "collection.tab.entries": "Items";
186
+ readonly "collection.tab.template": "Page design";
187
+ readonly "collection.tab.settings": "Settings";
188
+ readonly "collection.notFound": "This collection doesn't exist. It may have been deleted.";
189
+ readonly "collection.back": "Back to collections";
190
+ readonly "entries.add": "Add {entry}";
191
+ readonly "entries.empty": "There's nothing in {name} yet.";
192
+ readonly "entries.column.title": "Title";
193
+ readonly "entries.column.address": "Address";
194
+ readonly "newEntry.title": "Add {entry}";
195
+ readonly "newEntry.entryTitle": "Title";
196
+ readonly "newEntry.address": "Address";
197
+ readonly "newEntry.addressHint": "The last part of the page's address, as in {example}.";
198
+ readonly "newEntry.message": 'Add {entry} "{title}"';
199
+ readonly "entryName.invalid": "Use lowercase letters, numbers and hyphens only, such as easter-vigil.";
200
+ readonly "entryName.reserved": "This address is used by the admin panel. Choose another.";
201
+ readonly "entryName.taken": "Something else on the site already uses this address.";
202
+ readonly "moveEntry.message": 'Move {entry} "{title}" from {from} to {to}';
203
+ readonly "deleteEntry.body": "{title} will be removed from {name}.";
204
+ readonly "deleteEntry.bodyPage": "{title} will be removed from {name}, and its page at {path} from the site. Menu links to it will stop working.";
205
+ readonly "deleteEntry.message": 'Delete {entry} "{title}"';
206
+ readonly "editEntry.message": 'Update {entry} "{title}"';
207
+ readonly "editEntry.notFound": "This item doesn't exist. It may have been renamed or deleted.";
208
+ readonly "editEntry.back": "Back to {name}";
209
+ readonly "editEntry.required": "Fill in {fields} before publishing.";
210
+ readonly "editEntry.invalidEvent": "Check {fields}: an event has to end after it starts.";
211
+ readonly "editEntry.noPage": "Items in {name} don't have pages of their own. They appear wherever a Collection list block shows {name}.";
212
+ readonly "template.help": "Every item's page uses this design. To show an item's information, add an Entry field block, or type a field's name in braces in any text:";
213
+ readonly "template.message": "Update the page design for {name}";
214
+ readonly "template.noPages": "Items in {name} don't have pages of their own, so there's no page design. To give them pages, turn that on in Settings.";
215
+ readonly "collectionSettings.markdown": "Store items as Markdown files";
216
+ readonly "collectionSettings.markdownHint": "Each item's text is saved as Markdown, a plain-text format that developers can also edit in their own tools. It's edited here as before.";
217
+ readonly "collectionSettings.markdownNeedsText": "To store items as Markdown files, add a formatted-text field first.";
218
+ readonly "collectionSettings.markdownBody": "Field saved as the Markdown text";
219
+ readonly "collectionSettings.markdownConverts": "Every item will be converted when you publish.";
220
+ readonly "collectionSettings.calendar": "Show items in calendars";
221
+ readonly "collectionSettings.calendarHint": "Items become events that Calendar blocks show, which visitors can add to their own calendars or subscribe to.";
222
+ readonly "collectionSettings.calendarNeedsDate": 'To show items in calendars, add a "Date and time, for events" field first.';
223
+ readonly "collectionSettings.calendarWhen": "When items happen";
224
+ readonly "collectionSettings.calendarPlace": "Where";
225
+ readonly "collectionSettings.calendarSummary": "Summary";
226
+ readonly "collectionSettings.calendarNone": "None";
227
+ readonly "event.starts": "Starts";
228
+ readonly "event.ends": "Ends (optional)";
229
+ readonly "event.time": "Time";
230
+ readonly "event.allDay": "All day";
231
+ readonly "event.repeats": "Repeats";
232
+ readonly "event.repeat.none": "Doesn't repeat";
233
+ readonly "event.repeat.day": "Daily";
234
+ readonly "event.repeat.week": "Weekly";
235
+ readonly "event.repeat.month": "Monthly";
236
+ readonly "event.repeat.year": "Yearly";
237
+ readonly "event.interval.days": "Every how many days";
238
+ readonly "event.interval.weeks": "Every how many weeks";
239
+ readonly "event.interval.months": "Every how many months";
240
+ readonly "event.interval.years": "Every how many years";
241
+ readonly "event.onDays": "On";
242
+ readonly "event.monthlyOn": "On";
243
+ readonly "event.monthly.date": "Day {day} of the month";
244
+ readonly "event.monthly.weekday": "The {nth} {weekday} of the month";
245
+ readonly "event.monthly.last": "The last {weekday} of the month";
246
+ readonly "event.nth.1": "first";
247
+ readonly "event.nth.2": "second";
248
+ readonly "event.nth.3": "third";
249
+ readonly "event.nth.4": "fourth";
250
+ readonly "event.nth.5": "fifth";
251
+ readonly "event.until": "Until (optional)";
252
+ readonly "event.skip": "Dates it doesn't happen";
253
+ readonly "event.skipDate": "A date it doesn't happen";
254
+ readonly "event.addSkip": "Skip this date";
255
+ readonly "event.next": "Next: {when}";
256
+ readonly "event.when": "{when}";
257
+ readonly "collectionSettings.general": "General";
258
+ readonly "collectionSettings.path": "Address of each item's page";
259
+ readonly "collectionSettings.pathHint": "{slug} stands for each item's own address, as in /videos/{slug}.";
260
+ readonly "collectionSettings.pathWarning": "Changing this changes the address of every item's page. Links to the old addresses elsewhere will stop working.";
261
+ readonly "collectionSettings.sortField": "Order items by";
262
+ readonly "collectionSettings.sortOrder": "Direction";
263
+ readonly "collectionSettings.ascending": "A to Z, oldest or smallest first";
264
+ readonly "collectionSettings.descending": "Z to A, newest or largest first";
265
+ readonly "collectionSettings.message": "Update the settings for {name}";
266
+ readonly "collectionSettings.addressClash": "With this address, {title} would have the same address as another page.";
267
+ readonly "collectionSettings.delete": "Delete collection";
268
+ readonly "collectionSettings.deleteTitle": "Delete {name}?";
269
+ readonly "collectionSettings.deleteBody": "{name} and everything in it ({count} items) will be removed from the site, along with their pages. Collection lists showing it will be empty.";
270
+ readonly "collectionSettings.deleteMessage": 'Delete collection "{name}"';
271
+ readonly "fields.title": "Fields";
272
+ readonly "fields.intro": "The information each item has. Every item has a title. A field's kind can't be changed once it's published, but you can add a new field instead.";
273
+ readonly "fields.add": "Add field";
274
+ readonly "fields.label": "Label";
275
+ readonly "fields.type": "Kind of information";
276
+ readonly "fields.required": "Must be filled in";
277
+ readonly "fields.hint": "Help text";
278
+ readonly "fields.options": "Choices";
279
+ readonly "fields.option": "Choice {number}";
280
+ readonly "fields.addOption": "Add choice";
281
+ readonly "fields.optionsRequired": "Add at least one choice.";
282
+ readonly "fields.placeholder": "Show it on the page design with {placeholder}";
283
+ readonly "fields.remove": "Remove field";
284
+ readonly "fields.removed": "Removed fields are also removed from every item when you publish.";
285
+ readonly "fields.newLabel": "New field";
286
+ readonly "fields.type.text": "Short text";
287
+ readonly "fields.type.textarea": "Long text";
288
+ readonly "fields.type.richtext": "Formatted text";
289
+ readonly "fields.type.number": "Number";
290
+ readonly "fields.type.date": "Date";
291
+ readonly "fields.type.event": "Date and time, for events";
292
+ readonly "fields.type.link": "Link";
293
+ readonly "fields.type.image": "Image (URL)";
294
+ readonly "fields.type.select": "Choice from a list";
295
+ readonly "fields.type.tags": "Tags (any number of choices from a list)";
296
+ readonly "demo.banner": "This is a demo. Try anything you like: your changes show here in the admin panel and are saved in this browser only. The site itself never changes.";
297
+ readonly "demo.published": "Saved in this browser. The site itself doesn't change in a demo.";
298
+ readonly "demo.startOver": "Start over";
299
+ readonly "demo.startOverTitle": "Start over?";
300
+ readonly "demo.startOverBody": "Everything you've changed in this demo, including uploads, will be undone.";
301
+ readonly "blocks.demo": "In this demo you can see which blocks there are, but not add or remove them: a block is added to a real site by updating its code.";
302
+ readonly "markdown.formatted": "Formatted";
303
+ readonly "markdown.source": "Markdown";
304
+ readonly "markdown.sourceOnly": "This text uses things the formatted view can't show, such as tables or pictures, so it can only be edited as Markdown.";
305
+ readonly "blocks.title": "Blocks";
306
+ readonly "blocks.intro": "Add blocks to the editor, or remove ones you don't use. A change shows in the editor once the site has been updated, usually within a few minutes.";
307
+ readonly "blocks.installed": "Added to this site";
308
+ readonly "blocks.noneInstalled": "No blocks have been added yet. The editor offers the built-in ones.";
309
+ readonly "blocks.loading": "Loading the blocks you can add…";
310
+ readonly "blocks.recommended": "Recommended";
311
+ readonly "blocks.add": "Add";
312
+ readonly "blocks.addLabel": "Add {name}";
313
+ readonly "blocks.added": "Added";
314
+ readonly "blocks.remove": "Remove";
315
+ readonly "blocks.removeLabel": "Remove {name}";
316
+ readonly "blocks.undo": "Undo";
317
+ readonly "blocks.undoAddLabel": "Don't add {name}";
318
+ readonly "blocks.undoRemoveLabel": "Don't remove {name}";
319
+ readonly "blocks.willAdd": "Will be added";
320
+ readonly "blocks.willRemove": "Will be removed";
321
+ readonly "blocks.pendingTitle": "Changes to publish";
322
+ readonly "blocks.pendingAdd": "Add {name}";
323
+ readonly "blocks.pendingRemove": "Remove {name}";
324
+ readonly "blocks.discard": "Discard changes";
325
+ readonly "blocks.publish": "Publish";
326
+ readonly "blocks.publishedNotice": "Published. Added blocks will be in the editor's list of blocks, and removed ones gone from it, once the site has been updated.";
327
+ readonly "blocks.addMessage": "Add the {name} block";
328
+ readonly "blocks.removeMessage": "Remove the {name} block";
329
+ readonly "blocks.changeMessage": "Change blocks: {changes}";
330
+ readonly "blocks.addPart": "add {names}";
331
+ readonly "blocks.removePart": "remove {names}";
332
+ readonly "blocks.inUseTitle": "{name} can't be removed yet";
333
+ readonly "blocks.inUse": "{name} is used in: {places}. Take it out of those first, then remove it.";
334
+ readonly "blocks.usedTemplate": "the page design of {name}";
335
+ readonly "blocks.error.record": "The list of blocks added to this site couldn't be read. Tell whoever looks after the site.";
336
+ readonly "blocks.error.unreachable": "The blocks you can add couldn't be loaded. Check your internet connection and try again.";
337
+ readonly "blocks.error.invalid": "The list of blocks you can add has a problem, so it couldn't be read. Try again later.";
338
+ readonly "blocks.error.untrusted": "This block comes from somewhere this site doesn't trust, so it can't be added.";
339
+ readonly "blocks.error.not-a-block": "This can't be added to the editor as a block.";
340
+ readonly "blocks.error.already-installed": "{name} has already been added.";
341
+ readonly "blocks.error.name-taken": "The site already has a block with the same name as {name}, so it can't be added.";
342
+ readonly "blocks.error.packages": "This block needs software the site doesn't have ({packages}). Ask whoever looks after the site to add it.";
343
+ readonly "blocks.error.unsupported-file": "This block includes a file that can't be added from here ({path}). Ask whoever looks after the site to add it.";
344
+ readonly "blocks.error.file-exists": "The site already has a different file where this block goes ({path}). Ask whoever looks after the site to add it.";
345
+ readonly "blocks.error.not-installed": "{name} hasn't been added, so there's nothing to remove.";
346
+ readonly "blocks.error.in-use": "{name} is still used on the site. Take it out first, then remove it.";
347
+ readonly "media.title": "Media";
348
+ readonly "media.intro": "Images and files for the site. Upload them here, or while editing a page. Large photos are made smaller, and details hidden in photos, such as where they were taken, are removed.";
349
+ readonly "media.upload": "Upload files";
350
+ readonly "media.uploading": "Uploading…";
351
+ readonly "media.drop": "Drop files here to upload them";
352
+ readonly "media.empty": "There are no images or files yet.";
353
+ readonly "media.search": "Find a file";
354
+ readonly "media.noMatches": "No files match.";
355
+ readonly "media.copy": "Copy address";
356
+ readonly "media.copied": "Copied";
357
+ readonly "media.replace": "Replace";
358
+ readonly "media.delete": "Delete";
359
+ readonly "media.uploaded": "Uploaded. Visitors see new files once the live site is updated.";
360
+ readonly "media.uploadMessage": "Add {names}";
361
+ readonly "media.replaceMessage": "Replace {name}";
362
+ readonly "media.deleteMessage": "Delete {name}";
363
+ readonly "media.deleteTitle": "Delete {name}?";
364
+ readonly "media.deleteBody": "{name} will be removed from the site.";
365
+ readonly "media.deleteUsed": "It's used in: {places}. Those places will show a missing image or a broken link.";
366
+ readonly "media.notUsed": "Nothing on the site uses it.";
367
+ readonly "media.error.type": "{name} can't be uploaded. The site can use images (JPEG, PNG, GIF, WebP, AVIF and SVG), PDFs, office documents, MP3 audio, MP4 and WebM video, and captions for videos (WebVTT).";
368
+ readonly "media.error.size": "{name} is too large: files can be up to 25 MB. For long videos, upload them to YouTube or Vimeo and link to them instead.";
369
+ readonly "media.error.unreadable": "{name} couldn't be read. It may be damaged, or in a format browsers can't open, such as HEIC. Save it as a JPEG and try again.";
370
+ readonly "media.choose": "Choose image";
371
+ readonly "media.chooseFile": "Choose file";
372
+ readonly "media.chooseVideo": "Choose video";
373
+ readonly "media.pickerTitle": "Choose an image";
374
+ readonly "media.pickerTitleFile": "Choose a file";
375
+ readonly "media.pickerTitleVideo": "Choose a video";
376
+ readonly "media.pickerEmpty": "Nothing has been uploaded yet. Upload a file to use it here.";
377
+ readonly "media.clear": "Remove";
378
+ readonly "ai.label": "AI";
379
+ readonly "ai.title": "Write with AI";
380
+ readonly "ai.mode.add": "Describe what to add to this page, and AI will write it at the end of the page.";
381
+ readonly "ai.mode.edit": "Describe how to change the selected {block}.";
382
+ readonly "ai.mode.fill": "Describe this {item}, or paste your notes, and AI will fill in its fields.";
383
+ readonly "ai.instruction": "What should it write?";
384
+ readonly "ai.placeholder.add": "For example: a section about our Christmas Mass schedule, with a heading, a short welcome and a button to the contact page.";
385
+ readonly "ai.placeholder.edit": "For example: make it shorter and friendlier, or translate it into Spanish.";
386
+ readonly "ai.placeholder.fill": "For example: Fr. Smith's homily from Sunday, about hope. Paste any notes here.";
387
+ readonly "ai.write": "Write it";
388
+ readonly "ai.change": "Change it";
389
+ readonly "ai.fill": "Fill it in";
390
+ readonly "ai.stop": "Stop";
391
+ readonly "ai.working": "Writing…";
392
+ readonly "ai.progress": "Writing… {count} characters so far";
393
+ readonly "ai.done": "Done. Check it over, then publish when you're happy. Undo takes it back.";
394
+ readonly "ai.check": "AI can get things wrong, so read what it writes before publishing. It won't make up times, names or prices: it leaves [placeholders] for you to fill in.";
395
+ readonly "ai.needsKey": "To use {service}, add an API key under the AI service settings below, or choose another service.";
396
+ readonly "ai.settings": "AI service: {service}";
397
+ readonly "ai.provider": "AI service";
398
+ readonly "ai.provider.manual": "Copy and paste into a chat app (free)";
399
+ readonly "ai.provider.custom": "Another service (OpenAI-compatible)";
400
+ readonly "ai.noKey": "(free, no key needed)";
401
+ readonly "ai.baseUrl": "Address of the service's API";
402
+ readonly "ai.baseUrlHint": "Such as https://example.org/v1.";
403
+ readonly "ai.key": "API key";
404
+ readonly "ai.keyHint": "Your key stays in this browser and is only ever sent to {service}.";
405
+ readonly "ai.getKey": "Get a key from {service}";
406
+ readonly "ai.remember": "Remember the key on this device";
407
+ readonly "ai.forget": "Forget the key";
408
+ readonly "ai.costHint": "{service} may charge the account the key belongs to for each request. Setting a spending limit there is a good idea.";
409
+ readonly "ai.model": "Model";
410
+ readonly "ai.modelHint": "Choose one from the list, or type its name.";
411
+ readonly "ai.model.claude-opus-5-5": "Claude Opus 5.5 (best results)";
412
+ readonly "ai.model.claude-sonnet-5-5": "Claude Sonnet 5.5 (faster, costs less)";
413
+ readonly "ai.model.claude-haiku-4-5": "Claude Haiku 4.5 (fastest, costs least)";
414
+ readonly "ai.manual.step1": "Copy this request into Claude.ai, ChatGPT or another chat app:";
415
+ readonly "ai.manual.copy": "Copy the request";
416
+ readonly "ai.manual.copied": "Copied";
417
+ readonly "ai.manual.step2": "Then paste the chat app's whole answer here:";
418
+ readonly "ai.manual.use": "Use this answer";
419
+ readonly "ai.error.key": "{service} didn't accept the API key. Check that it was copied in full, that it hasn't been deleted, and that it can use this model.";
420
+ readonly "ai.error.limit": "{service} is limiting requests right now, or the account is out of credit. Wait a minute and try again, or choose another service.";
421
+ readonly "ai.error.network": "Couldn't reach {service}. Check your connection and try again.";
422
+ readonly "ai.error.refused": "{service} declined to write this. Try asking a different way.";
423
+ readonly "ai.error.answer": "The answer couldn't be used. Try again, or try a different model or service.";
424
+ readonly "ai.error.service": "{service} reported a problem. Try again in a moment.";
425
+ readonly "settings.title": "Site Settings";
426
+ readonly "appearance.choice": "Colors of the admin panel";
427
+ readonly "appearance.system": "Match my computer";
428
+ readonly "appearance.light": "Light";
429
+ readonly "appearance.dark": "Dark";
430
+ readonly "settings.tab.general": "General";
431
+ readonly "settings.tab.theme": "Colors & fonts";
432
+ readonly "settings.tab.menus": "Menus";
433
+ readonly "settings.tab.css": "Custom CSS";
434
+ readonly "settings.tab.code": "Code";
435
+ readonly "settings.tab.redirects": "Redirects";
436
+ readonly "settings.tab.domain": "Domain";
437
+ readonly "settings.message": "Update site settings";
438
+ readonly "settings.preview": "Preview of the home page";
439
+ readonly "settings.previewEmpty": "Add a home page to see a preview here.";
440
+ readonly "domain.intro": "Connect a domain you own, such as example.org, so the site is at that address.";
441
+ readonly "domain.current": "The site is at {address} now.";
442
+ readonly "domain.connected": "Connected to {domain}.";
443
+ readonly "domain.signIn": "Editors sign in by going to {host} and coming back here. Add {address} to the redirect URIs of the application they sign in with on {host}, or signing in will stop working once the site moves.";
444
+ readonly "domain.local": "Domains are connected in the published site's admin panel, where you sign in with GitHub or GitLab.";
445
+ readonly "domain.demo": "Domains can't be connected in a demo.";
446
+ readonly "domain.loading": "Finding where the site is published…";
447
+ readonly "domain.elsewhere": "This site isn't published with {host} Pages, so its domain is connected where it is published.";
448
+ readonly "domain.elsewhere.vercel": "On Vercel: open the site's project, go to Settings → Domains and add the domain. Vercel shows the records to add at your registrar. Once the site works at its new address, put the address in General → Site address and publish.";
449
+ readonly "domain.field": "Domain";
450
+ readonly "domain.fieldHint": "Such as example.org or www.example.org. Buy one first from a registrar, such as Cloudflare, Namecheap or Porkbun. For example.org, www.example.org works too.";
451
+ readonly "domain.invalid": "That isn't a domain. Type it like example.org.";
452
+ readonly "domain.warning": "Once it's connected, the site's current address sends visitors to the new one, which works only once the records are in place. Have your registrar's DNS settings open, and add the records straight away.";
453
+ readonly "domain.connect": "Connect domain";
454
+ readonly "domain.connecting": "Connecting…";
455
+ readonly "domain.message": "Use the domain {domain}";
456
+ readonly "domain.records.title": "1. Add these records at your registrar";
457
+ readonly "domain.records.hint": "Your registrar is where you bought the domain. In its DNS settings, add each record below. Delete any other A, AAAA or CNAME records with the same names, such as a page the registrar shows on new domains.";
458
+ readonly "domain.records.type": "Type";
459
+ readonly "domain.records.name": "Name";
460
+ readonly "domain.records.value": "Value";
461
+ readonly "domain.records.state": "Found";
462
+ readonly "domain.records.ok": "In place";
463
+ readonly "domain.records.missing": "Not there yet";
464
+ readonly "domain.records.wrong": "Something else is there: {found}";
465
+ readonly "domain.records.optional": "optional";
466
+ readonly "domain.purpose.site": "Points the domain at the site.";
467
+ readonly "domain.purpose.verification": "Proves to {host} that the domain is yours. Leave it in place.";
468
+ readonly "domain.purpose.www": "Sends www. to the site too.";
469
+ readonly "domain.guides": "How to add records at:";
470
+ readonly "domain.cloudflare": "On Cloudflare, set each record's proxy status to DNS only, or {host} can't set up HTTPS for the domain.";
471
+ readonly "domain.host.title": "2. {host} checks the domain and sets up HTTPS";
472
+ readonly "domain.host.unverified": "Waiting for {host} to find the record that proves the domain is yours.";
473
+ readonly "domain.host.pending": "Waiting for the HTTPS certificate, which {host} asks for once the records are in place. It can take up to a day.";
474
+ readonly "domain.host.ready": "The HTTPS certificate is ready.";
475
+ readonly "domain.host.failed": "The HTTPS certificate couldn't be set up. Check the records, then remove the domain and connect it again.";
476
+ readonly "domain.site.title": "3. The site opens at {address}";
477
+ readonly "domain.site.waiting": "Not yet. New records can take from a few minutes to a day to reach everyone.";
478
+ readonly "domain.site.ok": "It does.";
479
+ readonly "domain.secure": "Send everyone to {address}";
480
+ readonly "domain.secureHint": "Visitors always get the secure address, and the site's old address sends them there too.";
481
+ readonly "domain.done": "Done: the site is at {address}.";
482
+ readonly "domain.check": "Check again";
483
+ readonly "domain.checking": "Checking…";
484
+ readonly "domain.checkFailed": "Couldn't check the records just now. Try again in a moment.";
485
+ readonly "domain.remove": "Remove domain";
486
+ readonly "domain.removeTitle": "Remove {domain}?";
487
+ readonly "domain.removeBody": "The site goes back to its address on {host}. Delete the records at your registrar afterwards, so nobody else can use the domain for a site.";
488
+ readonly "domain.removeMessage": "Stop using the domain {domain}";
489
+ readonly "domain.error.not-allowed": "Your account can't change the site's {host} Pages settings. Ask one of the site's owners to make you an owner too, or to connect the domain for you.";
490
+ readonly "domain.error.taken": "Another site on {host} already uses this domain. If it's yours too, remove it there first.";
491
+ readonly "domain.error.invalid": "{host} doesn't accept this domain.";
492
+ readonly "domain.error.not-ready": "The HTTPS certificate isn't ready yet. Try again in a while.";
493
+ readonly "domain.error.other": "Something went wrong.";
494
+ readonly "owner.token.title": "Use an owner token";
495
+ readonly "owner.token.intro": "Inviting and removing editors, and connecting a domain, need more access on {host} than signing in has. Create a second token for them. It's kept only until you close this tab, and stops working after a day; you can delete it on {host} sooner.";
496
+ readonly "owner.token.create": "Create an owner token on {host}";
497
+ readonly "owner.token.chooseSite": "If {host} asks what the token can access, choose only this site.";
498
+ readonly "owner.token.paste": "Copy the token and paste it here:";
499
+ readonly "owner.token.label": "Owner token";
500
+ readonly "owner.token.use": "Use this token";
501
+ readonly "owner.token.checking": "Checking…";
502
+ readonly "owner.token.error": "That token can't manage this site. Check that it was made by one of the site's owners, that it can access this site, and that the whole token was copied.";
503
+ readonly "owner.token.active": "This tab is using an owner token.";
504
+ readonly "owner.token.forget": "Stop using it";
505
+ readonly "settings.tab.editors": "Editors";
506
+ readonly "settings.tab.updates": "Updates";
507
+ readonly "updates.intro": "Goodfellow, the software the site runs on, gets fixes and new releases. Fixes install on their own each night, and only once the site has been checked to still build with them.";
508
+ readonly "updates.local": "Updates are shown in the published site's admin panel, where you sign in with GitHub or GitLab.";
509
+ readonly "updates.demo": "Updates aren't installed in a demo.";
510
+ readonly "updates.loading": "Checking for updates…";
511
+ readonly "updates.current": "This site uses Goodfellow {version}.";
512
+ readonly "updates.unknownVersion": "This site's Goodfellow release couldn't be found.";
513
+ readonly "updates.missing": "This site's build setup doesn't install updates on its own, for example because it was made before it could, or because it's published with Vercel. A developer can add it, as the documentation explains.";
514
+ readonly "updates.needsSetup": "Automatic updates aren't turned on yet. They need {host} to let the site's build publish the update, and to run it each night.";
515
+ readonly "updates.enable": "Turn on automatic updates";
516
+ readonly "updates.fixes.title": "Fixes";
517
+ readonly "updates.fixes.ready": "Fixes up to Goodfellow {version} are ready. They install on their own tonight, or you can install them now.";
518
+ readonly "updates.fixes.readyPaused": "Fixes up to Goodfellow {version} are ready. Automatic fixes are turned off, so they're only installed if you install them now.";
519
+ readonly "updates.fixes.now": "Install fixes now";
520
+ readonly "updates.fixes.none": "The site has every fix for its release.";
521
+ readonly "updates.newer.title": "Goodfellow {version} is out";
522
+ readonly "updates.newer.body": "Newer releases can change how some things work, so they're only installed when one of the site's owners chooses to. Read what's new first.";
523
+ readonly "updates.newer.whatsNew": "What's new";
524
+ readonly "updates.newer.install": "Update to {version}";
525
+ readonly "updates.newer.onlyOwners": "Only the site's owners can install a newer release.";
526
+ readonly "updates.automatic.label": "Install fixes automatically each night";
527
+ readonly "updates.automatic.hint": "Turn this off to keep the site on the release it has now, for example while something an update changed is looked into. Fixes are then only installed when someone installs them here.";
528
+ readonly "updates.automatic.onlyOwners": "Only the site's owners can change this.";
529
+ readonly "updates.automatic.turnOff": "Turn off automatic fixes";
530
+ readonly "updates.automatic.turnOn": "Turn on automatic fixes";
531
+ readonly "updates.back.title": "Something stopped working?";
532
+ readonly "updates.back.body": "If something stopped working when Goodfellow {current} was installed, you can go back to {version}. The site is checked to still build with it first. Updates won't install {current} again, but will install fixes that come after it.";
533
+ readonly "updates.back.button": "Go back to {version}";
534
+ readonly "updates.back.confirm": "Go back to Goodfellow {version}? It takes a few minutes.";
535
+ readonly "updates.skipped.title": "Releases that won't be installed";
536
+ readonly "updates.skipped.body": "The site went back from these releases, so updates don't install them.";
537
+ readonly "updates.skipped.allow": "Allow {version} again";
538
+ readonly "updates.skipped.allowMessage": "Allow Goodfellow {version} again";
539
+ readonly "updates.started": "The update has started. It takes a few minutes, and this page shows how it went.";
540
+ readonly "updates.last.title": "Last update";
541
+ readonly "updates.last.none": "No update has run yet.";
542
+ readonly "updates.last.running": "An update is running now. It takes a few minutes.";
543
+ readonly "updates.last.updated": "On {date}, Goodfellow {version} was installed.";
544
+ readonly "updates.last.updatedSome": "On {date}, an update was installed.";
545
+ readonly "updates.last.wentBack": "On {date}, the site went back to Goodfellow {version}.";
546
+ readonly "updates.last.paused": "On {date}, automatic fixes were turned off, so nothing was installed.";
547
+ readonly "updates.last.upToDate": "On {date}, there was nothing new to install.";
548
+ readonly "updates.last.failed": "On {date}, the update didn't work, so nothing changed and the site stayed as it was.";
549
+ readonly "updates.last.unknown": "An update ran on {date}.";
550
+ readonly "updates.last.details": "See the details on {host}";
551
+ readonly "updates.failed.build": "The site didn't build with Goodfellow {version}; a developer may need to look at the details.";
552
+ readonly "updates.failed.install": "Its packages couldn't be installed. The next night tries again.";
553
+ readonly "updates.failed.blocks": "One of the site's blocks couldn't be updated.";
554
+ readonly "updates.failed.publish": "Someone published at the same time. The next night tries again.";
555
+ readonly "updates.kept": "Someone changed these files of the site's blocks, so the update left them as they were. A developer can compare them with the new versions:";
556
+ readonly "updates.error.load": "The updates couldn't be checked. Check your connection and try again.";
557
+ readonly "updates.error.not-allowed": "Your account can't do that on {host}. Ask one of the site's owners.";
558
+ readonly "updates.error.missing": "This site's build setup doesn't install updates, so there's nothing to run.";
559
+ readonly "updates.error.save": "The change couldn't be saved. Try again in a moment.";
560
+ readonly "updates.error.other": "Something went wrong. Try again in a moment.";
561
+ readonly "editors.intro": "The people who can edit this site.";
562
+ readonly "editors.roles": "Editors can change and publish everything in the admin panel. Owners can also invite and remove editors, and connect a domain.";
563
+ readonly "editors.local": "Editors are invited in the published site's admin panel, where you sign in with GitHub or GitLab.";
564
+ readonly "editors.demo": "Editors can't be invited in a demo.";
565
+ readonly "editors.loading": "Loading editors…";
566
+ readonly "editors.onlyOwners": "Only the site's owners can invite and remove editors.";
567
+ readonly "editors.cantPublish": "Editors can't publish yet: {host} only lets owners publish to the site until it's told to let editors publish too.";
568
+ readonly "editors.letPublish": "Let editors publish";
569
+ readonly "editors.person": "Person";
570
+ readonly "editors.role": "Can";
571
+ readonly "editors.roleFor": "What {name} can do";
572
+ readonly "editors.actions": "Actions";
573
+ readonly "editors.role.owner": "Owner";
574
+ readonly "editors.role.editor": "Editor";
575
+ readonly "editors.role.viewer": "Can't publish";
576
+ readonly "editors.you": "You";
577
+ readonly "editors.invited": "Invited, hasn't accepted yet";
578
+ readonly "editors.inherited": "Through a group on {host}";
579
+ readonly "editors.remove": "Remove";
580
+ readonly "editors.withdraw": "Withdraw invitation";
581
+ readonly "editors.removeTitle": "Remove {name}?";
582
+ readonly "editors.removeBody": "They won't be able to edit the site any more. Their account on {host} stays as it is.";
583
+ readonly "editors.withdrawTitle": "Withdraw the invitation to {name}?";
584
+ readonly "editors.withdrawBody": "The invitation stops working. You can invite them again later.";
585
+ readonly "editors.invite.title": "Invite someone";
586
+ readonly "editors.invite.field": "Their {host} username";
587
+ readonly "editors.invite.hint": "They need a {host} account. {host} emails them an invitation, which they accept before they can sign in here.";
588
+ readonly "editors.invite.fieldEmail": "Their email address or {host} username";
589
+ readonly "editors.invite.hintEmail": "With an email address, {host} emails them an invitation, and they make an account if they don't have one.";
590
+ readonly "editors.invite.submit": "Invite";
591
+ readonly "editors.error.load": "The editors couldn't be loaded. Check your connection and try again.";
592
+ readonly "editors.error.not-allowed": "You can't change who edits the site.";
593
+ readonly "editors.error.not-found": "There's no {host} account with that name. Check the spelling.";
594
+ readonly "editors.error.invalid": "That isn't a username or email address that {host} accepts.";
595
+ readonly "editors.error.already": "They already edit the site, or have been invited.";
596
+ readonly "editors.error.other": "Something went wrong. Try again in a moment.";
597
+ readonly "general.siteTitle": "Site name";
598
+ readonly "general.description": "Description";
599
+ readonly "general.descriptionHint": "Shown by search engines when a page doesn't have its own description.";
600
+ readonly "general.url": "Site address";
601
+ readonly "general.urlHint": "The full public address, such as https://example.org. Used for search engines and link previews.";
602
+ readonly "general.externalLinksInNewTab": "Open links to other sites in a new tab";
603
+ readonly "general.externalLinksInNewTabHint": "Applies to every link to another site: menus, buttons and text. Links to this site's own pages open in the same tab.";
604
+ readonly "general.language": "Language code";
605
+ readonly "general.languageHint": "Such as en, es or fr.";
606
+ readonly "general.timeZone": "Time zone";
607
+ readonly "general.timeZoneHint": "The time zone events' times are in. Calendars show them in it, and visitors' calendars move them to their own.";
608
+ readonly "general.timeZoneNone": "Not set: times are shown as they're written";
609
+ readonly "general.timeZoneUseMine": "Use {zone}";
610
+ readonly "general.titleTemplate": "Browser tab title";
611
+ readonly "general.titleTemplateHint": '%s is replaced by the page title, so "%s | My site" shows "About | My site".';
612
+ readonly "general.favicon": "Browser tab icon";
613
+ readonly "general.logo": "Logo";
614
+ readonly "general.logoAlt": "Logo description";
615
+ readonly "general.socialImage": "Image when shared on social media";
616
+ readonly "general.contact": "Contact details";
617
+ readonly "general.contactHint": "Shown wherever a Contact details block is placed, such as the footer.";
618
+ readonly "general.address": "Address";
619
+ readonly "general.phone": "Phone";
620
+ readonly "general.email": "Email";
621
+ readonly "forms.title": "Forms";
622
+ readonly "forms.hint": "Where answers to the site's forms go. The form service emails them to you: they're never kept with the site's pages.";
623
+ readonly "forms.service": "Form service";
624
+ readonly "forms.service.web3forms": "Web3Forms: free for 250 answers a month, with no account";
625
+ readonly "forms.service.formspree": "Formspree";
626
+ readonly "forms.service.other": "Another service";
627
+ readonly "forms.accessKey": "Web3Forms access key";
628
+ readonly "forms.accessKeyHint": "On Web3Forms' site, enter the email address answers should go to. Web3Forms emails you a key: paste it here.";
629
+ readonly "forms.accessKeyLink": "Get an access key from Web3Forms";
630
+ readonly "forms.captcha": "Ask visitors to show they aren't robots (hCaptcha)";
631
+ readonly "forms.captchaHint": "Adds Web3Forms' hCaptcha and its script to pages with a form. To turn away answers without it, also turn hCaptcha on for the form in a Web3Forms account.";
632
+ readonly "forms.formspree": "Formspree form address";
633
+ readonly "forms.formspreeHint": "Make a form in Formspree and copy its address, such as https://formspree.io/f/xyzabcde. On Formspree's free plan, visitors see Formspree's own thank-you page.";
634
+ readonly "forms.address": "Address forms send answers to";
635
+ readonly "forms.addressHint": "The service's address for forms, starting with https://. Forms send the thank-you page's address as _next, the subject as _subject, and a hidden _gotcha field that only robots fill in, as Formspree, FormSubmit and Formcarry expect.";
636
+ readonly "forms.error.key": "This isn't a Web3Forms access key. Copy it from Web3Forms' email: it looks like 0b5c4f7e-1a2b-4c3d-8e9f-0123456789ab.";
637
+ readonly "forms.error.formspree": "This isn't a Formspree form's address. It looks like https://formspree.io/f/xyzabcde.";
638
+ readonly "forms.error.address": "The address must be a full address starting with https://.";
639
+ readonly "theme.colors": "Colors";
640
+ readonly "theme.fonts": "Fonts";
641
+ readonly "theme.fontsHint": "Choose from Google Fonts. Site default uses each visitor's standard font.";
642
+ readonly "font.default": "Site default";
643
+ readonly "font.defaultHint": "Visitor's standard font";
644
+ readonly "font.search": "Search fonts";
645
+ readonly "font.searchHint": "Type to search Google Fonts, then use the arrow keys and Enter to choose.";
646
+ readonly "font.loading": "Loading fonts…";
647
+ readonly "font.noMatch": "No fonts match “{query}”.";
648
+ readonly "font.category.sans-serif": "Sans serif";
649
+ readonly "font.category.serif": "Serif";
650
+ readonly "font.category.display": "Display";
651
+ readonly "font.category.handwriting": "Handwriting";
652
+ readonly "font.category.monospace": "Monospace";
653
+ readonly "theme.headingFont": "Headings";
654
+ readonly "theme.bodyFont": "Text";
655
+ readonly "theme.radius": "Corner rounding";
656
+ readonly "theme.radiusHint": "Such as 0.5rem, or 0 for square corners.";
657
+ readonly "theme.color.background": "Background";
658
+ readonly "theme.color.foreground": "Text";
659
+ readonly "theme.color.primary": "Main color";
660
+ readonly "theme.color.primaryForeground": "Text on main color";
661
+ readonly "theme.color.secondary": "Second color";
662
+ readonly "theme.color.secondaryForeground": "Text on second color";
663
+ readonly "theme.color.muted": "Subtle background";
664
+ readonly "theme.color.mutedForeground": "Subtle text";
665
+ readonly "theme.color.accent": "Highlight";
666
+ readonly "theme.color.accentForeground": "Text on highlight";
667
+ readonly "theme.color.border": "Borders";
668
+ readonly "theme.default": "Default";
669
+ readonly "theme.pickColor": "Choose a color for {name}";
670
+ readonly "menus.intro": "Menus are lists of links. Show one anywhere with the Menu block, using its name.";
671
+ readonly "menus.empty": "There are no menus yet.";
672
+ readonly "menus.add": "Add menu";
673
+ readonly "menus.newName": "New menu name";
674
+ readonly "menus.nameInvalid": "Use lowercase letters, numbers and hyphens, and a name no other menu uses.";
675
+ readonly "menus.deleteMenu": "Delete menu";
676
+ readonly "menus.addLink": "Add link";
677
+ readonly "menus.addSublink": "Add link below this one";
678
+ readonly "menus.label": "Label";
679
+ readonly "menus.href": "Link to";
680
+ readonly "menus.moveUp": "Move up";
681
+ readonly "menus.moveDown": "Move down";
682
+ readonly "menus.remove": "Remove";
683
+ readonly "menus.newLink": "New link";
684
+ readonly "redirects.intro": "Send visitors from an old address to a new one, such as when a page has moved or this site replaced an older one. Search engines move the old address's place in their results to the new one.";
685
+ readonly "redirects.empty": "There are no redirects yet.";
686
+ readonly "redirects.from": "Old address";
687
+ readonly "redirects.to": "Send visitors to";
688
+ readonly "redirects.add": "Add redirect";
689
+ readonly "redirects.remove": "Remove";
690
+ readonly "redirects.message": "Message while visitors are sent on";
691
+ readonly "redirects.messageHint": "Shown at an old address for a moment, or for good in browsers without JavaScript. {placeholder} becomes a link to where visitors are going. Leave it empty for the message shown here.";
692
+ readonly "redirects.unused": "A page has this address, so visitors see the page instead. Remove the redirect, or move the page.";
693
+ readonly "redirects.problem.noFrom": "Add the old address, such as /about-us.";
694
+ readonly "redirects.problem.badFrom": "This isn't an address on this site. Start with /, such as /about-us, or paste the old page's full address.";
695
+ readonly "redirects.problem.query": "Addresses with a ? in them can't be redirected, since the site can't tell them apart from the address before the ?.";
696
+ readonly "redirects.problem.home": "The home page can't be redirected.";
697
+ readonly "redirects.problem.reserved": "This address is used by the site itself, so it can't be redirected.";
698
+ readonly "redirects.problem.noTo": "Add where to send visitors, such as /about.";
699
+ readonly "redirects.problem.badTo": "Send visitors to a page on this site, starting with /, or to another website's address, starting with https://.";
700
+ readonly "redirects.problem.loop": "This sends visitors back to the same address.";
701
+ readonly "redirects.problem.duplicate": "Another redirect is from the same address. Remove one of them.";
702
+ readonly "css.intro": "CSS here applies to every page and overrides the blocks' own styles. Tailwind's @apply works too.";
703
+ readonly "css.label": "Custom CSS";
704
+ readonly "code.editorHint": "Tab indents, and suggestions appear as you type. Press Escape, then Tab, to leave the editor. Ctrl+F finds and replaces.";
705
+ readonly "code.intro": "Code from services such as analytics or site verification, added to every page of the site. It never runs in the admin panel, so check it on the site once it's published. Paste only code you trust: it can change anything on the site.";
706
+ readonly "code.head": "In the page head";
707
+ readonly "code.headHint": "Script, style, link, meta and noscript tags, such as the ones Google Analytics gives you.";
708
+ readonly "code.body": "At the end of the page";
709
+ readonly "code.bodyHint": "Any HTML, such as a chat widget, added just before the end of every page.";
710
+ readonly "code.error.text": 'The code in the page head has text outside a tag: "{text}". Only tags such as <script> and <meta> can go there.';
711
+ readonly "code.error.tag": 'A <{tag}> tag can\'t go in the page head. Put it in "At the end of the page" instead.';
712
+ readonly "code.error.unclosed": "A {tag} tag in the page head isn't closed.";
713
+ };
714
+ type StringKey = keyof typeof defaultStrings;
715
+ type Strings = Record<StringKey, string>;
716
+ //#endregion
717
+ //#region src/admin.d.ts
718
+ interface AdminProps {
719
+ /** The site's `goodfellow.config.tsx`. */
720
+ config: GoodfellowConfig;
721
+ /**
722
+ * Where the site's files are read from and published to, without signing in.
723
+ * Used by `goodfellow dev`. Otherwise the admin panel signs in to `host`. In a
724
+ * demo (the config's `demo`), it's only read from, and changes stay in the browser.
725
+ */
726
+ store?: ContentStore;
727
+ /** The git host the site is stored on. Defaults to the config's `backend`. */
728
+ host?: GitHost;
729
+ preview: PreviewOptions;
730
+ /** The live site's address, for "View" links. Defaults to `/`. */
731
+ siteUrl?: string;
732
+ /** Replaces any of the admin panel's text, for rewording or translation. */
733
+ strings?: Partial<Strings>;
734
+ /**
735
+ * Where Goodfellow's block registry is, as `https://…/{name}.json`. Defaults to the
736
+ * release this admin panel was built with; the development servers serve their own copy.
737
+ */
738
+ registry?: string;
739
+ }
740
+ /** The admin panel. Render it on its own page, such as `/admin`. */
741
+ export declare function Admin({ config, store, host, preview, siteUrl, strings, registry }: AdminProps): import("react").JSX.Element;
742
+ /** Renders the admin panel into an element. */
743
+ export declare function mountAdmin(element: Element, props: AdminProps): void;
744
+ //#endregion
745
+ export type { AdminProps, PreviewOptions, StringKey, Strings };