@object-ui/i18n 17.6.0 → 18.0.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.
- package/CHANGELOG.md +5408 -0
- package/README.md +255 -13
- package/dist/LocalizationContext.d.ts +32 -9
- package/dist/LocalizationContext.js +32 -10
- package/dist/builtinAggregateLabels.d.ts +40 -0
- package/dist/builtinAggregateLabels.js +23 -0
- package/dist/currency.d.ts +27 -3
- package/dist/currency.js +28 -4
- package/dist/fallbackInterpolation.d.ts +79 -0
- package/dist/fallbackInterpolation.js +124 -0
- package/dist/i18n.d.ts +27 -1
- package/dist/i18n.js +99 -16
- package/dist/index.d.ts +8 -13
- package/dist/index.js +45 -17
- package/dist/locales/ar.d.ts +1504 -188
- package/dist/locales/ar.js +1711 -281
- package/dist/locales/de.d.ts +1080 -188
- package/dist/locales/de.js +1248 -261
- package/dist/locales/en.d.ts +1141 -249
- package/dist/locales/en.js +1714 -295
- package/dist/locales/es.d.ts +1186 -188
- package/dist/locales/es.js +1350 -255
- package/dist/locales/fr.d.ts +1186 -188
- package/dist/locales/fr.js +1351 -258
- package/dist/locales/index.d.ts +11940 -2033
- package/dist/locales/index.js +48 -9
- package/dist/locales/ja.d.ts +1080 -188
- package/dist/locales/ja.js +1240 -254
- package/dist/locales/ko.d.ts +1080 -188
- package/dist/locales/ko.js +1244 -258
- package/dist/locales/pt.d.ts +1186 -188
- package/dist/locales/pt.js +1350 -255
- package/dist/locales/registry.d.ts +102 -0
- package/dist/locales/registry.js +220 -0
- package/dist/locales/rtl.d.ts +24 -0
- package/dist/locales/rtl.js +26 -0
- package/dist/locales/ru.d.ts +1292 -188
- package/dist/locales/ru.js +1479 -272
- package/dist/locales/zh.d.ts +1144 -252
- package/dist/locales/zh.js +1245 -259
- package/dist/pickLocalized.d.ts +30 -0
- package/dist/pickLocalized.js +39 -0
- package/dist/provider.d.ts +101 -12
- package/dist/provider.js +335 -50
- package/dist/translateFn.d.ts +29 -0
- package/dist/translateFn.js +8 -0
- package/dist/useDisplayLocale.d.ts +11 -0
- package/dist/useDisplayLocale.js +11 -0
- package/dist/useObjectLabel.d.ts +143 -100
- package/dist/useObjectLabel.js +129 -82
- package/dist/useSafeTranslation.js +40 -42
- package/dist/utils/first-day-of-week.d.ts +71 -0
- package/dist/utils/first-day-of-week.js +61 -0
- package/dist/utils/formatting.d.ts +23 -1
- package/dist/utils/formatting.js +34 -5
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/spec-formatters.d.ts +13 -23
- package/dist/utils/spec-formatters.js +41 -2
- package/dist/utils/spec-translations.d.ts +16 -3
- package/dist/utils/spec-translations.js +52 -13
- package/package.json +12 -6
package/dist/locales/en.js
CHANGED
|
@@ -17,7 +17,7 @@ const en = {
|
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
// objectui#2600 B5 — capability picker scope group headers (labels come from
|
|
20
|
-
// the
|
|
20
|
+
// the capability registry; only these group titles are UI strings).
|
|
21
21
|
capability: {
|
|
22
22
|
group: {
|
|
23
23
|
platform: 'Platform',
|
|
@@ -30,38 +30,13 @@ const en = {
|
|
|
30
30
|
manage_users: 'Manage Users',
|
|
31
31
|
manage_org_users: 'Manage Organization Users',
|
|
32
32
|
manage_metadata: 'Manage Metadata',
|
|
33
|
+
manage_mailboxes: 'Manage Mailboxes',
|
|
33
34
|
manage_platform_settings: 'Manage Platform Settings',
|
|
34
35
|
setup_access: 'Setup Access',
|
|
35
36
|
setup_write: 'Write Settings',
|
|
36
37
|
studio_access: 'Studio Access',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// objectui#3546 slice six — the read-only facet summary + Studio deep-link a
|
|
40
|
-
// `sys_permission_set` record shows for its six authorization facets
|
|
41
|
-
// (ADR-0056 P1, plugin-detail's PermissionFacetLink).
|
|
42
|
-
//
|
|
43
|
-
// The four count labels are plural families. `_one` is the singular; the BASE
|
|
44
|
-
// key (no suffix) is the form every OTHER CLDR plural category resolves to,
|
|
45
|
-
// which is what keeps `ru` (few/many) and `ar` (two/few/many/zero) in their own
|
|
46
|
-
// language instead of falling through to English — i18next only looks up the
|
|
47
|
-
// one suffix a language's rules ask for, and falls back to the base key when
|
|
48
|
-
// that suffix is absent. `perm-home-namespace-3546.test.tsx` renders every
|
|
49
|
-
// language at counts 1/2/3/5/11/21/100 to hold this.
|
|
50
|
-
perm: {
|
|
51
|
-
facet: {
|
|
52
|
-
none: 'None',
|
|
53
|
-
more: '+{{count}} more',
|
|
54
|
-
objects: '{{count}} objects',
|
|
55
|
-
objects_one: '{{count}} object',
|
|
56
|
-
fields: '{{count}} field rules',
|
|
57
|
-
fields_one: '{{count}} field rule',
|
|
58
|
-
rls: '{{count}} RLS policies',
|
|
59
|
-
rls_one: '{{count}} RLS policy',
|
|
60
|
-
tabs: '{{count}} tab rules',
|
|
61
|
-
tabs_one: '{{count}} tab rule',
|
|
62
|
-
adminScope: 'Delegated admin configured',
|
|
63
|
-
designInStudio: 'Design in Studio →',
|
|
64
|
-
designInStudioHint: 'Design in Studio',
|
|
38
|
+
manage_sharing: 'Manage Sharing',
|
|
39
|
+
view_all_audit_log: 'View All Audit Log',
|
|
65
40
|
},
|
|
66
41
|
},
|
|
67
42
|
lookup: {
|
|
@@ -80,7 +55,8 @@ const en = {
|
|
|
80
55
|
selectFirst: 'Select {{fields}} first',
|
|
81
56
|
selectRecord: 'Select record',
|
|
82
57
|
recordCount: '{{count}} records',
|
|
83
|
-
|
|
58
|
+
recordCount_one: '{{count}} record',
|
|
59
|
+
recordCount_other: '{{count}} records',
|
|
84
60
|
pageOf: 'Page {{current}} of {{total}}',
|
|
85
61
|
filters: 'Filters',
|
|
86
62
|
clear: 'Clear',
|
|
@@ -137,17 +113,30 @@ const en = {
|
|
|
137
113
|
closeChat: 'Close chat',
|
|
138
114
|
closePanel: 'Close panel',
|
|
139
115
|
resizeDrawer: 'Resize drawer',
|
|
140
|
-
// Count badge on a tab / section header.
|
|
141
|
-
//
|
|
116
|
+
// Count badge on a tab / section header. An i18next count family
|
|
117
|
+
// (objectui#11445): the badge passes `count` and i18next picks the slot
|
|
118
|
+
// each pack's CLDR rules select.
|
|
142
119
|
itemCount: '{{count}} items',
|
|
143
|
-
|
|
120
|
+
itemCount_one: '{{count}} item',
|
|
121
|
+
itemCount_other: '{{count}} items',
|
|
144
122
|
toggleSidebar: 'Toggle sidebar',
|
|
123
|
+
breadcrumb: 'Breadcrumb',
|
|
145
124
|
package: 'Package',
|
|
146
125
|
done: 'Done',
|
|
147
126
|
editInStudio: 'Edit in studio',
|
|
148
127
|
record: 'Record',
|
|
149
128
|
retry: 'Retry',
|
|
150
129
|
printDialogHint: 'Opens your browser’s print dialog (not a PDF export)',
|
|
130
|
+
// The non-grid row ceiling's footnote (objectui#7210). Two keys because
|
|
131
|
+
// there are two conditions: a reported `total` states the fact with BOTH
|
|
132
|
+
// numbers, a missing one cannot name how many. Kept terse deliberately —
|
|
133
|
+
// this copy is eagerly loaded, and since objectui#7399 these bytes are
|
|
134
|
+
// budgeted by the `i18n-locales` chunk, not `framework`. ⛔ That ceiling's
|
|
135
|
+
// headroom is deliberately NOT restated here — it moves on every
|
|
136
|
+
// re-baseline, and the figure that was here went stale.
|
|
137
|
+
// `pnpm check:eager-closure` prints it.
|
|
138
|
+
rowCeilingNote: 'Showing the first {{shown}} of {{total}} records. Narrow the filter.',
|
|
139
|
+
rowCeilingNoteUnknownTotal: 'Showing the first {{shown}} records. Narrow the filter.',
|
|
151
140
|
},
|
|
152
141
|
actions: {
|
|
153
142
|
decisionOutput: {
|
|
@@ -159,6 +148,38 @@ const en = {
|
|
|
159
148
|
acknowledge: 'I have saved this',
|
|
160
149
|
copyAll: 'Copy all',
|
|
161
150
|
},
|
|
151
|
+
// The refusal notice for an action whose `autoTrigger` its own declared
|
|
152
|
+
// `visible` gate outranks (objectui#4191) — the deep link or host asked
|
|
153
|
+
// for it, but the author hid it on this surface.
|
|
154
|
+
notAvailableHere: '"{{action}}" is not available on the current page.',
|
|
155
|
+
// The reason a record action greyed out by its declared `disabled`
|
|
156
|
+
// predicate gives on hover, on focus and as its accessible description
|
|
157
|
+
// (objectui#11811): the generic one, since the action spec carries no
|
|
158
|
+
// author-written reason. Not `notAvailableHere` — that one is about the
|
|
159
|
+
// page, this one about the record.
|
|
160
|
+
notAvailableForRecord: 'Not available for this record',
|
|
161
|
+
// The success toast the action runner shows when no `outcomeMessages`
|
|
162
|
+
// entry applies to the answer and the action declares no `successMessage`;
|
|
163
|
+
// the server's message plays no part (objectui#11344). It is the one
|
|
164
|
+
// success-toast text the runner writes itself (objectui#10900).
|
|
165
|
+
completedSuccessfully: 'Action completed successfully',
|
|
166
|
+
// The runner's other own text (objectui#10969): the error fallbacks when no
|
|
167
|
+
// readable error message reached it, and the Undo label it hands the toast
|
|
168
|
+
// handler for an undoable success toast.
|
|
169
|
+
failed: 'Action failed',
|
|
170
|
+
parallelFailed: 'One or more parallel actions failed',
|
|
171
|
+
undo: 'Undo',
|
|
172
|
+
// The confirmation toast after that Undo has run — written by the console's
|
|
173
|
+
// two undo handlers (`useConsoleActionRuntime` and `RecordDetailView`), not
|
|
174
|
+
// by the runner (objectui#11056).
|
|
175
|
+
undone: 'Change undone',
|
|
176
|
+
// The console's global Ctrl+Z / Ctrl+Shift+Z toasts, raised by
|
|
177
|
+
// `AppContent`'s `useGlobalUndo` handlers once the operation has been
|
|
178
|
+
// undone / redone (objectui#11080). `{{description}}` is the operation's
|
|
179
|
+
// own description, passed through unchanged; the pack owns the words and
|
|
180
|
+
// the word order around it.
|
|
181
|
+
undoneOperation: 'Undo: {{description}}',
|
|
182
|
+
redoneOperation: 'Redo: {{description}}',
|
|
162
183
|
},
|
|
163
184
|
validation: {
|
|
164
185
|
required: '{{field}} is required',
|
|
@@ -181,8 +202,26 @@ const en = {
|
|
|
181
202
|
},
|
|
182
203
|
form: {
|
|
183
204
|
noPermissionToSave: "You don't have permission to save this record.",
|
|
205
|
+
// The notice a record form shows when every field is locked because the
|
|
206
|
+
// object's affordance for the form's mode is closed for this user
|
|
207
|
+
// (objectui#11000). `{{object}}` is the object's label.
|
|
208
|
+
noPermissionToCreate: "You don't have permission to create {{object}} records. The fields are read-only.",
|
|
209
|
+
noPermissionToEdit: "You don't have permission to edit {{object}} records. The fields are read-only.",
|
|
184
210
|
submitFailed: 'Could not save. Please try again.',
|
|
185
|
-
|
|
211
|
+
uploadInFlight: 'Wait for the upload to finish before saving.',
|
|
212
|
+
// The notice the record form raises when a field's own `visibleWhen` turns
|
|
213
|
+
// it invisible and the form clears the value it held (objectui#8070 names
|
|
214
|
+
// the `6a449fc49` clear). `{{fields}}` is the cleared fields' labels joined
|
|
215
|
+
// with `validation.formInvalidJoiner`. A list after a colon, so no word has
|
|
216
|
+
// to agree with how many fields were cleared.
|
|
217
|
+
clearedOnHide: 'Cleared — no longer applicable given the current values: {{fields}}',
|
|
218
|
+
// The refusal a record form raises at SUBMIT when a field's own
|
|
219
|
+
// `visibleWhen` could not be evaluated (objectui#8069, ADR-0137 D2 as ruled:
|
|
220
|
+
// the client refuses the one rule no server judges). It names the rule and
|
|
221
|
+
// the fields — `{{fields}}` is their labels joined with
|
|
222
|
+
// `validation.formInvalidJoiner` — because the fix is to the metadata, not
|
|
223
|
+
// to anything the person filling the form can type.
|
|
224
|
+
visibleWhenFaulted: "Can't submit: the visibleWhen rule of {{fields}} could not be evaluated. The rule must be fixed before this form can be submitted.",
|
|
186
225
|
removeItem: 'Remove item',
|
|
187
226
|
fieldRequired: 'This field is required',
|
|
188
227
|
invalidFormat: 'Invalid format',
|
|
@@ -197,6 +236,66 @@ const en = {
|
|
|
197
236
|
// only displace it by authoring a `description`, which makes a VISIBLE
|
|
198
237
|
// subtitle appear on every form — so the fallback has to come from here.
|
|
199
238
|
dialogDescriptionFallback: 'Complete the form fields, then submit or cancel.',
|
|
239
|
+
// The hint under a field the caller may read but not write, shown when the
|
|
240
|
+
// field declares no description of its own (objectui#11071).
|
|
241
|
+
deniedDescription: 'You do not have edit access to this field.',
|
|
242
|
+
// The hint under an empty field on a create form whose default the server
|
|
243
|
+
// resolves at insert — a CEL expression or a runtime token the form cannot
|
|
244
|
+
// evaluate, so it leaves the field empty and omits it (objectui#12108).
|
|
245
|
+
// Shown only while the field is empty: a typed value is saved instead.
|
|
246
|
+
serverDefaultHint: 'Set automatically when saved.',
|
|
247
|
+
// The size-limit hint the flat `ObjectForm` appends to a `file` or `image`
|
|
248
|
+
// field's description when the field declares `maxSize` (objectui#12156).
|
|
249
|
+
// `{{size}}` is the formatted limit ("10.0 MB"); only the words translate.
|
|
250
|
+
maxFileSize: 'Max size: {{size}}',
|
|
251
|
+
// The master-detail form's own chrome (objectui#11071): the collection
|
|
252
|
+
// placeholder while its columns resolve, the document totals stack
|
|
253
|
+
// (`{{rate}}` is the header's tax rate), the row editor's title
|
|
254
|
+
// (`{{title}}` is the collection's authored title, or `lineItem` when it
|
|
255
|
+
// has none; `{{row}}` is the 1-based row number), its Apply button, and the
|
|
256
|
+
// sr-only description of the dialog that hosts the form. The verbs `Add`,
|
|
257
|
+
// `Close` and `Saving…` come from `detail.add`, `common.close` and
|
|
258
|
+
// `detail.saving`.
|
|
259
|
+
masterDetail: {
|
|
260
|
+
loadingColumns: 'Loading columns…',
|
|
261
|
+
subtotal: 'Subtotal',
|
|
262
|
+
tax: 'Tax ({{rate}}%)',
|
|
263
|
+
total: 'Total',
|
|
264
|
+
lineItem: 'Line item',
|
|
265
|
+
rowTitle: '{{title}} — row {{row}}',
|
|
266
|
+
applyRow: 'Apply',
|
|
267
|
+
editorDescription: 'Enter the record and its line items, then save.',
|
|
268
|
+
// A collection's configuration hints (objectui#11160): no `childObject`
|
|
269
|
+
// (the twin of `lineItems.noChildObject`, which names the panel), a
|
|
270
|
+
// child schema that failed to load, and no lookup or master_detail
|
|
271
|
+
// field on the child that references the parent. `{{property}}` is a
|
|
272
|
+
// property name and `{{object}}` / `{{parent}}` are object names; each
|
|
273
|
+
// is rendered as code and never translated. `lookup` and
|
|
274
|
+
// `master_detail` are field type names, so every pack keeps them as
|
|
275
|
+
// written.
|
|
276
|
+
noChildObject: 'This collection has no child object configured: set {{property}} to the object whose rows it lists.',
|
|
277
|
+
schemaUnavailable: 'Could not load the schema of {{object}}, so this collection has no columns to show. Check that the object exists and is readable, then reload.',
|
|
278
|
+
noRelationshipField: 'Could not work out how {{object}} links to {{parent}}: no lookup or master_detail field on it references the parent. Set {{property}} on this collection to the field that holds the parent record.',
|
|
279
|
+
},
|
|
280
|
+
// The record page's `record:line_items` panel (objectui#11131): its
|
|
281
|
+
// title when the author declared none. Its Save / Saving… button reads
|
|
282
|
+
// `common.save` / `detail.saving`. `MasterDetailForm` reads `title` too,
|
|
283
|
+
// for a collection that authors no heading (objectui#11145).
|
|
284
|
+
//
|
|
285
|
+
// The rest is the panel's own states (objectui#11145): no parent record
|
|
286
|
+
// bound yet, rows held for another parent, and the two fallbacks for a
|
|
287
|
+
// failed load or save, shown when the server sent no message of its own.
|
|
288
|
+
// Its loading line reads `common.loading`. `noChildObject` is the config
|
|
289
|
+
// hint for a panel with no `childObject`: `{{property}}` is filled with
|
|
290
|
+
// the property name, rendered as code and never translated.
|
|
291
|
+
lineItems: {
|
|
292
|
+
title: 'Line Items',
|
|
293
|
+
saveRecordFirst: 'Save the record first to add line items.',
|
|
294
|
+
notLoaded: 'This record’s line items have not been loaded.',
|
|
295
|
+
loadFailed: 'Failed to load line items',
|
|
296
|
+
saveFailed: 'Failed to save line items',
|
|
297
|
+
noChildObject: 'This panel has no child object configured: set {{property}} to the object whose rows it lists.',
|
|
298
|
+
},
|
|
200
299
|
keepEditing: 'Keep editing',
|
|
201
300
|
discard: 'Discard',
|
|
202
301
|
conflictTitle: 'Save conflict',
|
|
@@ -214,6 +313,26 @@ const en = {
|
|
|
214
313
|
createSuccess: '{{object}} created successfully',
|
|
215
314
|
updateSuccess: '{{object}} updated successfully',
|
|
216
315
|
deleteSuccess: '{{object}} deleted successfully',
|
|
316
|
+
// plugin-form's own feedback chrome (objectui#11039): the success toast
|
|
317
|
+
// a form raises when the author declared no `successMessage` (`created`
|
|
318
|
+
// after a create, `saved` after an edit), the master-detail form's edit
|
|
319
|
+
// toast when the form has a `title` (`{{title}}` is that title), and the
|
|
320
|
+
// console form page's toast after a submit. An authored message always
|
|
321
|
+
// wins; these are only the defaults. The form's loading line and its
|
|
322
|
+
// thank-you panel read `publicForm.loading` / `publicForm.thankYouTitle` /
|
|
323
|
+
// `publicForm.thankYouMessage`, which say the same thing.
|
|
324
|
+
created: 'Created',
|
|
325
|
+
saved: 'Saved',
|
|
326
|
+
savedNamed: '{{title}} saved',
|
|
327
|
+
submitted: 'Submitted',
|
|
328
|
+
// The heading of the panel a form shows when its object schema or its
|
|
329
|
+
// record could not be loaded; the error's own message follows it.
|
|
330
|
+
errorLoading: 'Error loading form',
|
|
331
|
+
// Rides the success toast when a DECLARED `navigateOnSuccess` produced no
|
|
332
|
+
// destination (objectui#5034): the write succeeded, the declared
|
|
333
|
+
// navigation did not happen. `navigateOnSuccess` is the metadata key's
|
|
334
|
+
// name, so every pack keeps it as written.
|
|
335
|
+
navigateRefused: 'The `navigateOnSuccess` destination declared for this form was refused, so the navigation did not happen.',
|
|
217
336
|
fullscreen: {
|
|
218
337
|
title: 'Edit text',
|
|
219
338
|
description: 'Edit the full text value, then save or cancel your changes.',
|
|
@@ -225,6 +344,8 @@ const en = {
|
|
|
225
344
|
fields: {
|
|
226
345
|
relativeDate: {
|
|
227
346
|
overdue: 'Overdue {{count}}d',
|
|
347
|
+
overdue_one: 'Overdue {{count}}d',
|
|
348
|
+
overdue_other: 'Overdue {{count}}d',
|
|
228
349
|
},
|
|
229
350
|
file: {
|
|
230
351
|
dragDropHere: 'Drag & drop files here',
|
|
@@ -241,6 +362,9 @@ const en = {
|
|
|
241
362
|
remove: 'Remove {{name}}',
|
|
242
363
|
exceedsMaxSize: '"{{name}}" exceeds max size ({{max}} MB)',
|
|
243
364
|
uploadFailed: 'Failed to upload "{{name}}": {{error}}',
|
|
365
|
+
uploadIncomplete: 'Upload of "{{name}}" did not complete: no file id was returned, so nothing was saved',
|
|
366
|
+
restricted: 'Restricted file',
|
|
367
|
+
restrictedHint: 'You do not have access to the details of this file',
|
|
244
368
|
},
|
|
245
369
|
image: {
|
|
246
370
|
upload: 'Upload image',
|
|
@@ -251,10 +375,14 @@ const en = {
|
|
|
251
375
|
remove: 'Remove image {{index}}',
|
|
252
376
|
enlarge: 'Enlarge {{name}}',
|
|
253
377
|
preview: 'Image preview',
|
|
378
|
+
cropPreview: 'Image crop preview',
|
|
254
379
|
previous: 'Previous image',
|
|
255
380
|
next: 'Next image',
|
|
256
381
|
counter: '{{current}} / {{total}}',
|
|
257
382
|
},
|
|
383
|
+
percent: {
|
|
384
|
+
slider: 'Percentage',
|
|
385
|
+
},
|
|
258
386
|
richText: {
|
|
259
387
|
format: 'Format: {{format}}',
|
|
260
388
|
basicEditorHint: 'Rich text editor (basic)',
|
|
@@ -274,6 +402,10 @@ const en = {
|
|
|
274
402
|
search: 'Search objects…',
|
|
275
403
|
empty: 'No objects found',
|
|
276
404
|
},
|
|
405
|
+
registryRef: {
|
|
406
|
+
loadFailed: 'The list could not be loaded. You can still type the name.',
|
|
407
|
+
notFound: '{{name}} (not found)',
|
|
408
|
+
},
|
|
277
409
|
recipient: {
|
|
278
410
|
selectTypeFirst: 'Select a recipient type first.',
|
|
279
411
|
loading: 'Loading…',
|
|
@@ -285,6 +417,9 @@ const en = {
|
|
|
285
417
|
selectBusinessUnit: 'Select a business unit',
|
|
286
418
|
selectPosition: 'Select a position',
|
|
287
419
|
selectUnitAndSubordinates: 'Select a business unit',
|
|
420
|
+
selectField: 'Select a user field',
|
|
421
|
+
noUserFields: 'No user fields on this object',
|
|
422
|
+
fieldNotUserTyped: '{{name}} — not a user field',
|
|
288
423
|
},
|
|
289
424
|
filterCondition: {
|
|
290
425
|
selectObjectFirst: 'Select an object first.',
|
|
@@ -295,6 +430,93 @@ const en = {
|
|
|
295
430
|
editAsJson: 'Edit as JSON',
|
|
296
431
|
useVisualBuilder: 'Use visual builder',
|
|
297
432
|
},
|
|
433
|
+
// objectui#6755 — a widget's OWN refusal sentence: `ObjectField`'s
|
|
434
|
+
// unparsable JSON draft, and `LocationField`'s format and range refusals
|
|
435
|
+
// (objectui#6716 / #6714). They were string literals in the widgets, so a
|
|
436
|
+
// zh / ja / ar user who mistyped a coordinate or a JSON blob was told why in
|
|
437
|
+
// English inside a form whose every other word was translated.
|
|
438
|
+
//
|
|
439
|
+
// KEYED, where objectui#4028 DROPPED the five address placeholders in the
|
|
440
|
+
// namespace below — and the difference is what that decision's own comment
|
|
441
|
+
// records about them: "The right example is a function of the address's
|
|
442
|
+
// COUNTRY, not the reader's language", and "Each box here already has a
|
|
443
|
+
// visible label naming exactly what it wants". Neither reaches a refusal
|
|
444
|
+
// sentence: nothing else on the screen says why the edit was refused, and
|
|
445
|
+
// what that sentence must say IS a function of the reader's language. What
|
|
446
|
+
// #4028 does establish for both is the COST — ten pack entries per key,
|
|
447
|
+
// bound from then on by `check:i18n-drift` — and the 2026-08-29 maintainer
|
|
448
|
+
// ruling accepted that cost for these three sentences.
|
|
449
|
+
//
|
|
450
|
+
// Values are byte-identical to the literals they replace (`FIELD_DEFAULTS`
|
|
451
|
+
// in `packages/fields/src/widgets/useFieldTranslation.ts` carries the same
|
|
452
|
+
// three), so English and provider-less rendering are unchanged.
|
|
453
|
+
//
|
|
454
|
+
// `{{detail}}` is the SPEC's own complaint about the refused pair.
|
|
455
|
+
// `LocationField` refuses to restate `LocationValueSchema`'s bounds — a
|
|
456
|
+
// hand-copied range is a second contract — so this key translates the frame
|
|
457
|
+
// and interpolates whatever the schema said.
|
|
458
|
+
object: {
|
|
459
|
+
invalidJson: 'Invalid JSON',
|
|
460
|
+
},
|
|
461
|
+
location: {
|
|
462
|
+
refusedFormat: 'Not saved: enter a latitude, longitude pair (example: 30.2741, 120.1551).',
|
|
463
|
+
refusedRange: 'Not saved: {{detail}}',
|
|
464
|
+
latitude: 'latitude',
|
|
465
|
+
longitude: 'longitude',
|
|
466
|
+
refusedResidueOne: 'Not saved: {{name}} "{{text}}" is not a number. Enter plain decimals (example: 30.2741, 120.1551).',
|
|
467
|
+
refusedResidue: 'Not saved: {{name}} "{{text}}" and {{otherName}} "{{otherText}}" are not numbers. Enter plain decimals (example: 30.2741, 120.1551).',
|
|
468
|
+
},
|
|
469
|
+
// objectui#8148 — the FIFTH refusal sentence of objectui#6755's class, and
|
|
470
|
+
// the only SHARED one. The four above are each ONE widget's; this one is
|
|
471
|
+
// produced by `numberBadInput.tsx` for `NumberField`, `CurrencyField`,
|
|
472
|
+
// `PercentField` and both of `GeolocationField`'s boxes. That last is the
|
|
473
|
+
// sharpest case: it sits beside `LocationField`, whose refusals are keyed
|
|
474
|
+
// right above, so two adjacent coordinate widgets refused bad input in two
|
|
475
|
+
// different languages on the same form.
|
|
476
|
+
//
|
|
477
|
+
// ⭐ `{{example}}` is a HOLE, and that is what keeps decimal numerals out
|
|
478
|
+
// of every pack. Five different values reach this one sentence (`1234`,
|
|
479
|
+
// `1234.56`, `12.5`, `30.2741`, `120.1551`), so keying the example per
|
|
480
|
+
// widget would be five keys times ten packs — and each pack would then
|
|
481
|
+
// hold a decimal it could legitimately re-punctuate, where `1234,56` reads
|
|
482
|
+
// as the `latitude, longitude` PAIR `refusedFormat` above asks for. The
|
|
483
|
+
// widget fills the hole in ASCII; no pack spells a digit.
|
|
484
|
+
//
|
|
485
|
+
// The English value is byte-identical to the literal it replaces
|
|
486
|
+
// (`FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
487
|
+
// carries the same one), so English and provider-less rendering are
|
|
488
|
+
// unchanged.
|
|
489
|
+
// objectui#10567 — the editable date-only face's notice for a stored value
|
|
490
|
+
// written on a day that does not exist, the date-only sibling of
|
|
491
|
+
// `dateTime.impossibleDay` below: an `<input type="date">` can only paint
|
|
492
|
+
// such a value blank, so the widget names the stored string beside it.
|
|
493
|
+
// `FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
494
|
+
// carries the same English value for provider-less rendering.
|
|
495
|
+
date: {
|
|
496
|
+
impossibleDay: 'The stored value "{{value}}" is not a real date. Pick a date to replace it.',
|
|
497
|
+
},
|
|
498
|
+
// objectui#10474 — the editable date-time face's notice for a stored value
|
|
499
|
+
// written on a day that does not exist. The `datetime-local` control can
|
|
500
|
+
// only paint such a value blank, so the widget names the stored string
|
|
501
|
+
// beside it; a blank control alone would hide it (objectui#3127).
|
|
502
|
+
// `FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
503
|
+
// carries the same English value for provider-less rendering.
|
|
504
|
+
dateTime: {
|
|
505
|
+
impossibleDay: 'The stored value "{{value}}" is not a real date. Pick a date and time to replace it.',
|
|
506
|
+
},
|
|
507
|
+
// objectui#12622 — the record form's date picker: its two shortcuts,
|
|
508
|
+
// the clear / calendar buttons' accessible names, and the notice for
|
|
509
|
+
// typed text that names no date ({{format}} is the locale pattern).
|
|
510
|
+
datePicker: {
|
|
511
|
+
today: 'Today',
|
|
512
|
+
tomorrow: 'Tomorrow',
|
|
513
|
+
clear: 'Clear date',
|
|
514
|
+
openCalendar: 'Open calendar',
|
|
515
|
+
invalid: 'Not saved: "{{value}}" is not a date. Type it as {{format}}, or pick one from the calendar.',
|
|
516
|
+
},
|
|
517
|
+
number: {
|
|
518
|
+
badInput: 'Not saved: the text in this box is not a number. Enter a plain decimal (example: {{example}}).',
|
|
519
|
+
},
|
|
298
520
|
// objectui#3342 — the tags widget's input hint, shown while the tag list
|
|
299
521
|
// is empty. The author-declared `field.placeholder` always wins over this.
|
|
300
522
|
tags: {
|
|
@@ -341,10 +563,39 @@ const en = {
|
|
|
341
563
|
// to plural lookup before the base key, and these packs declare the base
|
|
342
564
|
// key only; a sentence whose grammar does not bend on the number is
|
|
343
565
|
// correct at 1 without ten plural entries per pack.
|
|
566
|
+
// objectui#11689 — `BooleanCellRenderer`'s own words (every list
|
|
567
|
+
// surface draws them): the badge a status-named column (`active`,
|
|
568
|
+
// `enabled`, …) shows for `false`, where `{{label}}` is the column label
|
|
569
|
+
// the face is handed, and the completion indicator's accessible names.
|
|
570
|
+
boolean: {
|
|
571
|
+
offBadge: '{{label}} — Off',
|
|
572
|
+
completed: 'Completed',
|
|
573
|
+
notCompleted: 'Not completed',
|
|
574
|
+
},
|
|
344
575
|
textarea: {
|
|
345
576
|
characterCount: 'Character count: {{count}} of {{max}}',
|
|
346
577
|
charactersRemaining: 'Characters remaining: {{count}}',
|
|
347
578
|
},
|
|
579
|
+
// objectui#11131 — the line-items grid's default chrome (`GridField`):
|
|
580
|
+
// its Add button, the read-only grid's empty state, and the list-mode
|
|
581
|
+
// grid's empty state. An authored `addLabel` still wins over `addLine`,
|
|
582
|
+
// and it fills the `{{label}}` hole (`detail.add` when none is authored).
|
|
583
|
+
//
|
|
584
|
+
// objectui#11145 — the rest of that chrome: the column chooser's heading,
|
|
585
|
+
// the computed cell's tooltip, and the row actions. Each row action has
|
|
586
|
+
// one key, read by both its `aria-label` and its `title`. The chooser's
|
|
587
|
+
// button reads `table.columns`, the footer `form.masterDetail.total` and
|
|
588
|
+
// the drag handle `view.dragToReorder`.
|
|
589
|
+
grid: {
|
|
590
|
+
addLine: 'Add line',
|
|
591
|
+
noItems: 'No items',
|
|
592
|
+
noItemsAddHint: 'No items yet — click “{{label}}” to begin.',
|
|
593
|
+
optionalColumns: 'Optional columns',
|
|
594
|
+
computed: 'Computed',
|
|
595
|
+
openRow: 'Open row',
|
|
596
|
+
duplicateRow: 'Duplicate row',
|
|
597
|
+
removeRow: 'Remove row',
|
|
598
|
+
},
|
|
348
599
|
},
|
|
349
600
|
table: {
|
|
350
601
|
rowsPerPage: 'Rows per page',
|
|
@@ -360,10 +611,15 @@ const en = {
|
|
|
360
611
|
selectAllRows: 'Select all rows',
|
|
361
612
|
expandRow: 'Expand row',
|
|
362
613
|
collapseRow: 'Collapse row',
|
|
614
|
+
rowActions: 'Row actions',
|
|
363
615
|
hideColumn: 'Hide column',
|
|
364
616
|
freezeColumn: 'Freeze column',
|
|
365
617
|
unfreezeColumn: 'Unfreeze column',
|
|
366
618
|
pageInfo: 'Page {{current}} of {{total}}',
|
|
619
|
+
firstPage: 'First page',
|
|
620
|
+
previousPage: 'Previous page',
|
|
621
|
+
nextPage: 'Next page',
|
|
622
|
+
lastPage: 'Last page',
|
|
367
623
|
totalRecords: '{{count}} total',
|
|
368
624
|
noResults: 'No results found',
|
|
369
625
|
noResultsHint: 'Try adjusting your filters or search query.',
|
|
@@ -373,8 +629,15 @@ const en = {
|
|
|
373
629
|
open: 'Open',
|
|
374
630
|
search: 'Search…',
|
|
375
631
|
modified: '{{count}} row modified',
|
|
632
|
+
modified_one: '{{count}} row modified',
|
|
633
|
+
modified_other: '{{count}} rows modified',
|
|
634
|
+
saved: '{{count}} row saved',
|
|
635
|
+
saved_one: '{{count}} row saved',
|
|
636
|
+
saved_other: '{{count}} rows saved',
|
|
376
637
|
saveFailed: 'Save failed',
|
|
377
638
|
selected: '{{count}} selected',
|
|
639
|
+
selected_one: '{{count}} selected',
|
|
640
|
+
selected_other: '{{count}} selected',
|
|
378
641
|
edit: 'Edit',
|
|
379
642
|
delete: 'Delete',
|
|
380
643
|
},
|
|
@@ -389,18 +652,32 @@ const en = {
|
|
|
389
652
|
pullToRefresh: 'Pull to refresh',
|
|
390
653
|
refreshing: 'Refreshing…',
|
|
391
654
|
openRecord: 'Open record',
|
|
655
|
+
recordUnavailable: '{{object}} · record unavailable',
|
|
392
656
|
openMenu: 'Open menu',
|
|
393
657
|
bulkSelected: '{{count}} selected',
|
|
658
|
+
bulkSelected_one: '{{count}} selected',
|
|
659
|
+
bulkSelected_other: '{{count}} selected',
|
|
394
660
|
bulkSelectedAllMatches: '{{count}} selected (all matches)',
|
|
395
661
|
bulkClear: 'Clear',
|
|
396
662
|
bulkAllOnPage: 'All {{count}} on this page are selected.',
|
|
663
|
+
bulkAllOnPage_one: '{{count}} record on this page is selected.',
|
|
664
|
+
bulkAllOnPage_other: 'All {{count}} on this page are selected.',
|
|
397
665
|
bulkSelectAllMatching: 'Select all {{count}} matching',
|
|
398
666
|
bulkAllMatchingSelected: 'All {{count}} matching records are selected.',
|
|
667
|
+
bulkActions: 'Bulk actions',
|
|
399
668
|
rowHeight: 'Row height: {{mode}}',
|
|
400
669
|
empty: 'Empty',
|
|
401
670
|
yes: 'Yes',
|
|
402
671
|
no: 'No',
|
|
403
672
|
systemFields: 'System',
|
|
673
|
+
// objectui#10881 — the grouped grid's two refusals: over a data source
|
|
674
|
+
// that cannot answer the group header query, and over rows a host
|
|
675
|
+
// handed in while declaring them one page of more. `queryGroupHeaders`
|
|
676
|
+
// is the member's name and stays untranslated.
|
|
677
|
+
grouping: {
|
|
678
|
+
needsHeaderQuery: 'This view is grouped, but its data source does not implement queryGroupHeaders, so the groups cannot be counted. Remove the grouping to show the records.',
|
|
679
|
+
needsWholeRows: 'Grouping needs every record, but this grid was handed one page of them, so the groups cannot be counted. Hand in every record, or let the grid fetch them from a data source that implements queryGroupHeaders.',
|
|
680
|
+
},
|
|
404
681
|
// Column-footer aggregate prefixes, keyed by the spec's `ColumnSummary`
|
|
405
682
|
// vocabulary (objectui#4024). The footer already formatted its NUMBER
|
|
406
683
|
// through the locale-aware formatter and then put a hardcoded English
|
|
@@ -411,11 +688,18 @@ const en = {
|
|
|
411
688
|
// right-to-left — so a pack owns the whole shape. Same reasoning as
|
|
412
689
|
// `collaboration.resolvedSuffix` below.
|
|
413
690
|
//
|
|
691
|
+
// `pagePattern` is `pattern` for a figure that covers only the page on
|
|
692
|
+
// screen of a larger matched set — the footer's fallback when the server
|
|
693
|
+
// cannot answer the whole set's figure (objectui#12081 item 3). A whole
|
|
694
|
+
// pattern rather than a suffix, for the same reason: where the scope sits
|
|
695
|
+
// is the pack's.
|
|
696
|
+
//
|
|
414
697
|
// `countEmpty`/`percentEmpty` (and the filled pair) deliberately share a
|
|
415
698
|
// word: the trailing `%` is what tells the two families apart on screen,
|
|
416
699
|
// exactly as the renderer's own comment says.
|
|
417
700
|
summary: {
|
|
418
701
|
pattern: '{{label}}: {{value}}',
|
|
702
|
+
pagePattern: '{{label}} (this page): {{value}}',
|
|
419
703
|
count: 'Count',
|
|
420
704
|
countEmpty: 'Empty',
|
|
421
705
|
countFilled: 'Filled',
|
|
@@ -446,8 +730,10 @@ const en = {
|
|
|
446
730
|
dragDrop: 'Drag & drop a CSV or Excel file here, or click to browse',
|
|
447
731
|
browseFiles: 'Browse Files',
|
|
448
732
|
downloadTemplate: 'Download template',
|
|
449
|
-
downloadTemplateHint: 'Get
|
|
733
|
+
downloadTemplateHint: 'Get an Excel file of the columns you can import (required fields marked *), with instructions for filling it in.',
|
|
450
734
|
templateFileName: '{{object}}-import-template',
|
|
735
|
+
templateDownloadFailed: 'Could not download the template. Please try again.',
|
|
736
|
+
templateNotPermitted: 'You do not have permission to create records of this object, so its import template is not available.',
|
|
451
737
|
parsing: 'Parsing…',
|
|
452
738
|
pasteHint: 'or paste (Ctrl/⌘+V) rows copied from Excel or Google Sheets',
|
|
453
739
|
legacyXls: 'Legacy .xls files aren\'t supported — please re-save as .xlsx.',
|
|
@@ -473,6 +759,8 @@ const en = {
|
|
|
473
759
|
typeMismatch: 'Looks like {{type}}',
|
|
474
760
|
autoMatched: 'Auto-matched',
|
|
475
761
|
autoMatchedSummary: 'Auto-matched {{count}} column(s) — review and adjust below.',
|
|
762
|
+
autoMatchedSummary_one: 'Auto-matched {{count}} column — review and adjust below.',
|
|
763
|
+
autoMatchedSummary_other: 'Auto-matched {{count}} columns — review and adjust below.',
|
|
476
764
|
confidence: {
|
|
477
765
|
high: 'High confidence',
|
|
478
766
|
medium: 'Medium confidence',
|
|
@@ -491,7 +779,11 @@ const en = {
|
|
|
491
779
|
mapped: 'Mapped',
|
|
492
780
|
skipped: 'Skipped',
|
|
493
781
|
rowsWithErrors: '{{count}} row(s) with errors',
|
|
782
|
+
rowsWithErrors_one: '{{count}} row with errors',
|
|
783
|
+
rowsWithErrors_other: '{{count}} rows with errors',
|
|
494
784
|
rowsCorrected: '{{count}} row(s) corrected',
|
|
785
|
+
rowsCorrected_one: '{{count}} row corrected',
|
|
786
|
+
rowsCorrected_other: '{{count}} rows corrected',
|
|
495
787
|
clickToFix: '— click a highlighted cell to fix it inline.',
|
|
496
788
|
showingRows: 'Showing {{shown}} of {{total}} rows',
|
|
497
789
|
importing: 'Importing… {{progress}}%',
|
|
@@ -502,12 +794,22 @@ const en = {
|
|
|
502
794
|
cancelImport: 'Cancel import',
|
|
503
795
|
importCancelled: 'Import cancelled',
|
|
504
796
|
resultsTruncated: 'Showing the first {{count}} row results (of {{total}}).',
|
|
797
|
+
resultsTruncated_one: 'Showing the first {{count}} row result (of {{total}}).',
|
|
798
|
+
resultsTruncated_other: 'Showing the first {{count}} row results (of {{total}}).',
|
|
505
799
|
importComplete: 'Import Complete',
|
|
800
|
+
importPartial: 'Import finished with errors',
|
|
801
|
+
importFailed: 'Import failed',
|
|
506
802
|
imported: '{{count}} imported',
|
|
507
803
|
createdCount: '{{count}} created',
|
|
804
|
+
createdCount_one: '{{count}} created',
|
|
805
|
+
createdCount_other: '{{count}} created',
|
|
508
806
|
updatedCount: '{{count}} updated',
|
|
807
|
+
updatedCount_one: '{{count}} updated',
|
|
808
|
+
updatedCount_other: '{{count}} updated',
|
|
509
809
|
skippedCount: '{{count}} skipped',
|
|
510
810
|
moreErrors: '…and {{count}} more errors',
|
|
811
|
+
moreErrors_one: '…and {{count}} more error',
|
|
812
|
+
moreErrors_other: '…and {{count}} more errors',
|
|
511
813
|
downloadFailed: 'Download failed rows',
|
|
512
814
|
options: 'Import options',
|
|
513
815
|
writeMode: 'When a row matches an existing record',
|
|
@@ -522,9 +824,6 @@ const en = {
|
|
|
522
824
|
needMatchFields: 'Select at least one field to match on.',
|
|
523
825
|
matchOnlyField: '(match only)',
|
|
524
826
|
optCreateOptions: 'Keep unknown option values',
|
|
525
|
-
optRunAutomations: 'Run automations & triggers',
|
|
526
|
-
optTreatHistorical: 'Import as historical data',
|
|
527
|
-
optTreatHistoricalHint: '(import completed records as-is — skip state-machine checks and keep their original timestamps & author instead of stamping now)',
|
|
528
827
|
optSkipBlankKey: 'Skip rows with a blank match value',
|
|
529
828
|
optBackground: 'Import in the background',
|
|
530
829
|
optBackgroundHint: '(runs as an undoable job)',
|
|
@@ -539,6 +838,7 @@ const en = {
|
|
|
539
838
|
invalidBoolean: '"{{value}}" is not a valid true/false value',
|
|
540
839
|
invalidNumber: '"{{value}}" is not a valid number',
|
|
541
840
|
invalidDate: '"{{value}}" is not a valid date',
|
|
841
|
+
invalidTime: '"{{value}}" is not a valid time',
|
|
542
842
|
invalidOption: '"{{value}}" is not one of the allowed options',
|
|
543
843
|
requiredValue: 'This field is required',
|
|
544
844
|
matchAmbiguous: 'Matches more than one existing record — use a unique value or the record id',
|
|
@@ -555,10 +855,15 @@ const en = {
|
|
|
555
855
|
historyColResult: 'Result',
|
|
556
856
|
historyColTime: 'When',
|
|
557
857
|
errorCount: '{{count}} errors',
|
|
858
|
+
errorCount_one: '{{count}} error',
|
|
859
|
+
errorCount_other: '{{count}} errors',
|
|
558
860
|
undoImport: 'Undo import',
|
|
559
861
|
undoing: 'Undoing…',
|
|
560
862
|
undoConfirm: 'Undo this import? Records it created will be deleted and records it updated will be restored to their previous values.',
|
|
561
863
|
reverted: 'Undone',
|
|
864
|
+
undoPartial: '{{count}} rows were not undone. Undo again to retry only those rows.',
|
|
865
|
+
undoPartial_one: '{{count}} row was not undone. Undo again to retry only that row.',
|
|
866
|
+
undoPartial_other: '{{count}} rows were not undone. Undo again to retry only those rows.',
|
|
562
867
|
jobStatus: {
|
|
563
868
|
pending: 'Pending',
|
|
564
869
|
running: 'Running',
|
|
@@ -571,6 +876,8 @@ const en = {
|
|
|
571
876
|
next: 'Next',
|
|
572
877
|
close: 'Close',
|
|
573
878
|
importNRows: 'Import {{count}} Rows',
|
|
879
|
+
importNRows_one: 'Import {{count}} Row',
|
|
880
|
+
importNRows_other: 'Import {{count}} Rows',
|
|
574
881
|
importingProgress: 'Importing…',
|
|
575
882
|
required: 'Required',
|
|
576
883
|
invalidType: 'Invalid {{type}}',
|
|
@@ -582,9 +889,13 @@ const en = {
|
|
|
582
889
|
},
|
|
583
890
|
bulk: {
|
|
584
891
|
confirmDefault: 'This will apply to {{count}} record(s).',
|
|
892
|
+
confirmDefault_one: 'This will apply to {{count}} record.',
|
|
893
|
+
confirmDefault_other: 'This will apply to {{count}} records.',
|
|
585
894
|
overLimit: 'Selection ({{count}}) exceeds the action limit ({{limit}}). Reduce the selection to proceed.',
|
|
586
895
|
affectedRecords: 'Affected records ({{count}}):',
|
|
587
896
|
skippedIneligible: '{{count}} selected record(s) are not eligible for this action and will be skipped.',
|
|
897
|
+
skippedIneligible_one: '{{count}} selected record is not eligible for this action and will be skipped.',
|
|
898
|
+
skippedIneligible_other: '{{count}} selected records are not eligible for this action and will be skipped.',
|
|
588
899
|
rowFallback: 'Row {{index}}',
|
|
589
900
|
andMore: '\u2026 and {{count}} more',
|
|
590
901
|
processed: '{{count}} / {{total}} processed',
|
|
@@ -602,7 +913,6 @@ const en = {
|
|
|
602
913
|
undo: 'Undo',
|
|
603
914
|
undoing: 'Undoing\u2026',
|
|
604
915
|
done: 'Done',
|
|
605
|
-
selectPlaceholder: 'Select\u2026',
|
|
606
916
|
loading: 'Loading\u2026',
|
|
607
917
|
},
|
|
608
918
|
},
|
|
@@ -611,26 +921,59 @@ const en = {
|
|
|
611
921
|
month: 'Month',
|
|
612
922
|
week: 'Week',
|
|
613
923
|
day: 'Day',
|
|
614
|
-
agenda: 'Agenda',
|
|
615
924
|
allDay: 'All Day',
|
|
616
|
-
noEvents: 'No events',
|
|
617
925
|
newEvent: 'New event',
|
|
618
926
|
moreEvents: '+{{count}} more',
|
|
927
|
+
unscheduled: 'Unscheduled ({{count}})',
|
|
928
|
+
loading: 'Loading calendar…',
|
|
929
|
+
loadError: 'Error: {{message}}',
|
|
930
|
+
configRequired: 'Calendar configuration required. Please specify startDateField, the calendar\'s one required key; the event title resolves without titleField.',
|
|
931
|
+
configRequiredHint: 'It belongs on the view\'s calendar block. An interface page has no calendar slot of its own: point its sourceView at a view that declares one.',
|
|
932
|
+
eventDetails: 'Event Details',
|
|
933
|
+
pullToRefresh: 'Pull to refresh',
|
|
934
|
+
refreshing: 'Refreshing…',
|
|
935
|
+
onDate: 'On {{date}}',
|
|
936
|
+
eventTitle: 'Title',
|
|
937
|
+
eventTitlePlaceholder: 'What\'s this event about?',
|
|
938
|
+
creating: 'Creating…',
|
|
939
|
+
titleRequired: 'Title is required',
|
|
940
|
+
a11y: {
|
|
941
|
+
region: 'Calendar',
|
|
942
|
+
grid: 'Calendar grid',
|
|
943
|
+
goToToday: 'Go to today',
|
|
944
|
+
previousPeriod: 'Previous period',
|
|
945
|
+
nextPeriod: 'Next period',
|
|
946
|
+
currentDate: 'Current date: {{date}}',
|
|
947
|
+
dayCell: '{{date}}, {{count}} events',
|
|
948
|
+
dayCell_one: '{{date}}, {{count}} event',
|
|
949
|
+
dayCell_other: '{{date}}, {{count}} events',
|
|
950
|
+
resizeEventEnd: 'Resize event end',
|
|
951
|
+
resizeEventEndHint: 'Drag to change end date',
|
|
952
|
+
resizeStart: 'Resize start',
|
|
953
|
+
resizeEnd: 'Resize end',
|
|
954
|
+
},
|
|
619
955
|
},
|
|
620
956
|
list: {
|
|
621
957
|
loading: 'Loading records…',
|
|
622
958
|
recordCount: '{{count}} records',
|
|
623
|
-
|
|
959
|
+
recordCount_one: '{{count}} record',
|
|
960
|
+
recordCount_other: '{{count}} records',
|
|
624
961
|
addRecord: 'Add record',
|
|
962
|
+
// objectui#12703 — the compact list's footer link to the object's list or the block's view.
|
|
963
|
+
viewAll: 'View all',
|
|
625
964
|
tabs: 'Tabs',
|
|
626
965
|
allRecords: 'All Records',
|
|
627
966
|
search: 'Search',
|
|
628
967
|
filter: 'Filter',
|
|
629
968
|
filterRecords: 'Filter Records',
|
|
969
|
+
filterActive: 'Filter, {{count}} active',
|
|
970
|
+
filterActive_one: 'Filter, {{count}} active',
|
|
971
|
+
filterActive_other: 'Filter, {{count}} active',
|
|
630
972
|
sort: 'Sort',
|
|
631
973
|
sortRecords: 'Sort Records',
|
|
632
974
|
sortByIdSuffix: '(by ID)',
|
|
633
975
|
sortRelationalHint: 'Columns that link to another record are not listed: they can only be sorted by the stored ID, not by the name shown in the cell. To sort by that name, denormalize it onto this object as a stored field, written when the source changes, and sort by that. Not a formula field: it is virtual, so no column is stored for it and the server refuses to sort by one.',
|
|
976
|
+
sortRelationalPicked: 'A linked column sorts by the stored ID, not the name shown.',
|
|
634
977
|
resetSortToDefault: 'Reset to view default',
|
|
635
978
|
group: 'Group',
|
|
636
979
|
groupBy: 'Group By',
|
|
@@ -648,6 +991,7 @@ const en = {
|
|
|
648
991
|
firstRunMessage: 'Create your first record to get started.',
|
|
649
992
|
noMatches: 'No matching records',
|
|
650
993
|
noMatchesMessage: 'No records match your current filters or search. Try adjusting or clearing them.',
|
|
994
|
+
viewFilterNoMatchesMessage: 'No records match this view’s filter.',
|
|
651
995
|
loadErrorTitle: 'Couldn\u2019t load records',
|
|
652
996
|
loadErrorMessage: 'Something went wrong while loading this data. Check your connection and try again.',
|
|
653
997
|
loadErrorForbiddenTitle: 'You don\u2019t have access',
|
|
@@ -689,14 +1033,15 @@ const en = {
|
|
|
689
1033
|
print: 'Print',
|
|
690
1034
|
hideFieldsTitle: 'Hide Fields',
|
|
691
1035
|
dataLimitReached: 'Showing first {{limit}} records. More data may be available.',
|
|
692
|
-
|
|
693
|
-
|
|
1036
|
+
display: 'Display',
|
|
1037
|
+
layout: 'Layout',
|
|
1038
|
+
rowNumbers: 'Row numbers',
|
|
1039
|
+
resetToViewDefault: 'Reset to view default',
|
|
694
1040
|
addGroup: 'Add group field',
|
|
695
1041
|
collapsedByDefault: 'Collapsed by default',
|
|
696
1042
|
removeGroup: 'Remove',
|
|
697
1043
|
inlineEditShort: 'Edit inline',
|
|
698
1044
|
inlineEditLabel: 'Edit records inline (click a cell to edit)',
|
|
699
|
-
recordEditingTitle: 'Record editing',
|
|
700
1045
|
},
|
|
701
1046
|
managedByBadge: {
|
|
702
1047
|
config: {
|
|
@@ -732,15 +1077,31 @@ const en = {
|
|
|
732
1077
|
deleteCard: 'Delete card',
|
|
733
1078
|
deleteColumn: 'Delete column',
|
|
734
1079
|
noCards: 'No cards',
|
|
1080
|
+
columnCards: '{{column}} cards',
|
|
1081
|
+
laneCards: '{{column}} - {{lane}} cards',
|
|
735
1082
|
cardTitlePlaceholder: 'Enter card title…',
|
|
736
1083
|
uncategorized: 'Uncategorized',
|
|
1084
|
+
loadMore: 'Load more',
|
|
737
1085
|
columns: 'columns',
|
|
738
1086
|
requiredFieldsTitle: 'Complete required fields',
|
|
739
1087
|
requiredFieldsDescription: 'This move makes the fields below required. Fill them in to continue.',
|
|
1088
|
+
dnd: {
|
|
1089
|
+
start: 'Picked up {{card}} in {{column}}.',
|
|
1090
|
+
overCard: 'Moving {{card}} over {{target}} in {{column}}.',
|
|
1091
|
+
overColumn: 'Moving {{card}} over {{column}}.',
|
|
1092
|
+
overNone: 'Moving {{card}}. It is not over a column.',
|
|
1093
|
+
moved: 'Moved {{card}} to {{column}}.',
|
|
1094
|
+
dropped: 'Dropped {{card}}. It stays in {{column}}.',
|
|
1095
|
+
cancelled: 'Cancelled moving {{card}}. It stays in {{column}}.',
|
|
1096
|
+
untitledCard: 'an untitled card',
|
|
1097
|
+
unnamedColumn: 'an unnamed column',
|
|
1098
|
+
instructions: 'To move this card to another column, drag it with a pointer or by touch.',
|
|
1099
|
+
dragging: 'Dragging {{card}}',
|
|
1100
|
+
},
|
|
740
1101
|
},
|
|
741
1102
|
timeline: {
|
|
742
1103
|
bucket: {
|
|
743
|
-
|
|
1104
|
+
earlier: 'Earlier',
|
|
744
1105
|
today: 'Today',
|
|
745
1106
|
tomorrow: 'Tomorrow',
|
|
746
1107
|
thisWeek: 'This week',
|
|
@@ -755,6 +1116,17 @@ const en = {
|
|
|
755
1116
|
},
|
|
756
1117
|
gantt: {
|
|
757
1118
|
rowLabel: 'Items',
|
|
1119
|
+
unusableRange: {
|
|
1120
|
+
malformedDate: 'Unusable gantt date range — {{path}} is {{value}}, which is not a valid date. Every gantt date has to parse: the startDate and endDate on every row item, plus any minDate / maxDate pinned on the schema.',
|
|
1121
|
+
malformedRow: 'Unusable gantt rows — {{path}} is {{value}}, which is not a row shape. A gantt draws items as a list of rows, every row as an object with a label and its own items, and every row\'s items as a list of bars; a null, a number, a string or a plain object in any of those places cannot be drawn.',
|
|
1122
|
+
inverted: 'Unusable gantt date range — minDate {{minDate}} is after maxDate {{maxDate}}. A pinned minDate / maxDate overrides the range computed from the rows, so this axis has no columns and no bar can be placed on it; swap the two values.',
|
|
1123
|
+
},
|
|
1124
|
+
},
|
|
1125
|
+
unsupported: {
|
|
1126
|
+
objectBoundGantt: 'Unsupported variant "gantt" — an object-bound timeline renders the feed variants ({{variants}}). Gantt needs literal rows, each with its own nested items, so the gantt axis (scale) has no effect here.',
|
|
1127
|
+
},
|
|
1128
|
+
unconfigured: {
|
|
1129
|
+
noDateAxis: 'Timeline date axis required — this view declares no date field, and an object-bound timeline will not invent one. Declare one of: {{fields}}. The first is the spec spelling; the rest are legacy aliases.',
|
|
758
1130
|
},
|
|
759
1131
|
},
|
|
760
1132
|
gantt: {
|
|
@@ -800,6 +1172,7 @@ const en = {
|
|
|
800
1172
|
},
|
|
801
1173
|
aria: {
|
|
802
1174
|
taskList: 'Task list',
|
|
1175
|
+
refreshing: 'Refreshing…',
|
|
803
1176
|
},
|
|
804
1177
|
tooltip: {
|
|
805
1178
|
days: 'd',
|
|
@@ -845,13 +1218,19 @@ const en = {
|
|
|
845
1218
|
conflict: {
|
|
846
1219
|
title: 'Schedule conflict',
|
|
847
1220
|
body: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected task(s)?',
|
|
1221
|
+
body_one: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected task?',
|
|
1222
|
+
body_other: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected tasks?',
|
|
848
1223
|
confirm: 'Auto-reschedule',
|
|
849
1224
|
cancel: 'Keep as is',
|
|
850
1225
|
},
|
|
851
1226
|
autoScheduleDlg: {
|
|
852
1227
|
title: 'Auto-schedule',
|
|
853
1228
|
body: 'Shift {{count}} task(s) later to satisfy dependency links?',
|
|
1229
|
+
body_one: 'Shift {{count}} task later to satisfy dependency links?',
|
|
1230
|
+
body_other: 'Shift {{count}} tasks later to satisfy dependency links?',
|
|
854
1231
|
skipped: '{{count}} locked task(s) also violate links and were skipped.',
|
|
1232
|
+
skipped_one: '{{count}} locked task also violates links and was skipped.',
|
|
1233
|
+
skipped_other: '{{count}} locked tasks also violate links and were skipped.',
|
|
855
1234
|
confirm: 'Apply',
|
|
856
1235
|
cancel: 'Cancel',
|
|
857
1236
|
none: 'All dependencies satisfied — nothing to reschedule.',
|
|
@@ -908,6 +1287,13 @@ const en = {
|
|
|
908
1287
|
tabActionsFor: 'View actions for {{name}}',
|
|
909
1288
|
readonlyAriaLabel: 'Read-only view',
|
|
910
1289
|
readonlyTooltip: 'System view — defined in code, read-only.',
|
|
1290
|
+
malformedFilter: 'This view’s filter is malformed, so no records are shown: the {{subject}} condition cannot be applied.',
|
|
1291
|
+
// objectui#11605 — an object-bound block whose node names its object in
|
|
1292
|
+
// neither place (no own key, no `dataSource.object`). `{{property}}` is the
|
|
1293
|
+
// block's object key (`objectName`), interpolated and never translated; the
|
|
1294
|
+
// wording was `element.number.noObject`'s with the property as a hole,
|
|
1295
|
+
// before objectui#11880 dropped that notice's flat `object`.
|
|
1296
|
+
noObject: 'No object named: set {{property}} or dataSource.object.',
|
|
911
1297
|
},
|
|
912
1298
|
detail: {
|
|
913
1299
|
back: 'Back',
|
|
@@ -921,9 +1307,12 @@ const en = {
|
|
|
921
1307
|
lockedByApproval: 'Locked for approval',
|
|
922
1308
|
lockedTooltip: 'This record has a pending approval request; editing is locked',
|
|
923
1309
|
writeStrippedTitle: 'Saved — but some fields did not take effect',
|
|
1310
|
+
writeWarningsTitle: 'Saved — with warnings',
|
|
924
1311
|
writeStrippedReadonly: 'Read-only, so it did not take effect: {{fields}}',
|
|
925
1312
|
writeStrippedByState: "Not editable in this record's current state, so it did not take effect: {{fields}}",
|
|
926
1313
|
writeStrippedPrimaryKey: "The record's identifier cannot be changed by a save, so it did not take effect: {{fields}}",
|
|
1314
|
+
writeStrippedComputed: 'Calculated by the server from a formula, so the value sent did not take effect: {{fields}}',
|
|
1315
|
+
writeStrippedStoredExpression: 'Computed from the record, so the computed value was saved instead of the one sent: {{fields}}',
|
|
927
1316
|
writeStrippedUnknownReason: 'Not applied by the server: {{fields}}',
|
|
928
1317
|
approvalPendingEditable: 'In approval · editable',
|
|
929
1318
|
approvalPendingTooltip: 'This record has a pending approval request; this step still allows editing',
|
|
@@ -950,6 +1339,16 @@ const en = {
|
|
|
950
1339
|
pathStageLostUpcoming: '{{stage}}, closed lost, not reached',
|
|
951
1340
|
pathStageWonUpcoming: '{{stage}}, goal stage, not reached',
|
|
952
1341
|
linkCopied: 'Link copied to clipboard',
|
|
1342
|
+
commentFailed: 'Your comment was not posted. Nothing was saved — please try again.',
|
|
1343
|
+
reactionFailed: 'Your reaction was not saved. Please try again.',
|
|
1344
|
+
// objectui#12268 — the author's Edit and Delete on their own comment in the
|
|
1345
|
+
// record feed: the two buttons' names, the delete confirm, and the two
|
|
1346
|
+
// refusals the record page raises.
|
|
1347
|
+
editComment: 'Edit comment',
|
|
1348
|
+
deleteComment: 'Delete comment',
|
|
1349
|
+
deleteCommentConfirm: 'Are you sure you want to delete this comment?',
|
|
1350
|
+
commentEditFailed: 'Your edit was not saved. The comment keeps its previous text.',
|
|
1351
|
+
commentDeleteFailed: 'The comment was not deleted. Please try again.',
|
|
953
1352
|
linkCopyFailed: 'Failed to copy link',
|
|
954
1353
|
cancel: 'Cancel',
|
|
955
1354
|
cancelEdit: 'Discard changes',
|
|
@@ -976,7 +1375,8 @@ const en = {
|
|
|
976
1375
|
pageHeaderActions: 'Page header actions',
|
|
977
1376
|
emojiPicker: 'Emoji picker',
|
|
978
1377
|
reactionCount: '{{emoji}} {{count}} reactions',
|
|
979
|
-
|
|
1378
|
+
reactionCount_one: '{{emoji}} {{count}} reaction',
|
|
1379
|
+
reactionCount_other: '{{emoji}} {{count}} reactions',
|
|
980
1380
|
// Record-overlay chrome (objectstack#5506). `recordDetail` is the VISIBLE
|
|
981
1381
|
// heading the overlay falls back to when the host passes no title;
|
|
982
1382
|
// `openAsFullPage` is the icon-only expand button's default accessible
|
|
@@ -1016,7 +1416,6 @@ const en = {
|
|
|
1016
1416
|
viewAll: 'View All',
|
|
1017
1417
|
new: 'New',
|
|
1018
1418
|
add: 'Add',
|
|
1019
|
-
emptyValue: '—',
|
|
1020
1419
|
activity: 'Activity',
|
|
1021
1420
|
history: 'History',
|
|
1022
1421
|
historyEmpty: 'No history yet',
|
|
@@ -1031,6 +1430,7 @@ const en = {
|
|
|
1031
1430
|
sortBy: 'Sort by',
|
|
1032
1431
|
filterPlaceholder: 'Filter…',
|
|
1033
1432
|
highlightFields: 'Key Fields',
|
|
1433
|
+
highlightsLabel: 'Record highlights',
|
|
1034
1434
|
// Comments
|
|
1035
1435
|
comments: 'Comments',
|
|
1036
1436
|
searchComments: 'Search comments…',
|
|
@@ -1042,8 +1442,14 @@ const en = {
|
|
|
1042
1442
|
unpin: 'Unpin',
|
|
1043
1443
|
justNow: 'just now',
|
|
1044
1444
|
minutesAgo: '{{count}}m ago',
|
|
1445
|
+
minutesAgo_one: '{{count}}m ago',
|
|
1446
|
+
minutesAgo_other: '{{count}}m ago',
|
|
1045
1447
|
hoursAgo: '{{count}}h ago',
|
|
1448
|
+
hoursAgo_one: '{{count}}h ago',
|
|
1449
|
+
hoursAgo_other: '{{count}}h ago',
|
|
1046
1450
|
daysAgo: '{{count}}d ago',
|
|
1451
|
+
daysAgo_one: '{{count}}d ago',
|
|
1452
|
+
daysAgo_other: '{{count}}d ago',
|
|
1047
1453
|
// Activity feed actors
|
|
1048
1454
|
systemActor: 'System',
|
|
1049
1455
|
unknownUser: 'Unknown',
|
|
@@ -1057,7 +1463,8 @@ const en = {
|
|
|
1057
1463
|
// Attachments
|
|
1058
1464
|
dropFilesToUpload: 'Drop files here or click to upload',
|
|
1059
1465
|
attachmentCount: '{{count}} attachment',
|
|
1060
|
-
|
|
1466
|
+
attachmentCount_one: '{{count}} attachment',
|
|
1467
|
+
attachmentCount_other: '{{count}} attachments',
|
|
1061
1468
|
removeAttachment: 'Remove attachment',
|
|
1062
1469
|
// Record Attachments panel (enable.files, objectstack#4358)
|
|
1063
1470
|
attachments: 'Attachments',
|
|
@@ -1066,6 +1473,7 @@ const en = {
|
|
|
1066
1473
|
noAttachments: 'No attachments yet. Upload a file to get started.',
|
|
1067
1474
|
downloadAttachment: 'Download',
|
|
1068
1475
|
deleteAttachment: 'Delete attachment',
|
|
1476
|
+
deleteAttachmentConfirm: 'Are you sure you want to delete the attachment "{{name}}"?',
|
|
1069
1477
|
attachmentDeleteDenied: 'Only the uploader or someone who can edit this record may delete this attachment.',
|
|
1070
1478
|
attachmentParentAccessDenied: "You don't have access to attach files to this record.",
|
|
1071
1479
|
attachmentDownloadDenied: "You don't have access to download this attachment.",
|
|
@@ -1075,12 +1483,6 @@ const en = {
|
|
|
1075
1483
|
attachmentsLoadFailed: "We couldn't load the attachments for this record.",
|
|
1076
1484
|
attachmentsApiUnavailable: 'The attachments list is not available on this object.',
|
|
1077
1485
|
retryLoadAttachments: 'Retry',
|
|
1078
|
-
// Diff
|
|
1079
|
-
unifiedDiff: 'Unified diff',
|
|
1080
|
-
sideBySideDiff: 'Side-by-side diff',
|
|
1081
|
-
noChanges: 'No changes',
|
|
1082
|
-
previousVersion: 'Previous',
|
|
1083
|
-
currentVersion: 'Current',
|
|
1084
1486
|
// Discussion
|
|
1085
1487
|
discussion: 'Discussion',
|
|
1086
1488
|
showDiscussion: 'Show Discussion ({{count}})',
|
|
@@ -1098,23 +1500,16 @@ const en = {
|
|
|
1098
1500
|
// Subscription
|
|
1099
1501
|
subscribedTooltip: 'Subscribed — click to unsubscribe',
|
|
1100
1502
|
unsubscribedTooltip: 'Subscribe to notifications',
|
|
1101
|
-
//
|
|
1102
|
-
firstRecord: 'First record (Home)',
|
|
1103
|
-
previousRecordKey: 'Previous record (←)',
|
|
1104
|
-
nextRecordKey: 'Next record (→)',
|
|
1105
|
-
lastRecord: 'Last record (End)',
|
|
1503
|
+
// The reference rail's empty related-record list
|
|
1106
1504
|
noRecords: 'No records',
|
|
1107
|
-
// objectui#3863 — the BASE key
|
|
1108
|
-
//
|
|
1109
|
-
//
|
|
1110
|
-
//
|
|
1111
|
-
//
|
|
1112
|
-
// `record-reference-rail.tsx`, which `check:i18n-keys` now judges as class 3.
|
|
1505
|
+
// objectui#3863 — the BASE key; since objectui#11432 every pack also spells out
|
|
1506
|
+
// each CLDR category its language selects, so with a count no pack reaches the
|
|
1507
|
+
// base. In `en` this value is parity ballast — and it must stay byte-identical to
|
|
1508
|
+
// the call site's inline `defaultValue` in `record-reference-rail.tsx`, which
|
|
1509
|
+
// `check:i18n-keys` now judges as class 3.
|
|
1113
1510
|
showEmptyRelated: '+ {{count}} empty',
|
|
1114
1511
|
showEmptyRelated_one: '+ {{count}} empty',
|
|
1115
1512
|
showEmptyRelated_other: '+ {{count}} empty',
|
|
1116
|
-
searchWhileNavigating: 'Search while navigating',
|
|
1117
|
-
searchRecords: 'Search records…',
|
|
1118
1513
|
// Activity timeline
|
|
1119
1514
|
allActivity: 'All Activity',
|
|
1120
1515
|
commentsOnly: 'Comments Only',
|
|
@@ -1122,13 +1517,29 @@ const en = {
|
|
|
1122
1517
|
tasksOnly: 'Tasks Only',
|
|
1123
1518
|
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
|
|
1124
1519
|
noActivity: 'No activity recorded',
|
|
1520
|
+
activityAccessDenied: "You don't have permission to view activity on this record.",
|
|
1521
|
+
commentsAccessDenied: "You don't have permission to view comments on this record.",
|
|
1522
|
+
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
|
|
1523
|
+
// `detail.*` pack did not already name, and the `formatFieldChange`
|
|
1524
|
+
// sentences, which are assembled in code and so need interpolation holes.
|
|
1525
|
+
allFilter: 'All',
|
|
1526
|
+
createsFilter: 'Creates',
|
|
1527
|
+
deletesFilter: 'Deletes',
|
|
1528
|
+
statusChangesFilter: 'Status Changes',
|
|
1529
|
+
activityEmptyValue: '(empty)',
|
|
1530
|
+
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
|
|
1531
|
+
activityCreated: 'Created this record',
|
|
1532
|
+
activityDeleted: 'Deleted this record',
|
|
1533
|
+
activityStatusChanged: 'Changed status to "{{value}}"',
|
|
1534
|
+
activityUpdated: 'Updated record',
|
|
1125
1535
|
loadMore: 'Load more',
|
|
1126
1536
|
edited: '(edited)',
|
|
1127
1537
|
via: 'via {{source}}',
|
|
1128
1538
|
viewSource: 'View source',
|
|
1129
1539
|
// Replies
|
|
1130
1540
|
replyCount: '{{count}} reply',
|
|
1131
|
-
|
|
1541
|
+
replyCount_one: '{{count}} reply',
|
|
1542
|
+
replyCount_other: '{{count}} replies',
|
|
1132
1543
|
replyPlaceholder: 'Reply…',
|
|
1133
1544
|
// Aria labels
|
|
1134
1545
|
filterActivity: 'Filter activity',
|
|
@@ -1141,13 +1552,54 @@ const en = {
|
|
|
1141
1552
|
copyPhone: 'Copy phone number',
|
|
1142
1553
|
copyRecordId: 'Copy record ID',
|
|
1143
1554
|
showEmptyFields: 'Show {{count}} empty fields',
|
|
1555
|
+
showEmptyFields_one: 'Show {{count}} empty field',
|
|
1556
|
+
showEmptyFields_other: 'Show {{count}} empty fields',
|
|
1144
1557
|
hideEmptyFields: 'Hide empty fields',
|
|
1145
1558
|
noValue: 'No value',
|
|
1559
|
+
unresolvedReference: 'Unresolved reference: {{value}} was not resolved to a user',
|
|
1560
|
+
unresolvedLookupReference: 'Unresolved reference: {{value}} was not resolved to a record on this screen',
|
|
1561
|
+
// Cell-level COUNT phrases for the `repeater` and file cells
|
|
1562
|
+
// (objectui#8441). Both were written straight into the renderer before this
|
|
1563
|
+
// — `repeater` as a number plus a hardcoded Chinese unit word, which every
|
|
1564
|
+
// reader on every locale saw, and `FileCellRenderer` as an English-only
|
|
1565
|
+
// `count === 1 ? 'file' : 'files'`, which is not plural-safe anywhere else.
|
|
1566
|
+
// One channel, two call sites.
|
|
1567
|
+
//
|
|
1568
|
+
// REAL i18next plural families — the one count shape this repo uses since
|
|
1569
|
+
// objectui#11445 retired the code-selected `xxxCountOne` / `xxxCountPlural`
|
|
1570
|
+
// sibling keys. i18next asks `Intl.PluralRules` for the
|
|
1571
|
+
// ONE suffix a number needs, so each pack carries every category its language
|
|
1572
|
+
// selects (`ru` `_few`/`_many`, `ar` `_zero`/`_two`/`_few`/`_many` —
|
|
1573
|
+
// objectui#11432) plus the base key (objectui#3863).
|
|
1574
|
+
// `all-locales-key-parity.test.ts` owns both rules.
|
|
1575
|
+
repeaterItemCount: '{{count}} items',
|
|
1576
|
+
repeaterItemCount_one: '{{count}} item',
|
|
1577
|
+
repeaterItemCount_other: '{{count}} items',
|
|
1578
|
+
fileCount: '{{count}} files',
|
|
1579
|
+
fileCount_one: '{{count}} file',
|
|
1580
|
+
fileCount_other: '{{count}} files',
|
|
1146
1581
|
},
|
|
1147
1582
|
chart: {
|
|
1148
|
-
noData: 'No chart data available',
|
|
1149
1583
|
loading: 'Loading chart…',
|
|
1584
|
+
refreshing: 'Refreshing…',
|
|
1150
1585
|
nullCategory: '(None)',
|
|
1586
|
+
// The refusal a scatter renders when handed more than one series
|
|
1587
|
+
// (objectui#7194): it binds ONE measure, so a second series was painted at
|
|
1588
|
+
// the first one's y values. One short sentence on purpose — this pack is
|
|
1589
|
+
// eagerly loaded and the `framework` chunk's gzip ceiling has ~0.2 KB of
|
|
1590
|
+
// headroom; the series keys are rendered by the chart as data, after it.
|
|
1591
|
+
scatterOneMeasure: 'A scatter plots one measure. Keep exactly one series:',
|
|
1592
|
+
// The refusal an object-bound chart renders when it declares no category
|
|
1593
|
+
// axis (objectui#8168) — `aggregate.groupBy` / `xAxisKey` / `xAxis.field`
|
|
1594
|
+
// all absent, so `runAggregate` would have grouped on a name nobody wrote.
|
|
1595
|
+
// The twin of `timeline.unconfigured.noDateAxis`. ONE short sentence, for
|
|
1596
|
+
// the same reason `scatterOneMeasure` above is one: the packs ship it ten
|
|
1597
|
+
// times, and the binding names are rendered by the component after it
|
|
1598
|
+
// rather than interpolated, so a rung added to or retired from the
|
|
1599
|
+
// resolver cannot leave this sentence naming a stale vocabulary.
|
|
1600
|
+
unconfigured: {
|
|
1601
|
+
noCategoryAxis: 'Chart category axis required — an object-bound chart will not invent one. Declare one of:',
|
|
1602
|
+
},
|
|
1151
1603
|
},
|
|
1152
1604
|
report: {
|
|
1153
1605
|
total: 'Total',
|
|
@@ -1162,6 +1614,8 @@ const en = {
|
|
|
1162
1614
|
loading: 'Loading…',
|
|
1163
1615
|
failedToLoad: 'Failed to load matrix: {{message}}',
|
|
1164
1616
|
needsAcross: 'Matrix report requires at least one `groupingsAcross` field.',
|
|
1617
|
+
// objectui#12330 — the report's no-access state; its title is `dashboard.widgetForbiddenTitle`.
|
|
1618
|
+
forbiddenMessage: 'You don’t have permission to view the data behind this report.',
|
|
1165
1619
|
aggregate: {
|
|
1166
1620
|
count: 'Count',
|
|
1167
1621
|
countDistinct: 'Distinct Count',
|
|
@@ -1189,30 +1643,40 @@ const en = {
|
|
|
1189
1643
|
panelTitle: 'Edit report',
|
|
1190
1644
|
},
|
|
1191
1645
|
},
|
|
1192
|
-
map: {
|
|
1193
|
-
searchLocations: 'Search locations…',
|
|
1194
|
-
locationDetails: 'Location Details',
|
|
1195
|
-
markersCount: '{{count}} markers',
|
|
1196
|
-
invalidCoordinates: '{{count}} record with missing or invalid coordinates excluded from the map.',
|
|
1197
|
-
invalidCoordinatesPlural: '{{count}} records with missing or invalid coordinates excluded from the map.',
|
|
1198
|
-
},
|
|
1199
1646
|
designer: {
|
|
1200
1647
|
undo: 'Undo',
|
|
1201
1648
|
redo: 'Redo',
|
|
1649
|
+
canvasMinimap: 'Canvas minimap',
|
|
1650
|
+
versionHistory: 'Version history',
|
|
1202
1651
|
},
|
|
1203
1652
|
dashboard: {
|
|
1204
1653
|
addWidget: 'Add widget',
|
|
1205
|
-
removeWidget: 'Remove widget',
|
|
1206
1654
|
editLayout: 'Edit layout',
|
|
1207
1655
|
saveLayout: 'Save layout',
|
|
1208
1656
|
resetLayout: 'Reset layout',
|
|
1209
1657
|
total: 'Total',
|
|
1210
|
-
noDataAvailable: 'No data available',
|
|
1211
1658
|
noDataSourceFor: 'No data source available for',
|
|
1212
|
-
|
|
1659
|
+
// objectui#7063 — the DEFAULT empty state every dashboard widget renders
|
|
1660
|
+
// when its query SUCCEEDED and returned nothing. It replaced the terse
|
|
1661
|
+
// per-widget `noRows` / `noDataAvailable` fragments at the render site;
|
|
1662
|
+
// objectui#7125 deleted those two keys from all ten packs once nothing
|
|
1663
|
+
// read them. The copy here has to read as a state rather than a failure,
|
|
1664
|
+
// which is why it says the widget loaded. `sourceLabel` carries its own
|
|
1665
|
+
// punctuation so the call site concatenates no separator (see
|
|
1666
|
+
// `WidgetEmptyState`).
|
|
1667
|
+
empty: {
|
|
1668
|
+
title: 'No data yet',
|
|
1669
|
+
message: 'This widget loaded successfully and its query returned no records yet.',
|
|
1670
|
+
sourceLabel: 'Source:',
|
|
1671
|
+
},
|
|
1213
1672
|
loading: 'Loading…',
|
|
1673
|
+
refreshing: 'Refreshing…',
|
|
1674
|
+
refreshAll: 'Refresh All',
|
|
1675
|
+
refreshDashboard: 'Refresh dashboard',
|
|
1214
1676
|
pickMeasures: 'Pick measures (values) for this dataset widget.',
|
|
1215
1677
|
datasetUnsupported: 'This data source does not support dataset queries.',
|
|
1678
|
+
widgetForbiddenTitle: 'You don’t have access',
|
|
1679
|
+
widgetForbiddenMessage: 'You don’t have permission to view the data behind this widget.',
|
|
1216
1680
|
details: 'Details',
|
|
1217
1681
|
exportCsv: 'Export CSV',
|
|
1218
1682
|
openInList: 'Open in list',
|
|
@@ -1359,10 +1823,6 @@ const en = {
|
|
|
1359
1823
|
appDescription: 'Description',
|
|
1360
1824
|
appIcon: 'Icon',
|
|
1361
1825
|
template: 'Template',
|
|
1362
|
-
layout: 'Layout',
|
|
1363
|
-
layoutSidebar: 'Sidebar',
|
|
1364
|
-
layoutHeader: 'Header',
|
|
1365
|
-
layoutEmpty: 'Empty',
|
|
1366
1826
|
selectObjects: 'Select Objects',
|
|
1367
1827
|
searchObjects: 'Search objects…',
|
|
1368
1828
|
selectAll: 'Select All',
|
|
@@ -1371,7 +1831,6 @@ const en = {
|
|
|
1371
1831
|
addGroup: 'Add Group',
|
|
1372
1832
|
addUrl: 'Add URL',
|
|
1373
1833
|
addSeparator: 'Add Separator',
|
|
1374
|
-
noNavItems: 'No navigation items yet.',
|
|
1375
1834
|
logoUrl: 'Logo URL',
|
|
1376
1835
|
primaryColor: 'Primary Color',
|
|
1377
1836
|
faviconUrl: 'Favicon URL',
|
|
@@ -1398,13 +1857,12 @@ const en = {
|
|
|
1398
1857
|
appearance: 'Appearance',
|
|
1399
1858
|
rowHeight: 'Row Height',
|
|
1400
1859
|
livePreview: 'Live Preview',
|
|
1401
|
-
stepBasicDesc: 'Name, title, and
|
|
1860
|
+
stepBasicDesc: 'Name, title, and icon',
|
|
1402
1861
|
stepObjectsDesc: 'Select business objects',
|
|
1403
1862
|
stepNavigationDesc: 'Build navigation tree',
|
|
1404
1863
|
stepBrandingDesc: 'Logo, colors, and favicon',
|
|
1405
1864
|
noObjectsFound: 'No objects found.',
|
|
1406
1865
|
noNavItemsHint: 'No navigation items yet. Select objects in the previous step or add items manually.',
|
|
1407
|
-
separator: 'Separator',
|
|
1408
1866
|
separatorLabel: '— Separator —',
|
|
1409
1867
|
newGroup: 'New Group',
|
|
1410
1868
|
newLink: 'New Link',
|
|
@@ -1438,6 +1896,7 @@ const en = {
|
|
|
1438
1896
|
navTypeSeparator: 'Separator',
|
|
1439
1897
|
navTypeAction: 'Action',
|
|
1440
1898
|
navTypeComponent: 'Component',
|
|
1899
|
+
navTypeDoc: 'Doc',
|
|
1441
1900
|
navEditIcon: 'Edit icon',
|
|
1442
1901
|
navToggleVisible: 'Toggle visibility',
|
|
1443
1902
|
navHidden: 'Hidden',
|
|
@@ -1515,11 +1974,8 @@ const en = {
|
|
|
1515
1974
|
defaultValue: 'Default Value',
|
|
1516
1975
|
placeholder: 'Placeholder',
|
|
1517
1976
|
referenceTo: 'Reference To',
|
|
1518
|
-
formula: 'Formula',
|
|
1519
1977
|
options: 'Options',
|
|
1520
1978
|
addOption: 'Add Option',
|
|
1521
|
-
validationRules: 'Validation Rules',
|
|
1522
|
-
addRule: 'Add Rule',
|
|
1523
1979
|
systemBadge: 'System',
|
|
1524
1980
|
ungrouped: 'General',
|
|
1525
1981
|
deleteConfirmTitle: 'Delete Field?',
|
|
@@ -1538,25 +1994,61 @@ const en = {
|
|
|
1538
1994
|
},
|
|
1539
1995
|
},
|
|
1540
1996
|
console: {
|
|
1997
|
+
// The fixed crumb `AppHeader`'s `studio` variant draws on the Studio front
|
|
1998
|
+
// door (objectui#11863), as `organizations.title` is the `orgs` variant's.
|
|
1999
|
+
// A product name, which every pack writes as is.
|
|
2000
|
+
studio: {
|
|
2001
|
+
title: 'Studio',
|
|
2002
|
+
// What a principal without `studio.access` reads at the Studio URL they
|
|
2003
|
+
// opened (objectui#12035), in place of the silent redirect home.
|
|
2004
|
+
accessRequired: 'You need Studio access to open Studio.',
|
|
2005
|
+
},
|
|
1541
2006
|
saveAdvisoryTitle: 'Saved — the authoring check raised {{count}} advisory finding(s)',
|
|
2007
|
+
saveAdvisoryTitle_one: 'Saved — the authoring check raised {{count}} advisory finding',
|
|
2008
|
+
saveAdvisoryTitle_other: 'Saved — the authoring check raised {{count}} advisory findings',
|
|
2009
|
+
publishAdvisoryTitle: 'Published — the authoring check raised {{count}} advisory finding(s)',
|
|
2010
|
+
publishAdvisoryTitle_one: 'Published — the authoring check raised {{count}} advisory finding',
|
|
2011
|
+
publishAdvisoryTitle_other: 'Published — the authoring check raised {{count}} advisory findings',
|
|
2012
|
+
importMappingsUnavailable: 'Saved import mappings for {{object}} could not be loaded',
|
|
2013
|
+
importMappingsRefused: 'The server refused this request, so this list is empty because it could not be read — not because nothing is registered. Sign in again, or ask an administrator for access.',
|
|
2014
|
+
importMappingsUnreadable: 'This list is empty because it could not be read, not because nothing is registered. Try again, and report this if it keeps happening.',
|
|
2015
|
+
savedViewsUnavailable: 'Saved views for {{object}} could not be loaded',
|
|
2016
|
+
savedViewsRefused: 'The server refused this request, so this list is empty because it could not be read — not because this object has no saved views. Sign in again, or ask an administrator for access.',
|
|
2017
|
+
savedViewsUnreadable: 'This list is empty because it could not be read, not because this object has no saved views. Try again, and report this if it keeps happening.',
|
|
1542
2018
|
title: 'ObjectOS',
|
|
1543
|
-
initializing: '
|
|
2019
|
+
initializing: 'Opening your console…',
|
|
2020
|
+
skipToContent: 'Skip to content',
|
|
1544
2021
|
search: 'Search…',
|
|
1545
2022
|
breadcrumb: {
|
|
1546
|
-
dashboards: 'Dashboards',
|
|
1547
|
-
pages: 'Pages',
|
|
1548
|
-
reports: 'Reports',
|
|
1549
2023
|
system: 'System',
|
|
2024
|
+
// The Setup system page segment after `System` (objectui#10900).
|
|
2025
|
+
marketplace: 'Marketplace',
|
|
2026
|
+
// The console app's own `system/*` pages after `System` (objectui#10969).
|
|
2027
|
+
settings: 'Settings',
|
|
2028
|
+
apps: 'Apps',
|
|
2029
|
+
profile: 'Profile',
|
|
2030
|
+
approvals: 'Approvals',
|
|
2031
|
+
aiApprovals: 'AI Approvals',
|
|
2032
|
+
auditLog: 'Audit Log',
|
|
1550
2033
|
},
|
|
1551
2034
|
nav: {
|
|
1552
2035
|
pinItem: 'Pin {{name}}',
|
|
1553
2036
|
unpinItem: 'Unpin {{name}}',
|
|
1554
|
-
dragToReorder: 'Drag to reorder',
|
|
1555
2037
|
favorites: 'Favorites',
|
|
2038
|
+
launcherLabel: 'App launcher',
|
|
2039
|
+
menuLabel: 'App navigation',
|
|
2040
|
+
menuEmpty: 'This app has no navigation entries you can open.',
|
|
2041
|
+
// objectui#12427 — the ⋯ menu a sidebar entry shows on hover (`SidebarItemMenu`).
|
|
2042
|
+
itemMenu: 'More actions for {{name}}',
|
|
2043
|
+
openInNewTab: 'Open in new tab',
|
|
2044
|
+
copyLink: 'Copy link',
|
|
2045
|
+
linkCopied: 'Link copied to clipboard',
|
|
2046
|
+
linkCopyFailed: 'Failed to copy link',
|
|
2047
|
+
design: 'Design',
|
|
1556
2048
|
},
|
|
1557
2049
|
settingsHub: {
|
|
1558
2050
|
title: 'Settings',
|
|
1559
|
-
subtitle: 'Configure your
|
|
2051
|
+
subtitle: 'Configure your system, integrations, and feature flags.',
|
|
1560
2052
|
loadError: 'Failed to load settings',
|
|
1561
2053
|
empty: 'No settings registered. Plugins can register settings manifests via the SettingsService.',
|
|
1562
2054
|
settingsCount: '{{n}} settings',
|
|
@@ -1564,7 +2056,7 @@ const en = {
|
|
|
1564
2056
|
// Section headers, keyed by the manifest `category` value. Unknown
|
|
1565
2057
|
// (plugin-authored) categories fall back to the literal category string.
|
|
1566
2058
|
categories: {
|
|
1567
|
-
Workspace: '
|
|
2059
|
+
Workspace: 'General',
|
|
1568
2060
|
Communication: 'Communication',
|
|
1569
2061
|
Security: 'Security',
|
|
1570
2062
|
Infrastructure: 'Infrastructure',
|
|
@@ -1600,18 +2092,22 @@ const en = {
|
|
|
1600
2092
|
discard: 'Discard',
|
|
1601
2093
|
saveChanges: 'Save changes',
|
|
1602
2094
|
// Save-bar counter. A REAL i18next plural family, not an English-only
|
|
1603
|
-
// `change(s)
|
|
1604
|
-
// elsewhere in this file.
|
|
2095
|
+
// `change(s)`.
|
|
1605
2096
|
//
|
|
1606
|
-
//
|
|
1607
|
-
//
|
|
1608
|
-
//
|
|
1609
|
-
// `
|
|
1610
|
-
// without this base key `ru` would render ENGLISH at counts 2-20.
|
|
1611
|
-
// `all-locales-key-parity.test.ts` owns that rule.
|
|
2097
|
+
// i18next asks `Intl.PluralRules` for the one suffix a language needs, so
|
|
2098
|
+
// each pack spells out every category its language selects — `ru` has
|
|
2099
|
+
// four, `ar` six (objectui#11432) — and keeps the base key
|
|
2100
|
+
// (objectui#3863). `all-locales-key-parity.test.ts` owns both rules.
|
|
1612
2101
|
unsavedCount: '{{count}} unsaved changes',
|
|
1613
2102
|
unsavedCount_one: '{{count}} unsaved change',
|
|
1614
2103
|
unsavedCount_other: '{{count}} unsaved changes',
|
|
2104
|
+
// The toast of a save the server refused field by field (objectui#13146).
|
|
2105
|
+
// `{{settings}}` is the refused settings' labels, as their rows draw them,
|
|
2106
|
+
// joined with `validation.formInvalidJoiner`; each row shows its own
|
|
2107
|
+
// reason, so the toast names the settings and gives no reason.
|
|
2108
|
+
fieldErrorsToast: '{{count}} settings need attention: {{settings}}',
|
|
2109
|
+
fieldErrorsToast_one: '{{count}} setting needs attention: {{settings}}',
|
|
2110
|
+
fieldErrorsToast_other: '{{count}} settings need attention: {{settings}}',
|
|
1615
2111
|
// The fail-closed crypto refusal (objectstack#8396). objectui#4579 added
|
|
1616
2112
|
// these as English literals on purpose — routing one string through i18n
|
|
1617
2113
|
// would have left a single translated string among a dozen hardcoded
|
|
@@ -1623,13 +2119,38 @@ const en = {
|
|
|
1623
2119
|
cryptoRefusalNoSubject: 'The declared-encrypted value was refused, so nothing was written.',
|
|
1624
2120
|
cryptoRefusalToast: 'Cannot encrypt secrets: {{subject}}',
|
|
1625
2121
|
cryptoRefusalToastNoSubject: 'Cannot encrypt secrets',
|
|
2122
|
+
// The source badge beside a settings row's label (objectui#12694): the
|
|
2123
|
+
// layer a value comes from. `{{source}}` is that layer's label, which the
|
|
2124
|
+
// server translates under `settingsCommon.sourceLabels`. One sentence per
|
|
2125
|
+
// badge, so a pack puts the layer where its own grammar wants it.
|
|
2126
|
+
sourceBadgeInherited: 'Inherited from {{source}}',
|
|
2127
|
+
sourceBadgeOverrides: 'Overrides {{source}}',
|
|
2128
|
+
// The action beside an `Overrides` badge (objectui#13145): it clears this
|
|
2129
|
+
// layer's value in the draft, and Save sends it as `null` (unset), so the
|
|
2130
|
+
// row falls back to the value the layer above carries.
|
|
2131
|
+
resetToDefault: 'Reset to default',
|
|
2132
|
+
// The chips on a settings row's header (objectui#12821): the env-lock
|
|
2133
|
+
// chip and the title it shows when the server sends no reason, and the
|
|
2134
|
+
// `Deprecated` chip, with `{{replacedBy}}` the key that replaces it.
|
|
2135
|
+
// `unsupportedSpecifierType` is the row drawn for a specifier type the
|
|
2136
|
+
// page has no control for, `{{type}}` that type.
|
|
2137
|
+
envLockBadge: 'Locked by env',
|
|
2138
|
+
envLockBadgeTitle: 'Pinned by environment variable — cannot be edited from the UI.',
|
|
2139
|
+
deprecatedBadge: 'Deprecated',
|
|
2140
|
+
deprecatedBadgeReplacedBy: 'Deprecated → {{replacedBy}}',
|
|
2141
|
+
unsupportedSpecifierType: 'Unsupported specifier type: {{type}}',
|
|
2142
|
+
},
|
|
2143
|
+
// The one-time workspace-timezone prompt (objectui#11758): asked of an
|
|
2144
|
+
// administrator while `localization.timezone` is still the manifest default.
|
|
2145
|
+
// `{{current}}` is that default, `{{zone}}` the zone the admin confirmed.
|
|
2146
|
+
workspaceTimezonePrompt: {
|
|
2147
|
+
title: 'Set the system timezone',
|
|
2148
|
+
description: 'This system still uses the platform default timezone, {{current}}. The system timezone decides what "today" means in formulas, how reports group dates and how dates and times are shown, for everyone in the system. Your browser timezone is filled in below.',
|
|
2149
|
+
laterHint: 'You can change it at any time on the Settings page.',
|
|
2150
|
+
decline: 'Keep the default',
|
|
2151
|
+
confirm: 'Set timezone',
|
|
2152
|
+
saved: 'System timezone set to {{zone}}',
|
|
1626
2153
|
},
|
|
1627
|
-
loadingSteps: {
|
|
1628
|
-
connecting: 'Connecting to data source',
|
|
1629
|
-
loadingConfig: 'Loading configuration',
|
|
1630
|
-
preparingWorkspace: 'Preparing workspace',
|
|
1631
|
-
},
|
|
1632
|
-
loadingHint: 'Setting up a new environment can take a few moments.',
|
|
1633
2154
|
error: {
|
|
1634
2155
|
connectionFailed: 'Cannot connect to server',
|
|
1635
2156
|
serverUnreachable: 'The server at {{url}} is unreachable.',
|
|
@@ -1655,21 +2176,20 @@ const en = {
|
|
|
1655
2176
|
groups: {
|
|
1656
2177
|
general: 'General',
|
|
1657
2178
|
navigation: 'Navigation',
|
|
1658
|
-
dataViews: 'Data Views',
|
|
1659
2179
|
aiChat: 'AI assistant',
|
|
1660
|
-
preferences: 'Preferences',
|
|
1661
2180
|
},
|
|
1662
2181
|
openCommandPalette: 'Open command palette',
|
|
1663
2182
|
showShortcuts: 'Show keyboard shortcuts',
|
|
1664
2183
|
closeDialog: 'Close dialog / panel',
|
|
1665
2184
|
toggleSidebar: 'Toggle sidebar',
|
|
1666
|
-
focusSearch: 'Focus search',
|
|
1667
|
-
createRecord: 'Create new record',
|
|
1668
|
-
refreshData: 'Refresh data',
|
|
1669
|
-
editRecord: 'Edit selected record',
|
|
1670
2185
|
newChat: 'New chat',
|
|
1671
2186
|
toggleChatsList: 'Toggle conversations list',
|
|
1672
|
-
|
|
2187
|
+
goHome: 'Back to home',
|
|
2188
|
+
},
|
|
2189
|
+
reportIndex: {
|
|
2190
|
+
title: 'Reports',
|
|
2191
|
+
emptyTitle: 'No reports',
|
|
2192
|
+
emptyDescription: 'This app has no reports you can open.',
|
|
1673
2193
|
},
|
|
1674
2194
|
commandPalette: {
|
|
1675
2195
|
title: 'Command palette',
|
|
@@ -1679,6 +2199,8 @@ const en = {
|
|
|
1679
2199
|
records: 'Records',
|
|
1680
2200
|
recentRecords: 'Recently viewed',
|
|
1681
2201
|
objects: 'Objects',
|
|
2202
|
+
packages: 'Packages',
|
|
2203
|
+
flows: 'Flows',
|
|
1682
2204
|
dashboards: 'Dashboards',
|
|
1683
2205
|
pages: 'Pages',
|
|
1684
2206
|
reports: 'Reports',
|
|
@@ -1702,13 +2224,27 @@ const en = {
|
|
|
1702
2224
|
},
|
|
1703
2225
|
usage: {
|
|
1704
2226
|
title: 'AI usage',
|
|
1705
|
-
|
|
1706
|
-
|
|
2227
|
+
// objectui#11658 — the popover's ONE figure: the share of the single
|
|
2228
|
+
// AI pool already used (a formatted percentage, never a token count).
|
|
2229
|
+
// It replaced the build / data-Q&A split, which could not attribute a
|
|
2230
|
+
// single-composer turn honestly.
|
|
2231
|
+
poolUsed: '{{percent}} used',
|
|
1707
2232
|
statusOk: 'Plenty left',
|
|
1708
2233
|
statusLow: 'Running low',
|
|
1709
2234
|
statusFull: 'Limit reached',
|
|
1710
2235
|
resetsDaily: 'Resets tonight',
|
|
1711
2236
|
resetsMonthly: 'Resets next cycle',
|
|
2237
|
+
// `resetKind: 'weekly'` (free plan's rolling 7-day window, cloud PR
|
|
2238
|
+
// #1852): "N days" (or "N hours" inside the final day). A REAL
|
|
2239
|
+
// i18next plural family — see the `unsavedCount` note above — so the
|
|
2240
|
+
// BASE key carries no suffix and must stay in every pack's lookup
|
|
2241
|
+
// chain (`all-locales-key-parity.test.ts`'s base-key rule).
|
|
2242
|
+
resetsWeeklyDays: 'Resets in {{count}} days',
|
|
2243
|
+
resetsWeeklyDays_one: 'Resets in {{count}} day',
|
|
2244
|
+
resetsWeeklyDays_other: 'Resets in {{count}} days',
|
|
2245
|
+
resetsWeeklyHours: 'Resets in {{count}} hours',
|
|
2246
|
+
resetsWeeklyHours_one: 'Resets in {{count}} hour',
|
|
2247
|
+
resetsWeeklyHours_other: 'Resets in {{count}} hours',
|
|
1712
2248
|
ctaUpgrade: 'Upgrade to keep going',
|
|
1713
2249
|
ctaTopUp: 'Add credits to continue',
|
|
1714
2250
|
ariaLabel: 'AI usage: {{status}}',
|
|
@@ -1721,6 +2257,38 @@ const en = {
|
|
|
1721
2257
|
share: 'Share',
|
|
1722
2258
|
shareTitle: 'Share this conversation',
|
|
1723
2259
|
shareDisabledTitle: 'Start chatting to enable sharing',
|
|
2260
|
+
// The build conversation's Build Doctor button (its accessible name,
|
|
2261
|
+
// and its tooltip enabled / before the first message) and the drawer
|
|
2262
|
+
// title it opens (objectui#10900).
|
|
2263
|
+
buildDoctor: 'Build Doctor',
|
|
2264
|
+
buildDoctorTitle: 'Build Doctor — what actually landed?',
|
|
2265
|
+
buildDoctorDisabledTitle: 'Send a message first',
|
|
2266
|
+
// The Build Doctor drawer's body (objectui#10969): its description, the
|
|
2267
|
+
// loading and not-found states, the summary line, the verdict, and each
|
|
2268
|
+
// section's title and hint. What the report itself carries (tool, artifact
|
|
2269
|
+
// and status names, timeline text) is data and stays verbatim.
|
|
2270
|
+
buildDoctorDrawer: {
|
|
2271
|
+
description: 'What the agent claimed vs what is actually live. Read-only diagnostic.',
|
|
2272
|
+
reconciling: 'Reconciling…',
|
|
2273
|
+
notAvailable: 'Not available — the conversation was not found or you are not authorized.',
|
|
2274
|
+
untitled: '(untitled)',
|
|
2275
|
+
summary: '{{turns}} turn(s) · {{messages}} msgs · {{tokens}} tok · {{seconds}}s LLM',
|
|
2276
|
+
allLive: 'All {{count}} attempted change(s) are live — nothing evaporated.',
|
|
2277
|
+
discrepancies: "{{count}} discrepancy(ies) — what the chat said doesn't match what's live.",
|
|
2278
|
+
orphanedTitle: 'Proposed but never applied',
|
|
2279
|
+
orphanedHint: 'A confirm card the agent proposed but no later turn applied — the change silently evaporated.',
|
|
2280
|
+
missingTitle: 'Claimed but missing',
|
|
2281
|
+
missingHint: "A tool result said it was applied, but the artifact isn't live in sys_metadata.",
|
|
2282
|
+
toolErrorsTitle: 'Tool errors',
|
|
2283
|
+
toolErrorsHint: 'Tool calls that returned an error during the build.',
|
|
2284
|
+
verifyTitle: 'Build check (verify_build)',
|
|
2285
|
+
yourApp: 'Your app:',
|
|
2286
|
+
noIssues: '0 issues',
|
|
2287
|
+
issueCount: '{{count}} issue(s)',
|
|
2288
|
+
platformNoise: '{{count}} platform sys_* finding(s) hidden',
|
|
2289
|
+
pendingActions: 'Pending actions',
|
|
2290
|
+
timeline: 'Timeline ({{count}})',
|
|
2291
|
+
},
|
|
1724
2292
|
newChat: 'New',
|
|
1725
2293
|
searchChats: 'Search chats…',
|
|
1726
2294
|
noChatsYet: 'No chats yet',
|
|
@@ -1743,14 +2311,39 @@ const en = {
|
|
|
1743
2311
|
liveCanvasUnlisted: 'Live app — {{app}} (unlisted until published)',
|
|
1744
2312
|
loadingAgents: 'Loading agents…',
|
|
1745
2313
|
askAnything: 'Ask anything…',
|
|
2314
|
+
askOrChangeApp: 'Ask about your data, or ask me to change this app…',
|
|
2315
|
+
describeAppToBuild: 'Describe the app you want to build, or what to change…',
|
|
1746
2316
|
emptyTitle: 'Start a conversation',
|
|
1747
2317
|
emptyDescription: 'Ask anything — the assistant has access to your current app context.',
|
|
1748
2318
|
switchAssistant: 'Switch assistant',
|
|
1749
2319
|
chooseAgent: 'Choose assistant…',
|
|
2320
|
+
// objectui#8329 — the maker's empty-state prose, and the FIRST sentence a
|
|
2321
|
+
// new user reads on the build surface (it sits above the start chips).
|
|
2322
|
+
// Same ADR-0112 v1 boundary the chips answer to (cloud#1984 /
|
|
2323
|
+
// objectui#7709 for the starters, cloud#2022 for the model's own closing
|
|
2324
|
+
// suggestions): these two descriptions are the product PROMISING, so they
|
|
2325
|
+
// may only name what v1 BUILDS — objects, fields, views, pages,
|
|
2326
|
+
// dashboards, sample data, apps and navigation. `build.description` used
|
|
2327
|
+
// to offer "an app or workflow … objects, screens and automations" and
|
|
2328
|
+
// `editApp.description` "… view or automation"; v1 has no flows, actions
|
|
2329
|
+
// or schedules, so a user who took either at its word was refused
|
|
2330
|
+
// outright — the worst possible answer to the first line on the page.
|
|
2331
|
+
//
|
|
2332
|
+
// NOT the same thing as the platform's manual automation surfaces, which
|
|
2333
|
+
// are real and stay as they are: `home.build.subtitle` (that card opens
|
|
2334
|
+
// Studio, which does author flows), `engine.studio.landing.description`,
|
|
2335
|
+
// `packagedAutomation.*` and the
|
|
2336
|
+
// marketplace `automation` category. The boundary is v1 AI AUTHORING, not
|
|
2337
|
+
// the word "automation".
|
|
2338
|
+
//
|
|
2339
|
+
// REVERT both sentences when ADR-0112 v2 re-adds flows and actions — same
|
|
2340
|
+
// line of the version roadmap as the chips. Every pack's wording is
|
|
2341
|
+
// guarded, in its own script, by
|
|
2342
|
+
// `packages/i18n/src/__tests__/makerEmptyState-v1-scope-8329.test.ts`.
|
|
1750
2343
|
empty: {
|
|
1751
2344
|
build: {
|
|
1752
2345
|
title: 'Build with AI',
|
|
1753
|
-
description: 'Describe an app
|
|
2346
|
+
description: 'Describe an app in plain language — I draft the objects, screens and sample data, then you review and publish.',
|
|
1754
2347
|
},
|
|
1755
2348
|
ask: {
|
|
1756
2349
|
title: 'Ask your data',
|
|
@@ -1759,17 +2352,26 @@ const en = {
|
|
|
1759
2352
|
editApp: {
|
|
1760
2353
|
title: 'Editing “{{app}}”',
|
|
1761
2354
|
titleGeneric: 'Edit this app',
|
|
1762
|
-
description: 'What would you like to change? I’ll modify this app in place — add a field, object, view or
|
|
2355
|
+
description: 'What would you like to change? I’ll modify this app in place — add a field, object, view or dashboard, or adjust what’s already there.',
|
|
1763
2356
|
},
|
|
1764
2357
|
},
|
|
1765
2358
|
clearConversation: 'Clear',
|
|
1766
2359
|
sendHint: 'to send',
|
|
2360
|
+
newlineHint: 'for a new line',
|
|
1767
2361
|
agentActivity: 'Agent activity',
|
|
1768
2362
|
toolCompleted: 'Completed',
|
|
1769
2363
|
toolRunning: 'Running',
|
|
1770
2364
|
toolAwaitingApproval: 'Awaiting approval',
|
|
1771
2365
|
toolFailed: 'Failed',
|
|
1772
2366
|
toolDetailsHidden: 'Tool inputs and raw results are hidden in this view.',
|
|
2367
|
+
// objectui#11667 — the inline HITL deny reason (stored on the pending
|
|
2368
|
+
// action as `rejection_reason`, read as prose) and the ADR-0057 P4
|
|
2369
|
+
// "Open in Builder" handoff card. The card's Approve / Reject buttons
|
|
2370
|
+
// borrow `aiApprovals.approveAndExecute` / `aiApprovals.reject`.
|
|
2371
|
+
toolDenyReason: 'Operator rejected from chat',
|
|
2372
|
+
builderHandoffTitle: 'Build this in the Builder',
|
|
2373
|
+
builderHandoffOpen: 'Open in Builder →',
|
|
2374
|
+
builderHandoffSuperseded: 'A newer request is available',
|
|
1773
2375
|
copy: 'Copy',
|
|
1774
2376
|
copied: 'Copied',
|
|
1775
2377
|
regenerate: 'Regenerate',
|
|
@@ -1786,7 +2388,7 @@ const en = {
|
|
|
1786
2388
|
publishOk: 'Published — objects are now live.',
|
|
1787
2389
|
seedWarn: 'Published, but some sample data failed to load.',
|
|
1788
2390
|
openBuiltApp: 'Open app',
|
|
1789
|
-
|
|
2391
|
+
viewBuiltAppInStudio: 'View in Studio',
|
|
1790
2392
|
previewDraft: 'Preview',
|
|
1791
2393
|
previewApp: 'Preview app',
|
|
1792
2394
|
resizeSplit: 'Resize chat and preview',
|
|
@@ -1843,23 +2445,41 @@ const en = {
|
|
|
1843
2445
|
recentRecords: 'List the 5 most recently created records.',
|
|
1844
2446
|
recordCounts: 'Count records for each object.',
|
|
1845
2447
|
},
|
|
2448
|
+
// cloud#1984 — these five chips are the maker's own recommendations, so
|
|
2449
|
+
// they may only ask for what ADR-0112 v1 BUILDS: objects, fields, views
|
|
2450
|
+
// (grid/kanban/calendar/gallery), pages, dashboards and sample data. No
|
|
2451
|
+
// wording that promises autonomous behaviour (alert / remind / notify /
|
|
2452
|
+
// automate / status workflow) — v1 has no flows, actions or schedules, and
|
|
2453
|
+
// the model silently degrades such a request into a board or a filtered
|
|
2454
|
+
// view, so the chip would promise an alert and deliver a page. REVERT to
|
|
2455
|
+
// the automation wording when ADR-0112 v2 re-adds flows and actions.
|
|
1846
2456
|
metadataAssistant: {
|
|
1847
|
-
buildCrm: 'Build a sales CRM — customers, contacts, and a
|
|
1848
|
-
buildApp: 'Create a project tracker — projects, tasks with owners and due dates,
|
|
1849
|
-
buildFlow: 'Design a support desk — tickets with priority, a status
|
|
1850
|
-
buildInventory: 'Build an inventory app — products, stock levels, suppliers, and
|
|
1851
|
-
buildRecruiting: 'Make an applicant tracker — candidates, open roles, interview
|
|
2457
|
+
buildCrm: 'Build a sales CRM — customers, contacts, and deals with a stage field, plus a dashboard that totals deal value by stage.',
|
|
2458
|
+
buildApp: 'Create a project tracker — projects, tasks with owners and due dates, a board grouped by status, and a calendar of due dates.',
|
|
2459
|
+
buildFlow: 'Design a support desk — tickets with priority and status fields, a board grouped by status, and links to customers.',
|
|
2460
|
+
buildInventory: 'Build an inventory app — products, stock levels, suppliers, and a view that filters the items below their reorder point.',
|
|
2461
|
+
buildRecruiting: 'Make an applicant tracker — candidates, open roles, an interview-stage field, and a board grouped by stage.',
|
|
1852
2462
|
},
|
|
1853
2463
|
generic: {
|
|
1854
2464
|
help: 'What can you help me with?',
|
|
1855
2465
|
availableObjects: 'List the available data objects.',
|
|
1856
2466
|
recentActivity: 'Summarize my recent activity.',
|
|
1857
2467
|
},
|
|
2468
|
+
// objectui#7709 — the edit-mode starters, shown when the maker is bound
|
|
2469
|
+
// to an EXISTING app (`?package=`). Same rule as the five above: they
|
|
2470
|
+
// may only ask for what ADR-0112 v1 BUILDS. The fourth chip used to be
|
|
2471
|
+
// `addAutomation` ("an approval, a status flow, or a notification") and
|
|
2472
|
+
// every capability it named is refused by v1 (cloud#1956 / PR #1970), so
|
|
2473
|
+
// it now asks for sample data — `seed` IS on v1's whitelist, and having
|
|
2474
|
+
// no data is what an existing app most often lacks. REVERT: when
|
|
2475
|
+
// ADR-0112 v2 re-adds flows and actions, THIS chip's automation wording
|
|
2476
|
+
// comes back as `addAutomation`; the retired string is pinned for every
|
|
2477
|
+
// pack in `packages/i18n/src/__tests__/makerEditChips-v1-scope-7709.test.ts`.
|
|
1858
2478
|
editApp: {
|
|
1859
2479
|
addField: 'Add a field to one of the objects.',
|
|
1860
2480
|
addObject: 'Add a new object and relate it to an existing one.',
|
|
1861
2481
|
addDashboard: 'Add a dashboard for the key metrics.',
|
|
1862
|
-
|
|
2482
|
+
addSampleData: 'Fill the existing objects with realistic sample records so I can demo the app.',
|
|
1863
2483
|
},
|
|
1864
2484
|
},
|
|
1865
2485
|
// objectui#3546 slice four — the AI console surfaces: the /ai chat page's app switcher,
|
|
@@ -1905,6 +2525,8 @@ const en = {
|
|
|
1905
2525
|
collapse: 'Collapse chat',
|
|
1906
2526
|
maximize: 'Open full page',
|
|
1907
2527
|
open: 'Open assistant',
|
|
2528
|
+
// objectui#11666 — the launchers' marker while a proposed plan awaits approval.
|
|
2529
|
+
planAwaitingApproval: 'A proposed plan is waiting for your approval',
|
|
1908
2530
|
},
|
|
1909
2531
|
group: {
|
|
1910
2532
|
today: 'Today',
|
|
@@ -1914,6 +2536,29 @@ const en = {
|
|
|
1914
2536
|
older: 'Older',
|
|
1915
2537
|
},
|
|
1916
2538
|
},
|
|
2539
|
+
// objectui#9954 — the environment admin's read-rate report (cloud#2333).
|
|
2540
|
+
// Two anomalous cases, two sets of words: an ABSENT `readsPerWrite` means the
|
|
2541
|
+
// environment wrote nothing at all, so the ratio is unbounded — the most
|
|
2542
|
+
// severe reading, and never a missing number. `{{threshold}}` always comes
|
|
2543
|
+
// from the wire; this repo holds no copy of the line. Report only — the copy
|
|
2544
|
+
// states that nothing is limited or blocked, and must keep doing so.
|
|
2545
|
+
readRate: {
|
|
2546
|
+
ratioTitle: 'Unusual read volume in this system',
|
|
2547
|
+
ratio: 'Reads are running at {{ratio}} rows for every row written. The platform flags anything above {{threshold}}. Nothing is limited or blocked; this is a report so the read pattern can be reviewed.',
|
|
2548
|
+
noWritesTitle: 'Reads with no writes at all in this system',
|
|
2549
|
+
noWrites: 'Rows are being read while none at all are being written, so the read rate has no upper bound. This is the most severe reading. The platform flags anything above {{threshold}}. Nothing is limited or blocked; this is a report so the read pattern can be reviewed.',
|
|
2550
|
+
},
|
|
2551
|
+
// objectui#10439 — the environment admin's storage-capacity banner (cloud#2135).
|
|
2552
|
+
// Raised by the tenant runtime's own verdict on `/api/v1/usage/storage`: `warn`
|
|
2553
|
+
// (80% and up) or `blocked` (uploads and bulk imports refused). `{{used}}` and
|
|
2554
|
+
// `{{limit}}` are that response's `usedMb` / `limitMb`, already formatted.
|
|
2555
|
+
storageUsage: {
|
|
2556
|
+
warningTitle: 'Storage is filling up',
|
|
2557
|
+
warning: '{{used}} MB of {{limit}} MB used. Uploads and imports pause once storage is full.',
|
|
2558
|
+
blockedTitle: 'Storage is full: uploads and imports are paused',
|
|
2559
|
+
blocked: '{{used}} MB of {{limit}} MB used. Existing data is untouched, and reading, exporting and editing single records still work.',
|
|
2560
|
+
upgrade: 'Upgrade to continue',
|
|
2561
|
+
},
|
|
1917
2562
|
errors: {
|
|
1918
2563
|
somethingWentWrong: 'Something went wrong',
|
|
1919
2564
|
unexpectedError: 'An unexpected error occurred while rendering this view.',
|
|
@@ -1964,6 +2609,7 @@ const en = {
|
|
|
1964
2609
|
objectNotFound: 'Object Not Found',
|
|
1965
2610
|
objectNotFoundDescription: 'The object "{{objectName}}" does not exist in the current configuration.',
|
|
1966
2611
|
objectNotFoundHint: 'Check your app navigation settings or select a different object from the sidebar.',
|
|
2612
|
+
objectPackageDisabled: 'The object "{{objectName}}" belongs to a package that is disabled, so it is not being served.',
|
|
1967
2613
|
filterOrNotSavable: 'This filter uses OR between conditions, which a saved view cannot store yet. It still applies to this list — remove the OR grouping to save it to the view.',
|
|
1968
2614
|
filterNestedNotSavable: 'This filter uses nested condition groups, which a saved view cannot store. Flatten it to a single list of conditions to save it to the view.',
|
|
1969
2615
|
systemViewReadonly: 'System view defined in code — read-only.',
|
|
@@ -1971,6 +2617,8 @@ const en = {
|
|
|
1971
2617
|
// (rename / pin / set-as-default / configure), so the copy has to cover
|
|
1972
2618
|
// any change to a built-in view rather than name one operation.
|
|
1973
2619
|
cannotEditMetaView: 'This view is built in and defined in code — it cannot be changed.',
|
|
2620
|
+
resetView: 'Reset view',
|
|
2621
|
+
resetViewTitle: 'Set this view back to its own sort, filters and column widths. Only yours change.',
|
|
1974
2622
|
cannotDeleteMetaView: 'This view is built in and defined in code — it cannot be deleted.',
|
|
1975
2623
|
expandToPage: 'Open as full page',
|
|
1976
2624
|
allRecords: 'All Records',
|
|
@@ -1978,14 +2626,17 @@ const en = {
|
|
|
1978
2626
|
import: 'Import',
|
|
1979
2627
|
importTitle: 'Import from CSV',
|
|
1980
2628
|
importedToast: 'Imported {{count}} row(s).',
|
|
2629
|
+
importedToast_one: 'Imported {{count}} row.',
|
|
2630
|
+
importedToast_other: 'Imported {{count}} rows.',
|
|
1981
2631
|
importedWithSkipped: 'Imported {{ok}} row(s); skipped {{skipped}}.',
|
|
1982
2632
|
configureView: 'Configure View',
|
|
1983
|
-
toolbar: 'Toolbar',
|
|
1984
2633
|
toolbarEnabledCount: '{{count}} of {{total}} enabled',
|
|
1985
2634
|
searchFields: 'Search fields…',
|
|
1986
2635
|
title: 'Title',
|
|
1987
2636
|
viewType: 'View type',
|
|
1988
2637
|
recordCount: '{{count}} records',
|
|
2638
|
+
recordCount_one: '{{count}} record',
|
|
2639
|
+
recordCount_other: '{{count}} records',
|
|
1989
2640
|
save: 'Save',
|
|
1990
2641
|
discard: 'Discard',
|
|
1991
2642
|
createView: 'Create View',
|
|
@@ -1996,6 +2647,8 @@ const en = {
|
|
|
1996
2647
|
deleteViewTitle: 'Delete view',
|
|
1997
2648
|
deleteViewConfirm: 'Are you sure you want to delete the view "{{name}}"? This cannot be undone.',
|
|
1998
2649
|
bulkDeleteConfirm: 'Delete {{count}} selected records? This cannot be undone.',
|
|
2650
|
+
bulkDeleteConfirm_one: 'Delete {{count}} selected record? This cannot be undone.',
|
|
2651
|
+
bulkDeleteConfirm_other: 'Delete {{count}} selected records? This cannot be undone.',
|
|
1999
2652
|
duplicateViewName: 'A view with this name already exists.',
|
|
2000
2653
|
viewTypeGrid: 'Grid',
|
|
2001
2654
|
viewTypeGridDesc: 'A spreadsheet-style table of records.',
|
|
@@ -2048,16 +2701,25 @@ const en = {
|
|
|
2048
2701
|
chartTypePie: 'Pie chart',
|
|
2049
2702
|
chartTypeArea: 'Area chart',
|
|
2050
2703
|
chartTypeScatter: 'Scatter chart',
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2704
|
+
dataset: 'Dataset',
|
|
2705
|
+
datasetHelp: 'The chart reads its numbers from this dataset of the object.',
|
|
2706
|
+
chartMeasure: 'Measure',
|
|
2707
|
+
chartMeasureHelp: 'The dataset measure plotted on the value axis.',
|
|
2708
|
+
chartDimension: 'Dimension',
|
|
2709
|
+
chartDimensionHelp: 'The dataset dimension the values are grouped by (optional).',
|
|
2710
|
+
viewTypeUnavailableDataset: 'This object exposes no dataset to chart.',
|
|
2711
|
+
noDatasetMeasure: 'This dataset declares no measure to chart.',
|
|
2056
2712
|
endDateField: 'End date field',
|
|
2057
2713
|
ufTabs: 'Tabs',
|
|
2058
2714
|
ufAddField: '+ Add filter field…',
|
|
2059
2715
|
ufShowAllRecords: 'Show "All records" tab',
|
|
2060
2716
|
},
|
|
2717
|
+
// The runtime draft bar's Publish / Discard refusals (RuntimeDraftBar,
|
|
2718
|
+
// objectui#11583). The toast's description is the refusal itself.
|
|
2719
|
+
runtimeDraft: {
|
|
2720
|
+
publishFailed: 'Publish failed',
|
|
2721
|
+
discardFailed: 'Discard failed',
|
|
2722
|
+
},
|
|
2061
2723
|
localeSwitcher: {
|
|
2062
2724
|
label: 'Language',
|
|
2063
2725
|
},
|
|
@@ -2078,7 +2740,7 @@ const en = {
|
|
|
2078
2740
|
signingIn: 'Signing you in…',
|
|
2079
2741
|
ssoHandoff: 'Continue to {{target}}',
|
|
2080
2742
|
// Phone/OTP sign-in labels. `LoginForm` interpolates `{seconds}` with a
|
|
2081
|
-
// literal `.replace()` of its own (
|
|
2743
|
+
// literal `.replace('{seconds}', …)` of its own (in `LoginForm`),
|
|
2082
2744
|
// so those SINGLE braces must survive translation — i18next never sees
|
|
2083
2745
|
// them.
|
|
2084
2746
|
emailOrPhoneLabel: 'Email or phone number',
|
|
@@ -2091,10 +2753,35 @@ const en = {
|
|
|
2091
2753
|
resendOtpCountdownText: 'Resend in {seconds}s',
|
|
2092
2754
|
usePhoneOtpText: 'Sign in with verification code',
|
|
2093
2755
|
usePasswordSignInText: 'Sign in with password instead',
|
|
2756
|
+
// The social provider buttons and the divider under them
|
|
2757
|
+
// (`SocialSignInButtons`, fed through `LoginForm`'s labels).
|
|
2758
|
+
// `{provider}` is the component's own single-brace hole, filled by a
|
|
2759
|
+
// literal `.replace()` with the provider's name as the server reports
|
|
2760
|
+
// it — the same convention as `{seconds}` above (objectui#10900).
|
|
2761
|
+
socialButton: 'Continue with {provider}',
|
|
2762
|
+
orText: 'or continue with email',
|
|
2763
|
+
// SSO sign-in (objectui#12762): the SSO button, and under SSO-only
|
|
2764
|
+
// ("enforced") mode the line that says how to sign in, the break-glass
|
|
2765
|
+
// link to the password form and the link back. Each English value is
|
|
2766
|
+
// `LoginForm`'s own default for that label, so an English session reads
|
|
2767
|
+
// the same with or without the pack.
|
|
2768
|
+
ssoButton: 'Sign in with SSO',
|
|
2769
|
+
ssoOnlyDescription: "Sign in with your organization's single sign-on",
|
|
2770
|
+
usePasswordText: 'Use a password instead',
|
|
2771
|
+
backToSsoText: 'Back to single sign-on',
|
|
2772
|
+
// objectui#12600 — the console login card's own header, the password
|
|
2773
|
+
// field's reveal toggle, and the footer's legal links.
|
|
2774
|
+
welcomeTitle: 'Welcome back',
|
|
2775
|
+
welcomeDescription: 'Sign in to continue your work',
|
|
2776
|
+
showPasswordText: 'Show password',
|
|
2777
|
+
hidePasswordText: 'Hide password',
|
|
2778
|
+
footer: {
|
|
2779
|
+
privacy: 'Privacy',
|
|
2780
|
+
terms: 'Terms',
|
|
2781
|
+
},
|
|
2094
2782
|
devAdminHint: {
|
|
2095
|
-
title: '
|
|
2096
|
-
|
|
2097
|
-
dismiss: 'Dismiss',
|
|
2783
|
+
title: 'Local development instance',
|
|
2784
|
+
signIn: 'Sign in as dev admin',
|
|
2098
2785
|
},
|
|
2099
2786
|
errors: {
|
|
2100
2787
|
invalidCredentials: 'Invalid email or password. Please try again.',
|
|
@@ -2119,8 +2806,13 @@ const en = {
|
|
|
2119
2806
|
submittingButton: 'Creating account…',
|
|
2120
2807
|
hasAccountText: 'Already have an account?',
|
|
2121
2808
|
signInText: 'Sign in',
|
|
2809
|
+
// Same pair as `auth.login.socialButton` / `orText`, for sign-up.
|
|
2810
|
+
socialButton: 'Sign up with {provider}',
|
|
2811
|
+
orText: 'or continue with email',
|
|
2122
2812
|
errors: {
|
|
2123
2813
|
userExists: 'An account with this email already exists. Try signing in instead.',
|
|
2814
|
+
selfRegistrationClosed: 'Self-registration is not open on this system. Ask an administrator for an invitation.',
|
|
2815
|
+
emailDomainNotAllowed: "This email's domain is not allowed to register here. Use your organization email, or ask an administrator for an invitation.",
|
|
2124
2816
|
},
|
|
2125
2817
|
verifyInbox: {
|
|
2126
2818
|
title: 'Check your inbox',
|
|
@@ -2192,7 +2884,7 @@ const en = {
|
|
|
2192
2884
|
resentSuccess: 'Verification email sent!',
|
|
2193
2885
|
resentDescription: 'Please check your inbox and click the verification link.',
|
|
2194
2886
|
resendFailed: 'Cannot resend verification email',
|
|
2195
|
-
resendUnavailable: 'Email delivery may not be configured for this
|
|
2887
|
+
resendUnavailable: 'Email delivery may not be configured for this system. Contact support if this persists.',
|
|
2196
2888
|
signInLink: 'Go to sign in',
|
|
2197
2889
|
backToSignIn: 'Back to sign in',
|
|
2198
2890
|
backToLogin: 'Back to login',
|
|
@@ -2242,14 +2934,14 @@ const en = {
|
|
|
2242
2934
|
cancel: 'Cancel',
|
|
2243
2935
|
},
|
|
2244
2936
|
shell: {
|
|
2245
|
-
tenantHostHint: 'You are signing in to this
|
|
2937
|
+
tenantHostHint: 'You are signing in to this system',
|
|
2246
2938
|
},
|
|
2247
2939
|
// These were previously supplied only as inline `defaultValue:` args at the
|
|
2248
2940
|
// SetPasswordPage call sites, so `zh` was the only pack that could carry a
|
|
2249
2941
|
// translation. Owning them here makes the page translatable everywhere.
|
|
2250
2942
|
setPassword: {
|
|
2251
2943
|
title: 'Set a recovery password',
|
|
2252
|
-
description: 'You signed in via single sign-on. Set a local password so you can still sign in
|
|
2944
|
+
description: 'You signed in via single sign-on. Set a local password so you can still sign in directly if SSO ever becomes unavailable.',
|
|
2253
2945
|
email: 'Email',
|
|
2254
2946
|
newPassword: 'New password',
|
|
2255
2947
|
confirmPassword: 'Confirm password',
|
|
@@ -2271,6 +2963,7 @@ const en = {
|
|
|
2271
2963
|
signOut: 'Sign out instead',
|
|
2272
2964
|
password: {
|
|
2273
2965
|
title: 'Your password has expired',
|
|
2966
|
+
resetTitle: 'You must change your password',
|
|
2274
2967
|
fallbackMessage: 'Please set a new password to continue.',
|
|
2275
2968
|
current: 'Current password',
|
|
2276
2969
|
next: 'New password',
|
|
@@ -2296,6 +2989,14 @@ const en = {
|
|
|
2296
2989
|
verifying: 'Verifying…',
|
|
2297
2990
|
invalidCode: 'Invalid code. Try again.',
|
|
2298
2991
|
},
|
|
2992
|
+
// objectui#13208 — the overlay on an IMPERSONATION session: the held
|
|
2993
|
+
// credential is the impersonated user's, so it offers the way out instead
|
|
2994
|
+
// of their forms. `{{user}}` is the impersonated user's display name.
|
|
2995
|
+
impersonation: {
|
|
2996
|
+
passwordTitle: '{{user}} must change their password',
|
|
2997
|
+
mfaTitle: '{{user}} must set up two-factor authentication',
|
|
2998
|
+
body: 'You are impersonating {{user}}, and only they can do this themselves. Stop impersonating to return to your own account.',
|
|
2999
|
+
},
|
|
2299
3000
|
},
|
|
2300
3001
|
},
|
|
2301
3002
|
// The OAuth authorization-code consent screen (`/oauth/consent`). A third
|
|
@@ -2304,21 +3005,28 @@ const en = {
|
|
|
2304
3005
|
// language — objectui#3546 slice three.
|
|
2305
3006
|
oauth: {
|
|
2306
3007
|
consent: {
|
|
2307
|
-
// `{{appName}}` is the client's registered name, or `unknownApp`
|
|
2308
|
-
//
|
|
2309
|
-
// hint the page passes (empty when no user is
|
|
2310
|
-
// attached to the sentence's last word.
|
|
3008
|
+
// `{{appName}}` is the client's registered name, or `unknownApp` while the
|
|
3009
|
+
// lookup is in flight or when it gives no name. `{{suffix}}` is the
|
|
3010
|
+
// parenthesised account hint the page passes (empty when no user is
|
|
3011
|
+
// loaded), so it must stay attached to the sentence's last word.
|
|
2311
3012
|
title: '{{appName}} wants to access your account',
|
|
2312
3013
|
request: '{{appName}} is requesting permission{{suffix}}.',
|
|
2313
3014
|
unknownApp: 'an application',
|
|
3015
|
+
// Shown when the lookup gives no registered name, above the raw
|
|
3016
|
+
// `client_id` labelled `clientId` — the id is never shown as the name.
|
|
3017
|
+
unidentified: 'This application could not be identified.',
|
|
3018
|
+
clientId: 'Client ID',
|
|
2314
3019
|
willAllow: 'This app will be able to:',
|
|
2315
|
-
// Only the
|
|
3020
|
+
// Only the seven scopes the page maps by name; anything else renders the
|
|
2316
3021
|
// raw scope string, which is why there is no generic entry here.
|
|
2317
3022
|
scope: {
|
|
2318
3023
|
openid: 'Confirm your identity',
|
|
2319
3024
|
profile: 'Read your basic profile (name, picture)',
|
|
2320
3025
|
email: 'Read your email address',
|
|
2321
3026
|
offlineAccess: 'Stay signed in (refresh access)',
|
|
3027
|
+
dataRead: 'Read records, within your own permissions',
|
|
3028
|
+
dataWrite: 'Create, change and delete records, within your own permissions',
|
|
3029
|
+
actionsExecute: 'Run actions on your behalf, within your own permissions',
|
|
2322
3030
|
},
|
|
2323
3031
|
deny: 'Deny',
|
|
2324
3032
|
authorize: 'Authorize',
|
|
@@ -2349,11 +3057,20 @@ const en = {
|
|
|
2349
3057
|
role: 'Role',
|
|
2350
3058
|
save: 'Save Changes',
|
|
2351
3059
|
},
|
|
3060
|
+
language: {
|
|
3061
|
+
title: 'Language',
|
|
3062
|
+
description: 'The language used for notifications and messages sent to you. The interface language is chosen separately, from the globe menu.',
|
|
3063
|
+
label: 'Preferred language',
|
|
3064
|
+
systemDefault: 'Use the deployment default',
|
|
3065
|
+
save: 'Save',
|
|
3066
|
+
saved: 'Language preference updated.',
|
|
3067
|
+
readOnly: 'Your administrator manages the language for your account.',
|
|
3068
|
+
},
|
|
2352
3069
|
password: {
|
|
2353
3070
|
changeTitle: 'Change Password',
|
|
2354
3071
|
setTitle: 'Set Local Password',
|
|
2355
|
-
changeDescription: 'Update the password you use to sign in
|
|
2356
|
-
setDescription: 'You signed in via single sign-on. Set a local password to also sign in with email and password
|
|
3072
|
+
changeDescription: 'Update the password you use to sign in.',
|
|
3073
|
+
setDescription: 'You signed in via single sign-on. Set a local password to also sign in with email and password.',
|
|
2357
3074
|
current: 'Current password',
|
|
2358
3075
|
new: 'New password',
|
|
2359
3076
|
password: 'Password',
|
|
@@ -2362,7 +3079,7 @@ const en = {
|
|
|
2362
3079
|
mismatch: 'Passwords do not match',
|
|
2363
3080
|
enterCurrent: 'Enter your current password',
|
|
2364
3081
|
changed: 'Password changed.',
|
|
2365
|
-
localSet: 'Local password set. You can now sign in with email and password
|
|
3082
|
+
localSet: 'Local password set. You can now sign in with email and password.',
|
|
2366
3083
|
changeAction: 'Change password',
|
|
2367
3084
|
setAction: 'Set password',
|
|
2368
3085
|
},
|
|
@@ -2377,22 +3094,21 @@ const en = {
|
|
|
2377
3094
|
unknown: 'An unexpected error occurred.',
|
|
2378
3095
|
},
|
|
2379
3096
|
workspace: {
|
|
2380
|
-
label: '
|
|
2381
|
-
default: 'My
|
|
2382
|
-
switch: 'Switch
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
nameLabel: 'Workspace name',
|
|
3097
|
+
label: 'Organizations',
|
|
3098
|
+
default: 'My Organization',
|
|
3099
|
+
switch: 'Switch organization',
|
|
3100
|
+
createTitle: 'Create an organization',
|
|
3101
|
+
createDescription: 'An organization is a shared space for your team to collaborate.',
|
|
3102
|
+
createButton: 'Create organization',
|
|
3103
|
+
nameLabel: 'Organization name',
|
|
2388
3104
|
namePlaceholder: 'e.g., Acme Inc',
|
|
2389
3105
|
slugLabel: 'URL slug',
|
|
2390
3106
|
slugHint: 'Used in URLs. Only lowercase letters, numbers, and hyphens.',
|
|
2391
3107
|
invite: 'Invite member',
|
|
2392
3108
|
members: 'Members',
|
|
2393
|
-
settings: '
|
|
3109
|
+
settings: 'Organization settings',
|
|
2394
3110
|
multiOrgDisabled: 'Creating new organizations is disabled on this instance.',
|
|
2395
|
-
createFailed: 'Failed to create
|
|
3111
|
+
createFailed: 'Failed to create organization',
|
|
2396
3112
|
},
|
|
2397
3113
|
help: {
|
|
2398
3114
|
onThisPage: 'On this page',
|
|
@@ -2400,10 +3116,15 @@ const en = {
|
|
|
2400
3116
|
allDocs: 'All documentation',
|
|
2401
3117
|
keyboardShortcuts: 'Keyboard shortcuts',
|
|
2402
3118
|
onlineDocs: 'Online documentation',
|
|
3119
|
+
loadingDocumentation: 'Loading documentation',
|
|
3120
|
+
about: 'About',
|
|
3121
|
+
aboutTitle: 'About this console',
|
|
3122
|
+
aboutDescription: 'The build this console was compiled from.',
|
|
3123
|
+
aboutBuild: 'Console build',
|
|
3124
|
+
aboutBuildUnknown: 'Unknown build (no version was set when this console was built)',
|
|
2403
3125
|
},
|
|
2404
3126
|
sidebar: {
|
|
2405
3127
|
settings: 'Settings',
|
|
2406
|
-
help: 'Help',
|
|
2407
3128
|
helpTooltip: 'Help & Documentation',
|
|
2408
3129
|
activityFeed: 'Activity feed',
|
|
2409
3130
|
notifications: 'Notifications',
|
|
@@ -2415,20 +3136,19 @@ const en = {
|
|
|
2415
3136
|
packageManagement: 'Package management',
|
|
2416
3137
|
searchNavigation: 'Search navigation…',
|
|
2417
3138
|
recent: 'Recent',
|
|
2418
|
-
favorites: 'Favorites',
|
|
2419
3139
|
starred: 'Starred',
|
|
2420
3140
|
removeFromFavorites: 'Remove {{name}} from favorites',
|
|
3141
|
+
allReports: 'All reports',
|
|
2421
3142
|
},
|
|
2422
3143
|
topbar: {
|
|
2423
3144
|
aiAssistant: 'AI Assistant',
|
|
2424
3145
|
designInStudio: 'Design in Studio',
|
|
3146
|
+
editApp: 'Edit app',
|
|
2425
3147
|
openAssistant: 'Open {{name}} assistant',
|
|
2426
3148
|
offline: 'Offline',
|
|
2427
3149
|
usersOnline: 'Users currently online',
|
|
2428
3150
|
switchView: 'Switch view',
|
|
2429
|
-
switchObject: 'Switch Object',
|
|
2430
3151
|
connection: {
|
|
2431
|
-
connected: 'Connected',
|
|
2432
3152
|
connecting: 'Connecting…',
|
|
2433
3153
|
reconnecting: 'Reconnecting…',
|
|
2434
3154
|
disconnected: 'Disconnected',
|
|
@@ -2443,48 +3163,69 @@ const en = {
|
|
|
2443
3163
|
},
|
|
2444
3164
|
home: {
|
|
2445
3165
|
title: 'Home',
|
|
2446
|
-
subtitle: 'Your workspace dashboard',
|
|
2447
3166
|
nav: 'Home',
|
|
2448
3167
|
allApps: 'All Applications',
|
|
2449
3168
|
yourApps: 'Your apps',
|
|
2450
3169
|
showMoreApps: 'More',
|
|
2451
3170
|
showLess: 'Show less',
|
|
2452
3171
|
continueEmpty: 'Items you open will show up here.',
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
3172
|
+
// objectui#12602 — Home's "My work" section: its heading, the link to the
|
|
3173
|
+
// full inbox, each column's title, "view all" link and empty line.
|
|
3174
|
+
myWork: {
|
|
3175
|
+
title: "My work",
|
|
3176
|
+
openInbox: "Open inbox",
|
|
3177
|
+
viewAll: "View all",
|
|
3178
|
+
approvals: "Awaiting approval",
|
|
3179
|
+
approvalsEmpty: "Nothing waiting for your approval",
|
|
3180
|
+
notifications: "Notifications",
|
|
3181
|
+
notificationsEmpty: "No unread notifications",
|
|
2456
3182
|
},
|
|
2457
3183
|
greetingMorning: 'Good morning',
|
|
2458
3184
|
greetingAfternoon: 'Good afternoon',
|
|
2459
3185
|
greetingEvening: 'Good evening',
|
|
2460
3186
|
greetingNight: 'Working late',
|
|
2461
|
-
|
|
3187
|
+
// objectui#11689 — the greeting's two joiners: the separator between the
|
|
3188
|
+
// greeting and the person's name (rendered only when there is a name), and
|
|
3189
|
+
// the closing mark. Punctuation is a locale property: zh-CN and ja write
|
|
3190
|
+
// full-width marks, ar its own comma.
|
|
3191
|
+
greetingSeparator: ', ',
|
|
3192
|
+
greetingEnd: '.',
|
|
3193
|
+
// objectui#12601 — the field in Home's top bar that opens the command palette.
|
|
3194
|
+
search: 'Search apps, records, pages…',
|
|
3195
|
+
// objectui#12601 — the line under the greeting that sums up what is
|
|
3196
|
+
// waiting: the approvals count, or `none` at zero.
|
|
3197
|
+
summary: {
|
|
3198
|
+
approvals: 'You have {{count}} approval(s) waiting today',
|
|
3199
|
+
approvals_one: 'You have {{count}} approval waiting today',
|
|
3200
|
+
approvals_other: 'You have {{count}} approvals waiting today',
|
|
3201
|
+
none: 'Nothing is waiting for you today',
|
|
3202
|
+
},
|
|
3203
|
+
// objectui#12601 — an admin's trailing tile in the apps strip; opens the marketplace.
|
|
3204
|
+
addApp: 'Add app',
|
|
3205
|
+
// objectui#12601 — the line under a Home app tile: when the user last had
|
|
3206
|
+
// the app open, `time` a compact relative time ("2 hr. ago"). The line is
|
|
3207
|
+
// 11 px in a 112 px tile and never cut, so a pack adds a verb only where
|
|
3208
|
+
// verb and time still fit (zh "{{time}}打开"); English does not have the
|
|
3209
|
+
// room for "Opened". Held to its width budget in every pack by
|
|
3210
|
+
// `appTileOpenedLine-12601.test.ts` (app-shell).
|
|
3211
|
+
appOpened: '{{time}}',
|
|
2462
3212
|
build: {
|
|
2463
3213
|
title: 'Build an app',
|
|
2464
|
-
|
|
2465
|
-
noCapability: 'Building apps isn\'t available in this workspace — it requires the “Manage Metadata” permission, which your account doesn\'t have.',
|
|
3214
|
+
noCapability: 'Building apps isn\'t available in this system — it requires the “Manage Metadata” permission, which your account doesn\'t have.',
|
|
2466
3215
|
},
|
|
2467
3216
|
template: {
|
|
2468
3217
|
title: 'Start with a template',
|
|
2469
|
-
subtitle: 'Install a template app from the marketplace and customize it.',
|
|
2470
3218
|
marketplaceDisabled: 'This runtime has no app marketplace configured, so there are no templates to install here.',
|
|
2471
3219
|
},
|
|
2472
3220
|
open: 'Open',
|
|
2473
|
-
|
|
2474
|
-
apps: 'Applications',
|
|
2475
|
-
starred: 'Starred',
|
|
2476
|
-
recent: 'Recent items',
|
|
2477
|
-
},
|
|
2478
|
-
loading: 'Loading workspace…',
|
|
2479
|
-
recent: 'Recent',
|
|
2480
|
-
starred: 'Starred',
|
|
3221
|
+
loading: 'Loading…',
|
|
2481
3222
|
welcome: 'Build your business system with AI',
|
|
2482
3223
|
welcomeDescription: 'Describe your business in one sentence — AI generates the objects, screens, APIs and agent tools. Or start from scratch.',
|
|
2483
3224
|
welcomeAdminDescription: 'Describe your business in one sentence — AI generates the objects, screens, APIs and agent tools. Or set things up yourself from the menu on the left.',
|
|
2484
3225
|
welcomeAdminDescriptionNoBuild: 'Set up your first application from the Administration menu on the left. Once you have data, the AI assistant can help you explore it.',
|
|
2485
3226
|
welcomeAdminDescriptionNoAi: 'Set up your first application from the Administration menu on the left.',
|
|
2486
3227
|
noAppsTitle: 'No applications yet',
|
|
2487
|
-
noAppsDescription: '
|
|
3228
|
+
noAppsDescription: 'The system is being set up — apps your admin shares with you will show up here.',
|
|
2488
3229
|
buildWithAI: 'Build with AI',
|
|
2489
3230
|
askAI: 'Ask AI',
|
|
2490
3231
|
recoveryReminder: {
|
|
@@ -2493,7 +3234,15 @@ const en = {
|
|
|
2493
3234
|
dismiss: 'Dismiss',
|
|
2494
3235
|
},
|
|
2495
3236
|
pendingDrafts: {
|
|
2496
|
-
|
|
3237
|
+
// objectui#12602 — the drafts row in Home's "My work" section: the
|
|
3238
|
+
// count, then the first draft names joined by `nameSeparator`, in
|
|
3239
|
+
// their package when they share one.
|
|
3240
|
+
title: "{{count}} unpublished change(s)",
|
|
3241
|
+
title_one: "{{count}} unpublished change",
|
|
3242
|
+
title_other: "{{count}} unpublished changes",
|
|
3243
|
+
inPackage: "{{names}} waiting to publish in {{package}}",
|
|
3244
|
+
waiting: "{{names}} waiting to publish",
|
|
3245
|
+
nameSeparator: ", ",
|
|
2497
3246
|
cta: 'Publish',
|
|
2498
3247
|
publishing: 'Publishing…',
|
|
2499
3248
|
published: 'Published! Your changes are live.',
|
|
@@ -2513,12 +3262,10 @@ const en = {
|
|
|
2513
3262
|
browseMarketplace: 'Browse App Marketplace',
|
|
2514
3263
|
quickActions: {
|
|
2515
3264
|
title: 'Quick Actions',
|
|
2516
|
-
createApp: 'Create App',
|
|
2517
|
-
createAppDesc: 'Start with a new application',
|
|
2518
3265
|
manageObjects: 'Manage Objects',
|
|
2519
3266
|
manageObjectsDesc: 'Configure data models',
|
|
2520
3267
|
systemSettings: 'System Settings',
|
|
2521
|
-
systemSettingsDesc: 'Configure your
|
|
3268
|
+
systemSettingsDesc: 'Configure your system',
|
|
2522
3269
|
},
|
|
2523
3270
|
recentApps: {
|
|
2524
3271
|
title: 'Recently Accessed',
|
|
@@ -2526,7 +3273,11 @@ const en = {
|
|
|
2526
3273
|
object: 'Object',
|
|
2527
3274
|
dashboard: 'Dashboard',
|
|
2528
3275
|
page: 'Page',
|
|
3276
|
+
report: 'Report',
|
|
3277
|
+
package: 'Package',
|
|
3278
|
+
view: 'List view',
|
|
2529
3279
|
record: 'Record',
|
|
3280
|
+
metadata: 'Metadata',
|
|
2530
3281
|
},
|
|
2531
3282
|
},
|
|
2532
3283
|
starredApps: {
|
|
@@ -2553,6 +3304,11 @@ const en = {
|
|
|
2553
3304
|
manageAllApps: 'Manage All Apps',
|
|
2554
3305
|
systemConsole: 'System Console',
|
|
2555
3306
|
noAppsConfigured: 'No apps configured',
|
|
3307
|
+
allApps: 'All apps',
|
|
3308
|
+
editAppInStudio: 'Edit {{app}} in Studio',
|
|
3309
|
+
backToHome: 'Back to home',
|
|
3310
|
+
settings: 'Settings',
|
|
3311
|
+
productHome: '{{product}} home',
|
|
2556
3312
|
},
|
|
2557
3313
|
systemNav: {
|
|
2558
3314
|
systemSettings: 'System Settings',
|
|
@@ -2563,7 +3319,6 @@ const en = {
|
|
|
2563
3319
|
organizations: 'Organizations',
|
|
2564
3320
|
roles: 'Roles',
|
|
2565
3321
|
configuration: 'Configuration',
|
|
2566
|
-
createApp: 'Create App',
|
|
2567
3322
|
administration: 'Administration',
|
|
2568
3323
|
datasources: 'Datasources',
|
|
2569
3324
|
documentation: 'Documentation',
|
|
@@ -2572,12 +3327,14 @@ const en = {
|
|
|
2572
3327
|
title: 'Recent Activity',
|
|
2573
3328
|
filter: 'Filter',
|
|
2574
3329
|
empty: 'No recent activity',
|
|
3330
|
+
accessDenied: "You don't have permission to view activity.",
|
|
2575
3331
|
viewAll: 'View all activity',
|
|
2576
3332
|
ariaLabel: 'Activity feed',
|
|
2577
3333
|
typeCreate: 'Create',
|
|
2578
3334
|
typeUpdate: 'Update',
|
|
2579
3335
|
typeDelete: 'Delete',
|
|
2580
3336
|
typeComment: 'Comment',
|
|
3337
|
+
typeSystem: 'System',
|
|
2581
3338
|
relativeJustNow: 'just now',
|
|
2582
3339
|
relativeSecondsAgo: '{{count}}s ago',
|
|
2583
3340
|
relativeMinutesAgo: '{{count}}m ago',
|
|
@@ -2598,8 +3355,11 @@ const en = {
|
|
|
2598
3355
|
placeholder: 'Search objects, dashboards, pages, reports…',
|
|
2599
3356
|
inputAriaLabel: 'Search objects, dashboards, pages, reports',
|
|
2600
3357
|
resultsCount: '{{count}} result for "{{query}}"',
|
|
2601
|
-
|
|
3358
|
+
resultsCount_one: '{{count}} result for "{{query}}"',
|
|
3359
|
+
resultsCount_other: '{{count}} results for "{{query}}"',
|
|
2602
3360
|
itemsAvailable: '{{count}} items available',
|
|
3361
|
+
itemsAvailable_one: '{{count}} item available',
|
|
3362
|
+
itemsAvailable_other: '{{count}} items available',
|
|
2603
3363
|
noResults: 'No results found',
|
|
2604
3364
|
noResultsHint: 'Try adjusting your search terms',
|
|
2605
3365
|
typeObjects: 'Objects',
|
|
@@ -2617,6 +3377,10 @@ const en = {
|
|
|
2617
3377
|
interfacePageSourceMissing: 'This interface page references "{{name}}", which is not available.',
|
|
2618
3378
|
recordNotFound: 'Record not found',
|
|
2619
3379
|
recordNotFoundDescription: 'The record you are looking for does not exist or may have been deleted.',
|
|
3380
|
+
recordAccessDenied: 'You don’t have access to {{object}} records',
|
|
3381
|
+
recordAccessDeniedDescription: 'You don’t have permission to view records of this type. Contact your administrator if you think you should have access.',
|
|
3382
|
+
recordLoadFailed: 'Couldn’t load this record',
|
|
3383
|
+
recordLoadFailedDescription: 'Something went wrong while loading it. Check your connection and try again.',
|
|
2620
3384
|
pageNotFound: 'Page Not Found',
|
|
2621
3385
|
pageNotFoundDescription: 'The page "{{name}}" could not be found. It may have been removed or renamed.',
|
|
2622
3386
|
dashboardNotFound: 'Dashboard Not Found',
|
|
@@ -2626,10 +3390,19 @@ const en = {
|
|
|
2626
3390
|
noAppsConfigured: 'No Apps Configured',
|
|
2627
3391
|
noAppsConfiguredDescription: 'No applications have been registered. Create your first app or visit System Settings to configure your environment.',
|
|
2628
3392
|
appNotAvailable: 'App not available',
|
|
2629
|
-
appNotAvailableDescription: 'This app is not available
|
|
3393
|
+
appNotAvailableDescription: 'This app is not available — try again in a moment.',
|
|
3394
|
+
appNotFound: "This app can't be opened",
|
|
3395
|
+
appNotFoundDescription: 'The server did not return this app for your account.',
|
|
3396
|
+
appUnreachable: "Couldn't reach the server",
|
|
3397
|
+
appUnreachableDescription: 'This app could not be checked. Try again in a moment.',
|
|
2630
3398
|
appAccessDenied: "You don't have access to this app",
|
|
2631
3399
|
appAccessDeniedDescription: 'This app exists, but your account is not authorized to open it. Ask an administrator to grant you access.',
|
|
2632
3400
|
appAccessDeniedHome: 'Back to home',
|
|
3401
|
+
// objectui#12079 — the app root when the app serves this caller no navigation (`AppNoAccessEmptyState`).
|
|
3402
|
+
appNothingAvailable: 'Nothing in {{app}} is available to you yet',
|
|
3403
|
+
appNothingAvailableDescription: 'This app has no pages your account can open. Ask an administrator to grant you access.',
|
|
3404
|
+
appNothingAvailableGrantDescription: 'This app has no pages your account can open. You can grant access in Setup.',
|
|
3405
|
+
openSetup: 'Open Setup',
|
|
2633
3406
|
createFirstApp: 'Create Your First App',
|
|
2634
3407
|
systemSettings: 'System Settings',
|
|
2635
3408
|
back: 'Back',
|
|
@@ -2650,6 +3423,10 @@ const en = {
|
|
|
2650
3423
|
publishing: 'Publishing…',
|
|
2651
3424
|
exit: 'Exit preview',
|
|
2652
3425
|
changes: 'Changes',
|
|
3426
|
+
// objectui#12968 — what is pending on the surface the preview shows.
|
|
3427
|
+
pendingHere: 'Draft preview · {{count}} unpublished changes on this page',
|
|
3428
|
+
pendingHere_one: 'Draft preview · {{count}} unpublished change on this page',
|
|
3429
|
+
pendingHere_other: 'Draft preview · {{count}} unpublished changes on this page',
|
|
2653
3430
|
// Magic-moment hint: a freshly-built draft renders empty (dashboards at 0,
|
|
2654
3431
|
// lists "Nothing here yet") because seed/sample rows only load on publish.
|
|
2655
3432
|
// Say so plainly so an empty preview never reads as a broken build.
|
|
@@ -2670,11 +3447,69 @@ const en = {
|
|
|
2670
3447
|
detailNone: 'No differences detected — the draft matches the published version.',
|
|
2671
3448
|
detailChangedKeys: 'Also changed:',
|
|
2672
3449
|
confirmNote: 'Publishing releases all {{count}} pending drafts of this package atomically.',
|
|
3450
|
+
confirmNote_one: 'Publishing releases the {{count}} pending draft of this package atomically.',
|
|
3451
|
+
confirmNote_other: 'Publishing releases all {{count}} pending drafts of this package atomically.',
|
|
3452
|
+
// objectui#11591 — the package-less sheet: no package to batch, so each
|
|
3453
|
+
// draft publishes by itself and one that fails stays pending.
|
|
3454
|
+
confirmNoteSeparate: 'Publishing releases the {{count}} pending drafts one at a time: a draft that fails stays pending while the others go live.',
|
|
3455
|
+
confirmNoteSeparate_one: 'Publishing releases the {{count}} pending draft on its own: if it fails, it stays pending.',
|
|
3456
|
+
confirmNoteSeparate_other: 'Publishing releases the {{count}} pending drafts one at a time: a draft that fails stays pending while the others go live.',
|
|
2673
3457
|
publishConfirm: 'Publish all',
|
|
2674
|
-
//
|
|
3458
|
+
// objectui#12517 — the confirm posture's summary line above the list:
|
|
3459
|
+
// the item count, then one `{{n}} {{type}}` per type group.
|
|
3460
|
+
summaryItems: '{{count}} items',
|
|
3461
|
+
summaryItems_one: '{{count}} item',
|
|
3462
|
+
summaryItems_other: '{{count}} items',
|
|
3463
|
+
summaryType: '{{n}} {{type}}',
|
|
3464
|
+
// objectui#13147 — one count family per known metadata type, so the summary
|
|
3465
|
+
// reads "2 flows", not "2 flow". A type with no row here keeps `summaryType`.
|
|
3466
|
+
typeCount: {
|
|
3467
|
+
object: '{{count}} objects',
|
|
3468
|
+
object_one: '{{count}} object',
|
|
3469
|
+
object_other: '{{count}} objects',
|
|
3470
|
+
view: '{{count}} views',
|
|
3471
|
+
view_one: '{{count}} view',
|
|
3472
|
+
view_other: '{{count}} views',
|
|
3473
|
+
page: '{{count}} pages',
|
|
3474
|
+
page_one: '{{count}} page',
|
|
3475
|
+
page_other: '{{count}} pages',
|
|
3476
|
+
dashboard: '{{count}} dashboards',
|
|
3477
|
+
dashboard_one: '{{count}} dashboard',
|
|
3478
|
+
dashboard_other: '{{count}} dashboards',
|
|
3479
|
+
app: '{{count}} apps',
|
|
3480
|
+
app_one: '{{count}} app',
|
|
3481
|
+
app_other: '{{count}} apps',
|
|
3482
|
+
action: '{{count}} actions',
|
|
3483
|
+
action_one: '{{count}} action',
|
|
3484
|
+
action_other: '{{count}} actions',
|
|
3485
|
+
report: '{{count}} reports',
|
|
3486
|
+
report_one: '{{count}} report',
|
|
3487
|
+
report_other: '{{count}} reports',
|
|
3488
|
+
flow: '{{count}} flows',
|
|
3489
|
+
flow_one: '{{count}} flow',
|
|
3490
|
+
flow_other: '{{count}} flows',
|
|
3491
|
+
permission: '{{count}} permission sets',
|
|
3492
|
+
permission_one: '{{count}} permission set',
|
|
3493
|
+
permission_other: '{{count}} permission sets',
|
|
3494
|
+
agent: '{{count}} agents',
|
|
3495
|
+
agent_one: '{{count}} agent',
|
|
3496
|
+
agent_other: '{{count}} agents',
|
|
3497
|
+
email_template: '{{count}} email templates',
|
|
3498
|
+
email_template_one: '{{count}} email template',
|
|
3499
|
+
email_template_other: '{{count}} email templates',
|
|
3500
|
+
},
|
|
3501
|
+
// objectui#12929 — the unchecked choice under an added object field whose
|
|
3502
|
+
// literal default the batch publish can write into the existing records.
|
|
3503
|
+
backfillOption: 'Backfill default ({{count}} existing records)',
|
|
3504
|
+
backfillOption_one: 'Backfill default ({{count}} existing record)',
|
|
3505
|
+
backfillOption_other: 'Backfill default ({{count}} existing records)',
|
|
3506
|
+
backfillOptionNoCount: 'Backfill default',
|
|
3507
|
+
// [`7a90afdf9`] Pre-publish security-posture findings, shown next to
|
|
2675
3508
|
// the confirm button so a refusal the door would issue is read BEFORE
|
|
2676
3509
|
// the click rather than as a toast after the batch rolled back.
|
|
2677
3510
|
securityBlockTitle: 'Publishing will be refused — {{count}} item(s) need a decision first',
|
|
3511
|
+
securityBlockTitle_one: 'Publishing will be refused — {{count}} item needs a decision first',
|
|
3512
|
+
securityBlockTitle_other: 'Publishing will be refused — {{count}} items need a decision first',
|
|
2678
3513
|
securityBlockWhere: 'Fix it on the object under Settings → Record sharing, then publish again.',
|
|
2679
3514
|
},
|
|
2680
3515
|
// ADR-0045 — the materialized-but-unlisted app banner
|
|
@@ -2702,7 +3537,19 @@ const en = {
|
|
|
2702
3537
|
revertLabel: 'Reverted a change',
|
|
2703
3538
|
applyLabel: 'Build change',
|
|
2704
3539
|
revert: 'revert',
|
|
2705
|
-
|
|
3540
|
+
// objectui#9266 — the count is INSIDE the value, one interpolated string
|
|
3541
|
+
// per pack. It used to be a bare unit word that `CommitTimeline` glued to
|
|
3542
|
+
// a number it rendered itself, which no pack could make agree: `de` read
|
|
3543
|
+
// `1 Elemente`, `ru` `1 элементов`, `ar` `1 عناصر`. Each pack now states
|
|
3544
|
+
// the count in its own count-INVARIANT idiom — `en` keeps the `(s)` marker
|
|
3545
|
+
// it already dodged with, `zh`/`ja`/`ko` keep the inline counter their
|
|
3546
|
+
// grammar needs no plural for, and `de`/`fr`/`es`/`pt`/`ru`/`ar` use the
|
|
3547
|
+
// label-colon form (`Elemente: 3`, `Элементов: 3`), which is the shape
|
|
3548
|
+
// `fields.textarea.charactersRemaining` already uses for this exact
|
|
3549
|
+
// reason. It needs no family: every pack's form reads at any number,
|
|
3550
|
+
// which is why `count-families-11445.test.ts` names it on its
|
|
3551
|
+
// count-neutral list rather than holding it to the family rule.
|
|
3552
|
+
items: '{{count}} item(s)',
|
|
2706
3553
|
revertAction: 'Revert',
|
|
2707
3554
|
reverted: 'Reverted — the change has been undone.',
|
|
2708
3555
|
revertFailed: 'Revert failed',
|
|
@@ -2718,22 +3565,17 @@ const en = {
|
|
|
2718
3565
|
requiredError: '{{label}} is required',
|
|
2719
3566
|
lookupPlaceholder: 'Record id for {{label}}',
|
|
2720
3567
|
lookupHelpText: 'No reference object is configured for this parameter, so the record picker is unavailable. Enter a record id, or ask an administrator to fix the action parameter.',
|
|
3568
|
+
unresolvedParam: 'This parameter cannot be shown: the field it is backed by is missing from the object metadata, so the control it needs cannot be built. Ask an administrator to fix the action definition.',
|
|
3569
|
+
carryOverHint: 'Carried over unchanged (read-only)',
|
|
2721
3570
|
cancel: 'Cancel',
|
|
2722
3571
|
confirm: 'Confirm',
|
|
2723
3572
|
uploading: 'Uploading…',
|
|
2724
|
-
defaultActionTitle: 'Action',
|
|
2725
|
-
ok: 'OK',
|
|
2726
3573
|
},
|
|
2727
3574
|
actionConfirm: {
|
|
2728
3575
|
title: 'Confirm Action',
|
|
2729
3576
|
confirm: 'Continue',
|
|
2730
3577
|
cancel: 'Cancel',
|
|
2731
3578
|
},
|
|
2732
|
-
rowAction: {
|
|
2733
|
-
openMenu: 'Open menu',
|
|
2734
|
-
edit: 'Edit',
|
|
2735
|
-
delete: 'Delete',
|
|
2736
|
-
},
|
|
2737
3579
|
navigationSync: {
|
|
2738
3580
|
addedPage: 'Navigation updated: added page "{{name}}"',
|
|
2739
3581
|
addedDashboard: 'Navigation updated: added dashboard "{{name}}"',
|
|
@@ -2751,10 +3593,14 @@ const en = {
|
|
|
2751
3593
|
deleteFailed: 'Failed to delete {{label}}',
|
|
2752
3594
|
noRecordId: 'No record ID provided',
|
|
2753
3595
|
deleteConfirm: 'Are you sure you want to delete this record?',
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
3596
|
+
deleteConfirmTitle: 'Delete {{label}} "{{name}}"?',
|
|
3597
|
+
bulkDeleteConfirmTitle: 'Delete {{count}} {{label}} records?',
|
|
3598
|
+
bulkDeleteConfirmTitle_one: 'Delete {{count}} {{label}} record?',
|
|
3599
|
+
bulkDeleteConfirmTitle_other: 'Delete {{count}} {{label}} records?',
|
|
3600
|
+
deleteConfirmButton: 'Delete',
|
|
2757
3601
|
bulkDeleteSuccess: 'Deleted {{count}} {{label}} records',
|
|
3602
|
+
bulkDeleteSuccess_one: 'Deleted {{count}} {{label}} record',
|
|
3603
|
+
bulkDeleteSuccess_other: 'Deleted {{count}} {{label}} records',
|
|
2758
3604
|
bulkDeletePartial: '{{succeeded}} deleted, {{failed}} failed',
|
|
2759
3605
|
},
|
|
2760
3606
|
objectViewActions: {
|
|
@@ -2766,15 +3612,6 @@ const en = {
|
|
|
2766
3612
|
exportFailed: 'Export failed: {{message}}',
|
|
2767
3613
|
forecastSoon: 'Forecast view coming soon',
|
|
2768
3614
|
},
|
|
2769
|
-
recordDetail: {
|
|
2770
|
-
viewersTooltip: 'Users viewing this record',
|
|
2771
|
-
},
|
|
2772
|
-
cellRender: {
|
|
2773
|
-
empty: 'Empty',
|
|
2774
|
-
yes: 'Yes',
|
|
2775
|
-
no: 'No',
|
|
2776
|
-
systemFields: 'System',
|
|
2777
|
-
},
|
|
2778
3615
|
user: {
|
|
2779
3616
|
profile: 'Profile',
|
|
2780
3617
|
settings: 'Settings',
|
|
@@ -2784,18 +3621,18 @@ const en = {
|
|
|
2784
3621
|
language: 'Language',
|
|
2785
3622
|
},
|
|
2786
3623
|
organizations: {
|
|
2787
|
-
mine: 'My
|
|
2788
|
-
create: 'Create
|
|
2789
|
-
title: '
|
|
2790
|
-
heading: 'Your
|
|
2791
|
-
subtitle: 'Select
|
|
2792
|
-
searchPlaceholder: 'Search for
|
|
2793
|
-
new: 'New
|
|
2794
|
-
current: 'Current
|
|
3624
|
+
mine: 'My Organizations',
|
|
3625
|
+
create: 'Create organization',
|
|
3626
|
+
title: 'Organizations',
|
|
3627
|
+
heading: 'Your Organizations',
|
|
3628
|
+
subtitle: 'Select an organization to continue, or create a new one.',
|
|
3629
|
+
searchPlaceholder: 'Search for an organization',
|
|
3630
|
+
new: 'New organization',
|
|
3631
|
+
current: 'Current organization',
|
|
2795
3632
|
manage: 'Manage',
|
|
2796
|
-
emptyTitle: 'No
|
|
2797
|
-
emptyDescription: 'Create your first
|
|
2798
|
-
noMatches: 'No
|
|
3633
|
+
emptyTitle: 'No organizations yet',
|
|
3634
|
+
emptyDescription: 'Create your first organization to get started.',
|
|
3635
|
+
noMatches: 'No organizations match your search.',
|
|
2799
3636
|
},
|
|
2800
3637
|
// Organization MANAGEMENT (packages/app-shell/src/console/organizations/**
|
|
2801
3638
|
// plus the workspace switcher). Distinct from `organizations` above, which
|
|
@@ -2889,6 +3726,7 @@ const en = {
|
|
|
2889
3726
|
// The org's URL segment. `deleteConfirmSlugLabel` asks the user to
|
|
2890
3727
|
// retype it, so the two must keep naming the same thing.
|
|
2891
3728
|
slugLabel: 'Slug',
|
|
3729
|
+
slugLockedNote: 'This organization has active environments, so its slug can’t be changed here: renaming it also moves their subdomains.',
|
|
2892
3730
|
logoLabel: 'Logo',
|
|
2893
3731
|
logoUpload: 'Upload',
|
|
2894
3732
|
logoReplace: 'Replace',
|
|
@@ -2953,18 +3791,39 @@ const en = {
|
|
|
2953
3791
|
viewAll: 'View all notifications',
|
|
2954
3792
|
groupCount: '{{count}} notifications',
|
|
2955
3793
|
groupUnread: '{{count}} unread',
|
|
3794
|
+
groupUnread_one: '{{count}} unread',
|
|
3795
|
+
groupUnread_other: '{{count}} unread',
|
|
2956
3796
|
groupMarkRead: 'Mark read',
|
|
2957
3797
|
groupMarkReadTitle: 'Mark all of this type read',
|
|
2958
3798
|
approvalsPending: '{{count}} pending approvals',
|
|
3799
|
+
approvalsPending_one: '{{count}} pending approval',
|
|
3800
|
+
approvalsPending_other: '{{count}} pending approvals',
|
|
2959
3801
|
viewApprovals: 'View approvals',
|
|
2960
3802
|
noPendingApprovals: 'No pending approvals',
|
|
2961
3803
|
openApprovalsInbox: 'Open Approvals Inbox',
|
|
2962
|
-
// Bell-badge breakdown (#7233): the badge sums unread notification topics
|
|
3804
|
+
// Bell-badge breakdown (objectstack-ai/objectstack#7233): the badge sums unread notification topics
|
|
2963
3805
|
// and pending approvals, then clamps at "9+". These three spell the sum
|
|
2964
3806
|
// out inside the popover so the number is explainable.
|
|
2965
3807
|
badgeTotal: '{{total}} total',
|
|
2966
|
-
badgeNotifications: '{{
|
|
2967
|
-
|
|
3808
|
+
badgeNotifications: '{{count}} notifications',
|
|
3809
|
+
badgeNotifications_one: '{{count}} notification',
|
|
3810
|
+
badgeNotifications_other: '{{count}} notifications',
|
|
3811
|
+
badgeApprovals: '{{count}} pending approvals',
|
|
3812
|
+
badgeApprovals_one: '{{count}} pending approval',
|
|
3813
|
+
badgeApprovals_other: '{{count}} pending approvals',
|
|
3814
|
+
// objectui#7011 — the arrival announcement (toast / desktop notification)
|
|
3815
|
+
// and the two switches that govern it.
|
|
3816
|
+
arrivalMany: '{{count}} new messages',
|
|
3817
|
+
arrivalMany_one: '{{count}} new message',
|
|
3818
|
+
arrivalMany_other: '{{count}} new messages',
|
|
3819
|
+
arrivalRepeats: '{{count}} new messages on this topic',
|
|
3820
|
+
arrivalRepeats_one: '{{count}} new message on this topic',
|
|
3821
|
+
arrivalRepeats_other: '{{count}} new messages on this topic',
|
|
3822
|
+
arrivalOpen: 'View',
|
|
3823
|
+
toastEnabled: 'In-app alerts',
|
|
3824
|
+
desktopEnabled: 'Desktop notifications',
|
|
3825
|
+
desktopBlocked: 'Blocked. Allow notifications for this site in your browser settings.',
|
|
3826
|
+
desktopUnsupported: 'This browser does not support desktop notifications.',
|
|
2968
3827
|
},
|
|
2969
3828
|
publicForm: {
|
|
2970
3829
|
submit: 'Submit',
|
|
@@ -2975,12 +3834,20 @@ const en = {
|
|
|
2975
3834
|
thankYouTitle: 'Thank you!',
|
|
2976
3835
|
thankYouMessage: 'Your submission has been received successfully.',
|
|
2977
3836
|
redirecting: 'Redirecting in {{seconds}} seconds…',
|
|
3837
|
+
// The console form page's line for a submit whose declared redirect is
|
|
3838
|
+
// pending (objectui#11071). `redirecting` above is the embeddable form's
|
|
3839
|
+
// countdown and carries a `{{seconds}}` hole this page has no value for.
|
|
3840
|
+
redirectPending: 'Redirecting…',
|
|
2978
3841
|
unavailableTitle: 'Form unavailable',
|
|
2979
3842
|
unavailableDescription: 'No public form is available at this URL. Make sure the underlying view has anonymous sharing enabled and matches this slug.',
|
|
2980
3843
|
tryDemo: 'Try the demo',
|
|
2981
3844
|
retry: 'Retry',
|
|
2982
3845
|
loading: 'Loading form…',
|
|
2983
3846
|
requiredHint: '* Required field',
|
|
3847
|
+
// The console form page's client-side refusal when required rows are empty
|
|
3848
|
+
// (objectui#11071). `{{fields}}` is the empty rows' labels joined with a
|
|
3849
|
+
// comma; the colon, its spacing and the order are the pack's.
|
|
3850
|
+
requiredFields: 'Required: {{fields}}',
|
|
2984
3851
|
consentLabelDefault: 'I agree to the privacy policy and consent to my data being processed for this request.',
|
|
2985
3852
|
consentLink: 'Privacy policy',
|
|
2986
3853
|
consentRequired: 'Please accept the privacy policy to continue.',
|
|
@@ -2993,10 +3860,10 @@ const en = {
|
|
|
2993
3860
|
body: 'The MCP surface is off (OS_MCP_SERVER_ENABLED=false), so there is nothing to connect. Ask your operator to re-enable it.',
|
|
2994
3861
|
},
|
|
2995
3862
|
url: {
|
|
2996
|
-
title: 'This
|
|
3863
|
+
title: 'This system\'s MCP endpoint',
|
|
2997
3864
|
body: 'Any MCP-capable AI client connects with this URL. Identity is self-serve: the deployment is its own OAuth 2.1 authorization server, so interactive clients just open a browser login — you connect as yourself, and every call runs under your own permissions and row-level security.',
|
|
2998
3865
|
downloadSkill: 'Download SKILL.md',
|
|
2999
|
-
skillHint: 'The portable agent skill: teaches any skills-capable agent how to work with this
|
|
3866
|
+
skillHint: 'The portable agent skill: teaches any skills-capable agent how to work with this system.',
|
|
3000
3867
|
},
|
|
3001
3868
|
claude: {
|
|
3002
3869
|
body: 'Settings → Connectors → Add custom connector, then paste this URL. Sign in through the browser when prompted.',
|
|
@@ -3031,18 +3898,97 @@ const en = {
|
|
|
3031
3898
|
noImportableFields: 'That object has no importable fields.',
|
|
3032
3899
|
schemaReadFailed: 'Could not read the object schema.',
|
|
3033
3900
|
imported: 'Imported {{count}} row(s) into {{object}}.',
|
|
3901
|
+
imported_one: 'Imported {{count}} row into {{object}}.',
|
|
3902
|
+
imported_other: 'Imported {{count}} rows into {{object}}.',
|
|
3034
3903
|
importFrom: 'Import the real rows from',
|
|
3035
3904
|
into: 'into',
|
|
3036
3905
|
opening: 'Opening…',
|
|
3037
3906
|
importAction: 'Import',
|
|
3038
3907
|
dismiss: 'Dismiss',
|
|
3039
3908
|
},
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3909
|
+
// `cloud:workspace-timezone-notice` — the Cloud welcome page's line naming the
|
|
3910
|
+
// timezone a workspace was seeded with at creation (objectui#11930). `{{zone}}`
|
|
3911
|
+
// is the seed, an IANA id printed verbatim.
|
|
3912
|
+
cloudWorkspaceTimezoneNotice: {
|
|
3913
|
+
seeded: 'The environment timezone was set to {{zone}} from your browser when the environment was created. You can change it in Settings → Localization.',
|
|
3914
|
+
},
|
|
3915
|
+
// `@object-ui/plugin-ai` — the `nl-query`, `ai-form-assist` and
|
|
3916
|
+
// `ai-recommendations` components (objectui#10232). The two count labels are
|
|
3917
|
+
// i18next count families (objectui#11445): the component passes `count` and
|
|
3918
|
+
// each pack carries every CLDR category its language selects.
|
|
3919
|
+
ai: {
|
|
3920
|
+
nlQuery: {
|
|
3921
|
+
placeholder: 'Ask a question about your data…',
|
|
3922
|
+
ask: 'Ask',
|
|
3923
|
+
results: 'Results',
|
|
3924
|
+
match: '{{percent}} match',
|
|
3925
|
+
simulatedSummary: 'Results for: {{query}}',
|
|
3926
|
+
noResults: 'No matching records found',
|
|
3927
|
+
recentQueries: 'Recent Queries',
|
|
3928
|
+
},
|
|
3929
|
+
formAssist: {
|
|
3930
|
+
title: 'AI Suggestions',
|
|
3931
|
+
suggestionCount: '{{count}} suggestions',
|
|
3932
|
+
suggestionCount_one: '{{count}} suggestion',
|
|
3933
|
+
suggestionCount_other: '{{count}} suggestions',
|
|
3934
|
+
applyAll: 'Apply All',
|
|
3935
|
+
confidence: '{{percent}} confidence',
|
|
3936
|
+
appliedCount: '{{count}} suggestions applied',
|
|
3937
|
+
appliedCount_one: '{{count}} suggestion applied',
|
|
3938
|
+
appliedCount_other: '{{count}} suggestions applied',
|
|
3939
|
+
},
|
|
3940
|
+
recommendations: {
|
|
3941
|
+
title: 'Recommendations',
|
|
3942
|
+
generating: 'Generating recommendations…',
|
|
3943
|
+
empty: 'No recommendations available',
|
|
3944
|
+
},
|
|
3945
|
+
},
|
|
3946
|
+
// The AI HITL approval inbox (`@object-ui/plugin-chatbot`'s
|
|
3947
|
+
// `AiPendingActionsInbox`) — objectui#7173. Its four relative-time phrases
|
|
3948
|
+
// are NOT here: it borrows `detail.justNow` / `minutesAgo` / `hoursAgo` /
|
|
3949
|
+
// `daysAgo`, already translated in all ten packs, the way `ObjectGrid` and
|
|
3950
|
+
// `ObjectKanban` borrow `detail.recordDetail`. Distinct from
|
|
3951
|
+
// `approvalsInbox` above, which is the human approval-PROCESS inbox:
|
|
3952
|
+
// different surface, different feature, so no rows are shared with it.
|
|
3953
|
+
aiApprovals: {
|
|
3954
|
+
title: 'AI Approvals',
|
|
3955
|
+
description: 'Actions an AI agent proposed that need a human review before execution.',
|
|
3956
|
+
tabPending: 'Pending',
|
|
3957
|
+
tabDecided: 'Decided',
|
|
3958
|
+
tabAll: 'All',
|
|
3959
|
+
statusPending: 'Pending',
|
|
3960
|
+
statusApproved: 'Approved',
|
|
3961
|
+
statusExecuted: 'Executed',
|
|
3962
|
+
statusFailed: 'Failed',
|
|
3963
|
+
statusRejected: 'Rejected',
|
|
3964
|
+
colTool: 'Tool',
|
|
3965
|
+
colAction: 'Action',
|
|
3966
|
+
colObject: 'Object',
|
|
3967
|
+
colStatus: 'Status',
|
|
3968
|
+
colProposed: 'Proposed',
|
|
3969
|
+
colDecision: 'Decision',
|
|
3970
|
+
emptyTitle: 'No actions waiting',
|
|
3971
|
+
emptyDescription: 'When the AI proposes a sensitive action it will appear here for review.',
|
|
3972
|
+
view: 'View',
|
|
3973
|
+
approve: 'Approve',
|
|
3974
|
+
reject: 'Reject',
|
|
3975
|
+
working: 'Working…',
|
|
3976
|
+
approveAndExecute: 'Approve & Execute',
|
|
3977
|
+
outcomeApprove: 'Approve for {{id}}: {{message}}',
|
|
3978
|
+
outcomeReject: 'Reject for {{id}}: {{message}}',
|
|
3979
|
+
outcomeExecuteFailed: 'Action failed during execution',
|
|
3980
|
+
drawerFallbackTitle: 'Pending action',
|
|
3981
|
+
drawerSubtitle: 'Tool {{tool}} on {{object}}',
|
|
3982
|
+
fieldProposedBy: 'Proposed by',
|
|
3983
|
+
fieldDecidedBy: 'Decided by',
|
|
3984
|
+
fieldConversation: 'Conversation',
|
|
3985
|
+
fieldToolInput: 'Tool input',
|
|
3986
|
+
fieldResult: 'Result',
|
|
3987
|
+
fieldError: 'Error',
|
|
3988
|
+
fieldRejectionReason: 'Rejection reason',
|
|
3989
|
+
rejectTitle: 'Reject this action?',
|
|
3990
|
+
rejectBody: 'The reason is shown back to the AI so it can adjust its next response.',
|
|
3991
|
+
rejectPlaceholder: "Optional reason (e.g. 'Wrong record id — please confirm with the user first.')",
|
|
3046
3992
|
},
|
|
3047
3993
|
aiModelStatus: {
|
|
3048
3994
|
summary: 'Build / Ask uses {{conversational}} ({{conversationalSource}}); structured uses {{structured}} ({{structuredSource}}).',
|
|
@@ -3052,8 +3998,8 @@ const en = {
|
|
|
3052
3998
|
rowConversational: 'Build / Ask model',
|
|
3053
3999
|
rowStructured: 'Structured (blueprint / seed)',
|
|
3054
4000
|
rowReasoning: 'Reasoning effort',
|
|
3055
|
-
readFailed: 'Couldn\'t read the effective AI model. This
|
|
3056
|
-
readFailedWithStatus: 'Couldn\'t read the effective AI model (HTTP {{status}}). This
|
|
4001
|
+
readFailed: 'Couldn\'t read the effective AI model. This system may not run an AI service, or you may lack the ai:read permission.',
|
|
4002
|
+
readFailedWithStatus: 'Couldn\'t read the effective AI model (HTTP {{status}}). This system may not run an AI service, or you may lack the ai:read permission.',
|
|
3057
4003
|
overridesInEffect: 'Overrides in effect: ',
|
|
3058
4004
|
noOverrides: 'none — running the deployed code defaults.',
|
|
3059
4005
|
adapter: 'Adapter: ',
|
|
@@ -3061,6 +4007,184 @@ const en = {
|
|
|
3061
4007
|
sourceInherits: 'same as build/ask',
|
|
3062
4008
|
sourcePinned: 'pinned by {{source}}',
|
|
3063
4009
|
},
|
|
4010
|
+
// objectui#7254 — the AI copilot's tool cards. Three families, all of them
|
|
4011
|
+
// English-only until this landed while every other string on the same screen
|
|
4012
|
+
// was translated:
|
|
4013
|
+
//
|
|
4014
|
+
// `tool.*` — one entry per PLATFORM-PROVIDED tool name
|
|
4015
|
+
// (@objectstack/spec `PLATFORM_TOOLS_BY_PACKAGE`, the
|
|
4016
|
+
// closed registry those runtimes are conformance-tested
|
|
4017
|
+
// against). `humanizeToolName` looks each up as
|
|
4018
|
+
// `chatbot.tool.<tool_name>` and falls back to its English
|
|
4019
|
+
// title-caser for a custom / third-party tool, so a name
|
|
4020
|
+
// missing here is degraded, never broken. Every value, `en`
|
|
4021
|
+
// included, is a short sentence in the pack's language
|
|
4022
|
+
// saying what the step does (cloud#2927 Target 3, ruled
|
|
4023
|
+
// 「同意」; objectui#12724): never the tool id, and never
|
|
4024
|
+
// the title-caser's output for it, which is how the step
|
|
4025
|
+
// reads for a tool the pack has no entry for.
|
|
4026
|
+
// `toolLabels-locale-parity-7481` holds both.
|
|
4027
|
+
// `toolState.*` — the card-header badge + activity-chip vocabulary. ONE
|
|
4028
|
+
// set for both surfaces (they used to carry separate
|
|
4029
|
+
// tables and disagreed on casing).
|
|
4030
|
+
// `build.*` — the apply_blueprint BUILD PANEL's own copy (objectui#7388).
|
|
4031
|
+
// Everything else on that panel is fed by the host as an
|
|
4032
|
+
// already-translated prop; these strings were literals in
|
|
4033
|
+
// the component, so they stayed English in every language.
|
|
4034
|
+
// `building`/`built` interpolate `appFallback` when the
|
|
4035
|
+
// build has no app label, so each pack must keep BOTH
|
|
4036
|
+
// frames in the one case/gender that noun phrase is in.
|
|
4037
|
+
// `verifying`/`verifyStep`/`verified` are the post-apply
|
|
4038
|
+
// verification line and `unknownPhase` the warning for a
|
|
4039
|
+
// phase outside the spec's vocabulary (objectui#11988).
|
|
4040
|
+
// `plan.*` — the "N objects · N views · N dashboards" strip. Plural
|
|
4041
|
+
// FAMILIES: one slot per CLDR category the pack's language
|
|
4042
|
+
// selects (objectui#11432), plus the base key for a call
|
|
4043
|
+
// made without a count. `all-locales-key-parity.test.ts`
|
|
4044
|
+
// derives the required slots from `Intl.PluralRules`.
|
|
4045
|
+
//
|
|
4046
|
+
// objectui#7481 — five `tool.*` entries are NEWER than the registry above:
|
|
4047
|
+
// `get_authoring_rules` (cloud#1837), `load_tools`, `open_record`, `test_flow`
|
|
4048
|
+
// and `toggle_flow` are registered by cloud `service-ai-studio` but the pinned
|
|
4049
|
+
// `@objectstack/spec` snapshot does not list them yet. They are kept here on
|
|
4050
|
+
// purpose: a step label the user reads must not wait on a pin bump. When the
|
|
4051
|
+
// pin advances, `chatbotToolLabels-locale-parity-7481` starts checking them
|
|
4052
|
+
// against the registry instead of against its own hand-held list.
|
|
4053
|
+
chatbot: {
|
|
4054
|
+
answer: {
|
|
4055
|
+
showFull: 'Show full answer',
|
|
4056
|
+
collapse: 'Collapse',
|
|
4057
|
+
expandTable: 'Expand',
|
|
4058
|
+
exitExpandedTable: 'Close',
|
|
4059
|
+
},
|
|
4060
|
+
tool: {
|
|
4061
|
+
aggregate_data: 'Aggregate the data',
|
|
4062
|
+
get_record: 'Read the record',
|
|
4063
|
+
query_data: 'Query the data',
|
|
4064
|
+
query_records: 'Look up the records',
|
|
4065
|
+
search_knowledge: 'Search the knowledge base',
|
|
4066
|
+
visualize_data: 'Chart the data',
|
|
4067
|
+
add_field: 'Add a field',
|
|
4068
|
+
apply_blueprint: 'Build the app from the plan',
|
|
4069
|
+
apply_edit: 'Apply the change',
|
|
4070
|
+
create_metadata: 'Create a metadata item',
|
|
4071
|
+
create_object: 'Create an object',
|
|
4072
|
+
create_package: 'Create a package',
|
|
4073
|
+
create_seed: 'Generate sample data',
|
|
4074
|
+
delete_field: 'Delete a field',
|
|
4075
|
+
describe_metadata: 'Look at the metadata',
|
|
4076
|
+
describe_object: 'Look at the object structure',
|
|
4077
|
+
get_active_package: 'Check the active package',
|
|
4078
|
+
get_authoring_rules: 'Read the authoring rules',
|
|
4079
|
+
get_metadata_schema: 'Read the metadata format',
|
|
4080
|
+
get_package: 'Look at the package',
|
|
4081
|
+
list_metadata: 'List the existing metadata',
|
|
4082
|
+
list_objects: 'List the existing objects',
|
|
4083
|
+
list_packages: 'List the existing packages',
|
|
4084
|
+
load_tools: 'Load more tools',
|
|
4085
|
+
modify_field: 'Change a field',
|
|
4086
|
+
open_record: 'Open the record',
|
|
4087
|
+
propose_blueprint: 'Draft the app plan',
|
|
4088
|
+
set_active_package: 'Switch to the target package',
|
|
4089
|
+
suggest_builder: 'Suggest building it with AI',
|
|
4090
|
+
test_flow: 'Try out the flow',
|
|
4091
|
+
todo_write: 'Note follow-up checks',
|
|
4092
|
+
toggle_flow: 'Turn the flow on or off',
|
|
4093
|
+
update_metadata: 'Update a metadata item',
|
|
4094
|
+
validate_expression: 'Check the expression',
|
|
4095
|
+
verify_build: 'Check the build',
|
|
4096
|
+
},
|
|
4097
|
+
toolState: {
|
|
4098
|
+
agentActivity: 'Agent activity',
|
|
4099
|
+
pending: 'Pending',
|
|
4100
|
+
running: 'Running',
|
|
4101
|
+
awaitingApproval: 'Awaiting approval',
|
|
4102
|
+
responded: 'Responded',
|
|
4103
|
+
completed: 'Completed',
|
|
4104
|
+
error: 'Error',
|
|
4105
|
+
denied: 'Denied',
|
|
4106
|
+
failed: 'Failed',
|
|
4107
|
+
},
|
|
4108
|
+
phase: {
|
|
4109
|
+
build: 'Build',
|
|
4110
|
+
design: 'Design the plan',
|
|
4111
|
+
stepCount: '{{count}} steps',
|
|
4112
|
+
stepCount_one: '{{count}} step',
|
|
4113
|
+
stepCount_other: '{{count}} steps',
|
|
4114
|
+
expand: 'Show steps',
|
|
4115
|
+
collapse: 'Hide steps',
|
|
4116
|
+
},
|
|
4117
|
+
plan: {
|
|
4118
|
+
countObjects: '{{count}} objects',
|
|
4119
|
+
countObjects_one: '{{count}} object',
|
|
4120
|
+
countObjects_other: '{{count}} objects',
|
|
4121
|
+
countViews: '{{count}} views',
|
|
4122
|
+
countViews_one: '{{count}} view',
|
|
4123
|
+
countViews_other: '{{count}} views',
|
|
4124
|
+
countDashboards: '{{count}} dashboards',
|
|
4125
|
+
countDashboards_one: '{{count}} dashboard',
|
|
4126
|
+
countDashboards_other: '{{count}} dashboards',
|
|
4127
|
+
countSeedData: 'sample data',
|
|
4128
|
+
extendTarget: 'Adding to existing app: {{app}}',
|
|
4129
|
+
awaitingConfirm: 'Awaiting confirmation',
|
|
4130
|
+
objectsAndFields: 'Objects and fields',
|
|
4131
|
+
views: 'Views',
|
|
4132
|
+
suggestedField: 'suggested',
|
|
4133
|
+
nameField: 'Name: {{field}}',
|
|
4134
|
+
},
|
|
4135
|
+
build: {
|
|
4136
|
+
building: 'Building {{app}}…',
|
|
4137
|
+
built: 'Built {{app}}',
|
|
4138
|
+
builtAndLive: 'Built and live · {{app}}',
|
|
4139
|
+
appFallback: 'your app',
|
|
4140
|
+
addingSampleData: 'adding sample data',
|
|
4141
|
+
group: {
|
|
4142
|
+
object: 'Objects',
|
|
4143
|
+
view: 'Views',
|
|
4144
|
+
dashboard: 'Dashboards',
|
|
4145
|
+
app: 'App',
|
|
4146
|
+
seed: 'Sample data',
|
|
4147
|
+
},
|
|
4148
|
+
moreArtifacts: '+{{n}} more',
|
|
4149
|
+
verifying: 'Checking the change…',
|
|
4150
|
+
verifyStep: 'step {{n}}',
|
|
4151
|
+
verified: 'Checked the change',
|
|
4152
|
+
unknownPhase: 'Unknown build phase',
|
|
4153
|
+
nextStepsLead: 'Next, you can say: {{steps}}',
|
|
4154
|
+
nextStepQuote: '“{{step}}”',
|
|
4155
|
+
draftPosture: 'Later changes are saved as drafts, and you publish them in Studio.',
|
|
4156
|
+
checksPassed: 'Checks passed {{passed}}/{{total}}',
|
|
4157
|
+
},
|
|
4158
|
+
changes: {
|
|
4159
|
+
planTitle: 'Change plan · {{count}} changes',
|
|
4160
|
+
planTitle_one: 'Change plan · {{count}} change',
|
|
4161
|
+
planTitle_other: 'Change plan · {{count}} changes',
|
|
4162
|
+
saveDraft: 'Save as draft',
|
|
4163
|
+
reviewAndPublish: 'Review changes and publish',
|
|
4164
|
+
undo: 'Undo',
|
|
4165
|
+
undoWithOthers: 'Undo (and {{count}} other drafts)',
|
|
4166
|
+
undoWithOthers_one: 'Undo (and {{count}} other draft)',
|
|
4167
|
+
undoWithOthers_other: 'Undo (and {{count}} other drafts)',
|
|
4168
|
+
undoConfirm: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that are not part of this change.',
|
|
4169
|
+
undoConfirm_one: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that is not part of this change.',
|
|
4170
|
+
undoConfirm_other: 'Undo discards all {{total}} unpublished drafts of this package, including {{count}} that are not part of this change.',
|
|
4171
|
+
undoConfirmUnknown: 'Undo discards every unpublished draft of this package, not only this change.',
|
|
4172
|
+
undoConfirmAction: 'Undo all',
|
|
4173
|
+
undoCancel: 'Cancel',
|
|
4174
|
+
undoing: 'Undoing…',
|
|
4175
|
+
undone: 'Undone',
|
|
4176
|
+
undoFailed: 'Undo failed',
|
|
4177
|
+
kind: {
|
|
4178
|
+
field: 'Field',
|
|
4179
|
+
object: 'Object',
|
|
4180
|
+
view: 'View',
|
|
4181
|
+
dashboard: 'Dashboard',
|
|
4182
|
+
app: 'App',
|
|
4183
|
+
seed: 'Sample data',
|
|
4184
|
+
package: 'App package',
|
|
4185
|
+
},
|
|
4186
|
+
},
|
|
4187
|
+
},
|
|
3064
4188
|
chatbotError: {
|
|
3065
4189
|
title: 'Response failed',
|
|
3066
4190
|
fallbackDetail: 'Something went wrong. Please try again.',
|
|
@@ -3074,10 +4198,18 @@ const en = {
|
|
|
3074
4198
|
buyCredits: 'Buy a credit pack',
|
|
3075
4199
|
upgradePlan: 'Upgrade plan',
|
|
3076
4200
|
},
|
|
4201
|
+
// Plan-tier labels, keyed by the TIER rather than by the surface that draws
|
|
4202
|
+
// them, so every plan-locked mark reuses one string (objectui#12190). The zh
|
|
4203
|
+
// value follows the cloud control plane's own zh plan label.
|
|
4204
|
+
planTier: {
|
|
4205
|
+
teamAndUp: 'Team plan and up',
|
|
4206
|
+
},
|
|
3077
4207
|
environment: {
|
|
3078
|
-
addEnvironment: 'Add environment',
|
|
3079
4208
|
setUpProduction: 'Set up your production environment',
|
|
3080
4209
|
addDevelopment: 'Add development environment',
|
|
4210
|
+
// The plan-locked stand-in for the create action (objectui#12190).
|
|
4211
|
+
// `{{tier}}` is a `planTier.*` label.
|
|
4212
|
+
developmentLocked: 'Development environments · {{tier}}',
|
|
3081
4213
|
// Plan/capacity dialog (EnvironmentEntitlementDialog). Shown on a paid
|
|
3082
4214
|
// conversion path, so it must read in the user's language — cloud#959.
|
|
3083
4215
|
entitlement: {
|
|
@@ -3126,14 +4258,14 @@ const en = {
|
|
|
3126
4258
|
},
|
|
3127
4259
|
unbound: {
|
|
3128
4260
|
title: 'Not connected',
|
|
3129
|
-
body: '
|
|
4261
|
+
body: 'This runtime is not connected to a control plane. Connect opens your cloud account in a new window, where one click approves the link — no ids or credentials are typed into this page.',
|
|
3130
4262
|
connect: 'Connect',
|
|
3131
4263
|
},
|
|
3132
4264
|
},
|
|
3133
4265
|
marketplace: {
|
|
3134
4266
|
title: 'App Marketplace',
|
|
3135
4267
|
subtitle: 'Browse approved apps published to the ObjectStack catalog. Click an app to view details and install it into one of your environments.',
|
|
3136
|
-
searchPlaceholder: 'Search apps by name or
|
|
4268
|
+
searchPlaceholder: 'Search apps by name or app ID…',
|
|
3137
4269
|
searchAria: 'Search marketplace apps',
|
|
3138
4270
|
installed: 'Installed',
|
|
3139
4271
|
installedCount: 'Installed ({{count}})',
|
|
@@ -3143,21 +4275,26 @@ const en = {
|
|
|
3143
4275
|
noMatchFilters: 'No apps match your filters.',
|
|
3144
4276
|
noDescription: 'No description provided.',
|
|
3145
4277
|
back: 'Back to marketplace',
|
|
3146
|
-
installedTitle: 'Installed Apps',
|
|
3147
|
-
installedSubtitle: 'Marketplace packages currently installed into this runtime\'s kernel. Cached manifests live in <code>.objectstack/installed-packages/</code> and survive restarts.',
|
|
3148
|
-
installedEmpty: 'No marketplace apps installed in this runtime yet.',
|
|
3149
4278
|
browseLink: 'Browse the marketplace →',
|
|
3150
|
-
installedAdditiveNote: '
|
|
3151
|
-
installedAt: 'Installed {{when}}',
|
|
3152
|
-
installedBy: 'by {{user}}',
|
|
3153
|
-
installedPackageId: 'package',
|
|
3154
|
-
cachedAs: 'Cached as <code>{{path}}</code>',
|
|
4279
|
+
installedAdditiveNote: 'Uninstall removes the app from the running kernel at once, together with its permission sets and their grants, and deletes the cached manifest so the package does not load at the next start. Records stored in its objects stay in the database.',
|
|
3155
4280
|
versionBadge: 'v{{version}}',
|
|
3156
4281
|
installedBadge: 'Installed v{{version}}',
|
|
4282
|
+
// objectui#11645 — an install-local entry this runtime refused to load at
|
|
4283
|
+
// startup (the listing's `notLoaded` marker), read on Installed Apps.
|
|
4284
|
+
notLoaded: {
|
|
4285
|
+
badge: 'Not loaded',
|
|
4286
|
+
protocolIncompatible: 'This runtime did not load this package: it targets protocol {{requiredRange}}, which this runtime does not support.',
|
|
4287
|
+
otherReason: 'This runtime did not load this package ({{code}}).',
|
|
4288
|
+
},
|
|
3157
4289
|
load: {
|
|
3158
4290
|
failed: 'Failed to load marketplace',
|
|
3159
4291
|
failedHintConfigured: 'This runtime reaches the marketplace through the control plane at {{url}}. Check that it is online and reachable from here.',
|
|
3160
|
-
failedHintSameOrigin: '
|
|
4292
|
+
failedHintSameOrigin: 'The marketplace catalog is reached through this runtime. Check that the runtime is online and can reach the catalog.',
|
|
4293
|
+
loading: 'Loading the marketplace catalog…',
|
|
4294
|
+
slow: 'Still loading — the marketplace catalog is slow to answer.',
|
|
4295
|
+
retry: 'Retry',
|
|
4296
|
+
unreachable: 'The marketplace catalog could not be reached.',
|
|
4297
|
+
answeredError: 'The marketplace catalog answered with an error (HTTP {{status}}).',
|
|
3161
4298
|
packageFailed: 'Failed to load package',
|
|
3162
4299
|
notFound: 'Not found.',
|
|
3163
4300
|
},
|
|
@@ -3181,10 +4318,15 @@ const en = {
|
|
|
3181
4318
|
purgeSampleData: 'Purge sample data',
|
|
3182
4319
|
purgeConfirm: 'Delete all sample records seeded by this package? User-added records will NOT be touched.',
|
|
3183
4320
|
purgeSuccess: 'Removed {{count}} sample record(s).',
|
|
4321
|
+
purgeSuccess_one: 'Removed {{count}} sample record.',
|
|
4322
|
+
purgeSuccess_other: 'Removed {{count}} sample records.',
|
|
3184
4323
|
purgeNoData: 'No sample records found to purge.',
|
|
3185
4324
|
reseedQueued: 'Sample data will be re-seeded on next environment access.',
|
|
3186
4325
|
reseedLocalSuccess: 'Re-seeded sample data: {{inserted}} inserted, {{updated}} updated.',
|
|
3187
4326
|
reseedPartialErrors: '({{count}} record(s) failed to write)',
|
|
4327
|
+
reseedPartialErrors_one: '({{count}} record failed to write)',
|
|
4328
|
+
reseedPartialErrors_other: '({{count}} records failed to write)',
|
|
4329
|
+
sampleDataKernelUnavailable: 'This control plane has no environment kernel, so sample data cannot be re-seeded or purged from here. Do it from the environment\'s own runtime.',
|
|
3188
4330
|
updateAvailable: 'Update available',
|
|
3189
4331
|
},
|
|
3190
4332
|
action: {
|
|
@@ -3194,6 +4336,7 @@ const en = {
|
|
|
3194
4336
|
installToCloud: 'Install to cloud…',
|
|
3195
4337
|
installed: 'Installed',
|
|
3196
4338
|
installing: 'Installing…',
|
|
4339
|
+
updating: 'Updating…',
|
|
3197
4340
|
uninstall: 'Uninstall',
|
|
3198
4341
|
uninstalling: 'Uninstalling…',
|
|
3199
4342
|
details: 'Details',
|
|
@@ -3211,15 +4354,50 @@ const en = {
|
|
|
3211
4354
|
environmentPlaceholder: 'Pick an environment',
|
|
3212
4355
|
includeSampleData: 'Include sample data',
|
|
3213
4356
|
noEnvs: 'No environments found in your active organization.',
|
|
3214
|
-
noPermission: 'You do not have permission to install apps in any environment. Only organization owners and admins can install — ask your
|
|
4357
|
+
noPermission: 'You do not have permission to install apps in any environment. Only organization owners and admins can install — ask your organization admin.',
|
|
3215
4358
|
signInFirst: 'You need to sign into ObjectStack Cloud first. Click "Open on cloud" below.',
|
|
3216
4359
|
success: 'Installed successfully. Open the environment to see the new app.',
|
|
3217
4360
|
localSuccess: 'Installed v{{version}} to this runtime. "{{name}}" should now appear in the app switcher.',
|
|
4361
|
+
// objectui#12098 — the install answered `hotLoaded: false`: installed, and
|
|
4362
|
+
// the running kernel did not register it (objectstack#22695), so nothing
|
|
4363
|
+
// of it is served before the next restart.
|
|
4364
|
+
localLoadsAtRestart: 'Installed v{{version}} to this runtime. "{{name}}" loads when the runtime next restarts; it does not appear in the app switcher until then.',
|
|
3218
4365
|
localManifestConflict: '{{message}}\nTip: a local app already owns this manifest_id. Remove it from objectstack.config.ts first.',
|
|
3219
4366
|
localUnauthorized: 'Sign in to this runtime first, then try again.',
|
|
3220
4367
|
localMarketplaceUnavailable: 'This runtime has no OS_CLOUD_URL configured, so the marketplace catalog is unreachable.',
|
|
3221
4368
|
updateTo: 'Update → v{{version}}',
|
|
3222
4369
|
installedVersion: 'Installed v{{version}}',
|
|
4370
|
+
// objectui#12087 — an install into THIS environment, from its answer
|
|
4371
|
+
// until the runtime serves the package's app (MarketplacePackagePage).
|
|
4372
|
+
deploying: 'Deploying the app…',
|
|
4373
|
+
deployed: 'The app is deployed and ready.',
|
|
4374
|
+
openApp: 'Open {{name}}',
|
|
4375
|
+
deployTimeout: 'The install was recorded, but this environment is not serving the app yet. It may still be deploying — check again shortly. If it never appears, the package may not have loaded, may include no app, or its app may need a permission you do not hold.',
|
|
4376
|
+
checkAgain: 'Check again',
|
|
4377
|
+
// ADR-0131 D6 — the install modes a package's manifest permits, and
|
|
4378
|
+
// what an unmanaged install answers (MarketplacePackagePage).
|
|
4379
|
+
mode: {
|
|
4380
|
+
label: 'Install mode',
|
|
4381
|
+
managed: 'Managed',
|
|
4382
|
+
managedHint: 'The package stays the authority: it is registered as code, receives its upgrades, and its items are not edited here.',
|
|
4383
|
+
unmanaged: 'Unmanaged copy',
|
|
4384
|
+
unmanagedHint: 'Copied once into this runtime as its own metadata: every item is editable here, and the copy receives no upgrade.',
|
|
4385
|
+
required: 'Choose an install mode to install this package.',
|
|
4386
|
+
},
|
|
4387
|
+
unmanagedSuccess: 'Copied v{{version}} of "{{name}}" into this runtime as its own metadata, in the base {{base}}. The copy is editable and receives no upgrade.',
|
|
4388
|
+
unmanagedStrippedLocks: 'The package locked these items. The copy is editable, so their locks were not copied:',
|
|
4389
|
+
unmanagedIgnored: 'This runtime does not support unmanaged installs, so "{{name}}" was installed managed (registered as code) instead of copied. Upgrade the runtime, then uninstall the package and install it again as an unmanaged copy.',
|
|
4390
|
+
},
|
|
4391
|
+
// objectui#12146 — the install dialog opened as an UPDATE of the copy
|
|
4392
|
+
// this environment holds (MarketplacePackagePage).
|
|
4393
|
+
update: {
|
|
4394
|
+
dialogTitle: 'Update {{name}}',
|
|
4395
|
+
dialogDescCurrent: 'Update the copy installed in this environment ({{host}}).',
|
|
4396
|
+
dialogDescPicker: 'Choose the environment whose installed copy to update. You need to be signed into ObjectStack Cloud.',
|
|
4397
|
+
majorNotice: 'This is a major version update (v{{fromMajor}} → v{{toMajor}}), which may include breaking changes.',
|
|
4398
|
+
releaseNotes: 'Read the v{{version}} release notes',
|
|
4399
|
+
success: 'Updated to v{{version}}.',
|
|
4400
|
+
deployTimeout: 'The update was recorded, but this environment is not serving v{{version}} yet. It may still be deploying — check again shortly.',
|
|
3223
4401
|
},
|
|
3224
4402
|
// objectui#3546 — the MarketplacePage "Your organization" strip.
|
|
3225
4403
|
org: {
|
|
@@ -3237,7 +4415,8 @@ const en = {
|
|
|
3237
4415
|
reviewed: 'Reviewed & approved',
|
|
3238
4416
|
unreviewed: 'Not yet reviewed',
|
|
3239
4417
|
signed: 'Signed',
|
|
3240
|
-
grantsIntro: '
|
|
4418
|
+
grantsIntro: 'This package requests:',
|
|
4419
|
+
notEnforced: 'Recorded at install, and re-confirmed if a later version asks for more — but the runtime does not yet restrict the package to this list.',
|
|
3241
4420
|
services: 'Platform services',
|
|
3242
4421
|
hooks: 'Lifecycle hooks',
|
|
3243
4422
|
network: 'Network access',
|
|
@@ -3261,11 +4440,20 @@ const en = {
|
|
|
3261
4440
|
dismiss: 'Dismiss',
|
|
3262
4441
|
confirmedToast: '"{{set}}" is now granted to {{anchor}}.',
|
|
3263
4442
|
dismissedToast: 'Suggestion for "{{set}}" dismissed.',
|
|
4443
|
+
guestUnsupported: 'Cannot be granted here: the Guest position takes no sets from accepted suggestions.',
|
|
4444
|
+
acceptedState: '"{{set}}" was accepted for all signed-in users (the Everyone position).',
|
|
4445
|
+
notInForceState: '"{{set}}" was accepted but is not in force yet: the Everyone position did not change on this request. The server log says why.',
|
|
4446
|
+
dismissedState: '"{{set}}" is not granted: the suggestion was dismissed or revoked.',
|
|
4447
|
+
revoke: 'Revoke',
|
|
4448
|
+
revoking: 'Revoking…',
|
|
4449
|
+
revokedToast: 'Acceptance of "{{set}}" revoked.',
|
|
3264
4450
|
},
|
|
3265
4451
|
uninstall: {
|
|
3266
|
-
confirm: 'Uninstall {{manifestId}} v{{version}} from this runtime?\n\nThe cached manifest will be removed.
|
|
3267
|
-
successInList: 'Removed {{manifestId}}
|
|
3268
|
-
successInDetail: 'Removed
|
|
4452
|
+
confirm: 'Uninstall {{manifestId}} v{{version}} from this runtime?\n\nThe app will leave the running kernel at once, together with its permission sets and their grants, and its cached manifest will be removed. Records stored in its objects stay in the database.',
|
|
4453
|
+
successInList: 'Removed {{manifestId}}: the app has left the running kernel, with its permission sets and their grants. Records stored in its objects stay in the database.',
|
|
4454
|
+
successInDetail: 'Removed {{manifestId}} and its cached manifest: the app has left the running kernel, with its permission sets and their grants. Records stored in its objects stay in the database.',
|
|
4455
|
+
confirmNotLoaded: 'Uninstall {{manifestId}} v{{version}} from this runtime?\n\nThe cached manifest will be removed. This runtime did not load the package, so none of it is running.',
|
|
4456
|
+
successNotLoaded: 'Removed {{manifestId}}. It was not loaded, so no restart is needed.',
|
|
3269
4457
|
},
|
|
3270
4458
|
accessDenied: {
|
|
3271
4459
|
title: 'App Marketplace is admin-only',
|
|
@@ -3288,30 +4476,19 @@ const en = {
|
|
|
3288
4476
|
storage: 'Storage',
|
|
3289
4477
|
other: 'Other',
|
|
3290
4478
|
},
|
|
3291
|
-
pricing: {
|
|
3292
|
-
free: 'Free',
|
|
3293
|
-
freemium: 'Freemium',
|
|
3294
|
-
paid: 'Paid',
|
|
3295
|
-
subscription: 'Subscription',
|
|
3296
|
-
'usage-based': 'Usage-based',
|
|
3297
|
-
'contact-sales': 'Contact Sales',
|
|
3298
|
-
},
|
|
3299
4479
|
relativeTime: {
|
|
3300
4480
|
today: 'today',
|
|
3301
4481
|
daysAgo: '{{count}}d ago',
|
|
3302
4482
|
monthsAgo: '{{count}}mo ago',
|
|
4483
|
+
monthsAgo_one: '{{count}}mo ago',
|
|
4484
|
+
monthsAgo_other: '{{count}}mo ago',
|
|
3303
4485
|
yearsAgo: '{{count}}y ago',
|
|
4486
|
+
yearsAgo_one: '{{count}}y ago',
|
|
4487
|
+
yearsAgo_other: '{{count}}y ago',
|
|
3304
4488
|
},
|
|
3305
4489
|
},
|
|
3306
|
-
approvals: {
|
|
3307
|
-
approve: 'Approve',
|
|
3308
|
-
reject: 'Reject',
|
|
3309
|
-
comment: 'Comment (optional)',
|
|
3310
|
-
approveSuccess: 'Approved',
|
|
3311
|
-
rejectSuccess: 'Rejected',
|
|
3312
|
-
rejectConfirm: 'Reject this approval request?',
|
|
3313
|
-
},
|
|
3314
4490
|
approvalsInbox: {
|
|
4491
|
+
recordUnresolvable: 'This record cannot be opened',
|
|
3315
4492
|
loadMore: 'Load more',
|
|
3316
4493
|
loadingMore: 'Loading…',
|
|
3317
4494
|
loadedOf: 'Loaded {{loaded}} of {{total}}',
|
|
@@ -3330,6 +4507,8 @@ const en = {
|
|
|
3330
4507
|
requestInfoSent: 'Sent back to the requester for more information',
|
|
3331
4508
|
remindBtn: 'Send reminder',
|
|
3332
4509
|
remindSuccess: 'Reminder sent to {{count}} approver(s)',
|
|
4510
|
+
remindSuccess_one: 'Reminder sent to {{count}} approver',
|
|
4511
|
+
remindSuccess_other: 'Reminder sent to {{count}} approvers',
|
|
3333
4512
|
remindThrottled: 'A reminder was sent recently — try again later.',
|
|
3334
4513
|
replyPlaceholder: 'Reply on this request…',
|
|
3335
4514
|
slaRemaining: 'SLA {{dur}} left',
|
|
@@ -3346,8 +4525,11 @@ const en = {
|
|
|
3346
4525
|
progressApprovals: 'Approvals — {{got}} of {{need}}',
|
|
3347
4526
|
progressGroups: 'Sign-off progress — {{got}} of {{need}} groups',
|
|
3348
4527
|
progressEligible: '{{count}} eligible approver(s)',
|
|
4528
|
+
progressEligible_one: '{{count}} eligible approver',
|
|
4529
|
+
progressEligible_other: '{{count}} eligible approvers',
|
|
3349
4530
|
progressBar: 'Decision progress',
|
|
3350
4531
|
declaredActions: 'Actions',
|
|
4532
|
+
decisionPanelOffRequestPage: 'The approval decision panel only works on approval request pages.',
|
|
3351
4533
|
attachmentChip: 'Attachment',
|
|
3352
4534
|
attachmentOpenFailed: 'Could not open the attachment — please try again',
|
|
3353
4535
|
approveOneTitle: 'Approve "{{title}}"?',
|
|
@@ -3377,6 +4559,8 @@ const en = {
|
|
|
3377
4559
|
filterCount: '{{shown}} of {{total}}',
|
|
3378
4560
|
selected: 'selected',
|
|
3379
4561
|
actionableCount: '({{count}} actionable)',
|
|
4562
|
+
actionableCount_one: '({{count}} actionable)',
|
|
4563
|
+
actionableCount_other: '({{count}} actionable)',
|
|
3380
4564
|
selectAll: 'Select all',
|
|
3381
4565
|
selectRow: 'Select request',
|
|
3382
4566
|
colRequest: 'Request',
|
|
@@ -3411,6 +4595,9 @@ const en = {
|
|
|
3411
4595
|
emptyPending: "You're all caught up — nothing is waiting on you.",
|
|
3412
4596
|
emptyOther: 'Nothing here yet.',
|
|
3413
4597
|
emptyViewAll: 'Browse all requests',
|
|
4598
|
+
waitingOnOthers: '{{count}} requests are waiting on other approvers',
|
|
4599
|
+
waitingOnOthers_one: '{{count}} request is waiting on other approvers',
|
|
4600
|
+
waitingOnOthers_other: '{{count}} requests are waiting on other approvers',
|
|
3414
4601
|
noMatches: 'No matches for current filters.',
|
|
3415
4602
|
keyboardHint: 'Keyboard: j/k move · Enter open · x select · a approve · r reject',
|
|
3416
4603
|
drawerTitle: 'Approval Request',
|
|
@@ -3428,12 +4615,12 @@ const en = {
|
|
|
3428
4615
|
overrideActionLabel: 'Override {{action}}',
|
|
3429
4616
|
overrideNotice: 'You hold no approver slot on this step. Continuing uses your admin override: it finalises the step immediately, bypassing any approver who has not acted. The decision is recorded as an admin override.',
|
|
3430
4617
|
overrideNoticeWho: 'You hold no approver slot on this step. Continuing uses your admin override: it finalises the step immediately and bypasses the approvers who have not acted — {{who}}. The decision is recorded as an admin override.',
|
|
4618
|
+
overrideReassignNotice: 'You hold no approver slot on this step. Continuing uses your admin override: the step moves to the new approver you pick, replacing any approver who has not acted. The request stays pending and waits on the new approver. The reassignment is recorded as an admin override.',
|
|
4619
|
+
overrideReassignNoticeWho: 'You hold no approver slot on this step. Continuing uses your admin override: the step moves to the new approver you pick, replacing the approvers who have not acted — {{who}}. The request stays pending and waits on the new approver. The reassignment is recorded as an admin override.',
|
|
4620
|
+
overrideRecallNotice: 'You did not submit this request. Continuing uses your admin override: the request is withdrawn, any approver who has not acted can no longer act on it, and the record is unlocked.',
|
|
4621
|
+
overrideRecallNoticeWho: 'You did not submit this request. Continuing uses your admin override: the request is withdrawn, the record is unlocked, and the approvers who have not acted can no longer act on it — {{who}}.',
|
|
3431
4622
|
viaOverrideChip: 'Admin override',
|
|
3432
4623
|
viaOverrideHint: 'The actor held no approver slot on this step — admitted by the admin-override path.',
|
|
3433
|
-
rawData: 'Raw data (JSON)',
|
|
3434
|
-
copy: 'Copy',
|
|
3435
|
-
copied: 'Copied',
|
|
3436
|
-
copyFailed: 'Copy failed',
|
|
3437
4624
|
overrideActor: 'Act as another identity (admin)',
|
|
3438
4625
|
actor: 'Actor',
|
|
3439
4626
|
auto: 'Auto',
|
|
@@ -3450,11 +4637,19 @@ const en = {
|
|
|
3450
4637
|
approveN: 'Approve {{count}}',
|
|
3451
4638
|
rejectN: 'Reject {{count}}',
|
|
3452
4639
|
bulkApproveTitle: 'Approve {{count}} requests?',
|
|
4640
|
+
bulkApproveTitle_one: 'Approve {{count}} request?',
|
|
4641
|
+
bulkApproveTitle_other: 'Approve {{count}} requests?',
|
|
3453
4642
|
bulkApproveBody: 'Each request is approved with your identity and its flow continues down the approve branch.',
|
|
3454
4643
|
bulkRejectTitle: 'Reject {{count}} requests?',
|
|
4644
|
+
bulkRejectTitle_one: 'Reject {{count}} request?',
|
|
4645
|
+
bulkRejectTitle_other: 'Reject {{count}} requests?',
|
|
3455
4646
|
bulkRejectBody: 'This rejects the selected requests and notifies their submitters.',
|
|
3456
4647
|
bulkApproved: 'Approved {{count}} requests',
|
|
4648
|
+
bulkApproved_one: 'Approved {{count}} request',
|
|
4649
|
+
bulkApproved_other: 'Approved {{count}} requests',
|
|
3457
4650
|
bulkRejected: 'Rejected {{count}} requests',
|
|
4651
|
+
bulkRejected_one: 'Rejected {{count}} request',
|
|
4652
|
+
bulkRejected_other: 'Rejected {{count}} requests',
|
|
3458
4653
|
bulkPartial: '{{ok}} succeeded, {{fail}} failed: {{which}}',
|
|
3459
4654
|
rejectOneTitle: 'Reject "{{title}}"?',
|
|
3460
4655
|
rejectOneBody: 'This rejects the request and notifies the submitter.',
|
|
@@ -3479,8 +4674,14 @@ const en = {
|
|
|
3479
4674
|
alreadyDecided: 'This request was already decided. Refresh the list.',
|
|
3480
4675
|
justNow: 'just now',
|
|
3481
4676
|
minutesAgo: '{{count}}m ago',
|
|
4677
|
+
minutesAgo_one: '{{count}}m ago',
|
|
4678
|
+
minutesAgo_other: '{{count}}m ago',
|
|
3482
4679
|
hoursAgo: '{{count}}h ago',
|
|
4680
|
+
hoursAgo_one: '{{count}}h ago',
|
|
4681
|
+
hoursAgo_other: '{{count}}h ago',
|
|
3483
4682
|
daysAgo: '{{count}}d ago',
|
|
4683
|
+
daysAgo_one: '{{count}}d ago',
|
|
4684
|
+
daysAgo_other: '{{count}}d ago',
|
|
3484
4685
|
},
|
|
3485
4686
|
filterBuilder: {
|
|
3486
4687
|
where: 'Where',
|
|
@@ -3504,28 +4705,32 @@ const en = {
|
|
|
3504
4705
|
rangeEnd: 'To',
|
|
3505
4706
|
operators: {
|
|
3506
4707
|
equals: 'Equals',
|
|
3507
|
-
|
|
4708
|
+
not_equals: 'Does not equal',
|
|
3508
4709
|
contains: 'Contains',
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
4710
|
+
icontains: 'Contains (ignore case)',
|
|
4711
|
+
not_contains: 'Does not contain',
|
|
4712
|
+
is_empty: 'Is empty',
|
|
4713
|
+
is_not_empty: 'Is not empty',
|
|
4714
|
+
greater_than: 'Greater than',
|
|
4715
|
+
less_than: 'Less than',
|
|
4716
|
+
greater_than_or_equal: 'Greater than or equal',
|
|
4717
|
+
less_than_or_equal: 'Less than or equal',
|
|
3517
4718
|
before: 'Before',
|
|
3518
4719
|
after: 'After',
|
|
3519
4720
|
between: 'Between',
|
|
3520
4721
|
in: 'In',
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
4722
|
+
not_in: 'Not in',
|
|
4723
|
+
starts_with: 'Starts with',
|
|
4724
|
+
ends_with: 'Ends with',
|
|
4725
|
+
is_null: 'Is null',
|
|
4726
|
+
is_not_null: 'Is not null',
|
|
3526
4727
|
exists: 'Is set',
|
|
3527
4728
|
notExists: 'Is not set',
|
|
3528
4729
|
},
|
|
4730
|
+
emptyCheckHint: {
|
|
4731
|
+
text: '"{{isEmpty}}" also matches blank text; "{{isNull}}" matches only a missing value.',
|
|
4732
|
+
list: '"{{isEmpty}}" also matches an empty list; "{{isNull}}" matches only a missing value.',
|
|
4733
|
+
},
|
|
3529
4734
|
},
|
|
3530
4735
|
sortBuilder: {
|
|
3531
4736
|
sortBy: 'Sort by',
|
|
@@ -3545,13 +4750,11 @@ const en = {
|
|
|
3545
4750
|
// The generic action words (Save / Cancel / Edit / Delete) are NOT repeated
|
|
3546
4751
|
// here — the thread reads them from `common`.
|
|
3547
4752
|
collaboration: {
|
|
3548
|
-
// Thread header.
|
|
3549
|
-
//
|
|
3550
|
-
// `detail`: zh/ja/ko have no separate singular form, so those packs would
|
|
3551
|
-
// legitimately omit the `_one` half and `all-locales-key-parity` reads a
|
|
3552
|
-
// legitimately-absent half as a lost key.
|
|
4753
|
+
// Thread header. An i18next count family (objectui#11445): the component
|
|
4754
|
+
// passes `count` and i18next picks the slot each pack's CLDR rules select.
|
|
3553
4755
|
commentCount: '{{count}} comments',
|
|
3554
|
-
|
|
4756
|
+
commentCount_one: '{{count}} comment',
|
|
4757
|
+
commentCount_other: '{{count}} comments',
|
|
3555
4758
|
// Appended to the count, separator included, so a translator owns the
|
|
3556
4759
|
// whole phrase rather than inheriting an English-shaped ` · ` glue.
|
|
3557
4760
|
resolvedSuffix: ' · Resolved',
|
|
@@ -3564,14 +4767,21 @@ const en = {
|
|
|
3564
4767
|
// existing minute/hour/day buckets and no date library was introduced.
|
|
3565
4768
|
justNow: 'just now',
|
|
3566
4769
|
minutesAgo: '{{count}}m ago',
|
|
4770
|
+
minutesAgo_one: '{{count}}m ago',
|
|
4771
|
+
minutesAgo_other: '{{count}}m ago',
|
|
3567
4772
|
hoursAgo: '{{count}}h ago',
|
|
4773
|
+
hoursAgo_one: '{{count}}h ago',
|
|
4774
|
+
hoursAgo_other: '{{count}}h ago',
|
|
3568
4775
|
daysAgo: '{{count}}d ago',
|
|
4776
|
+
daysAgo_one: '{{count}}d ago',
|
|
4777
|
+
daysAgo_other: '{{count}}d ago',
|
|
3569
4778
|
edited: '(edited)',
|
|
3570
4779
|
// Reaction-chip tooltip. A DEDICATED pair rather than `detail.reactionCount`:
|
|
3571
4780
|
// that one interpolates `{{emoji}}`, and here the emoji is the chip's
|
|
3572
4781
|
// visible label with nothing to hand the placeholder.
|
|
3573
4782
|
reactionCount: '{{count}} reactions',
|
|
3574
|
-
|
|
4783
|
+
reactionCount_one: '{{count}} reaction',
|
|
4784
|
+
reactionCount_other: '{{count}} reactions',
|
|
3575
4785
|
addThumbsUp: 'Add thumbs up',
|
|
3576
4786
|
reply: 'Reply',
|
|
3577
4787
|
// Accessible names for the three emoji-only controls (objectui#3441).
|
|
@@ -3597,12 +4807,14 @@ const en = {
|
|
|
3597
4807
|
send: 'Send',
|
|
3598
4808
|
// Presence avatar stack (objectui#3440). `presentUserCount*` is the avatar
|
|
3599
4809
|
// group's `aria-label` — with only images and initials inside, that label
|
|
3600
|
-
// IS the control for a screen reader.
|
|
3601
|
-
//
|
|
4810
|
+
// IS the control for a screen reader. Count families, like `commentCount`
|
|
4811
|
+
// above.
|
|
3602
4812
|
presentUserCount: '{{count}} users present',
|
|
3603
|
-
|
|
4813
|
+
presentUserCount_one: '{{count}} user present',
|
|
4814
|
+
presentUserCount_other: '{{count}} users present',
|
|
3604
4815
|
moreUserCount: '{{count}} more users',
|
|
3605
|
-
|
|
4816
|
+
moreUserCount_one: '{{count}} more user',
|
|
4817
|
+
moreUserCount_other: '{{count}} more users',
|
|
3606
4818
|
// Avatar tooltip. The parentheses are part of the translation, spacing
|
|
3607
4819
|
// included, so the CJK packs can drop the space English puts before `(`.
|
|
3608
4820
|
userStatusTitle: '{{name}} ({{status}})',
|
|
@@ -3617,6 +4829,25 @@ const en = {
|
|
|
3617
4829
|
// comma-joined, already-truncated label list built at the call site.
|
|
3618
4830
|
wizard: {
|
|
3619
4831
|
missingRequired: 'Please complete the required fields: {{fields}}',
|
|
4832
|
+
// The wizard's footer and step chrome (objectui#10999). The generic verbs
|
|
4833
|
+
// it shows come from `common.cancel`, `common.next`, `form.create`,
|
|
4834
|
+
// `form.update` and `form.stepOf`; these five are the wizard's own.
|
|
4835
|
+
// The Previous-step button. Not `common.back`: some packs say a wizard's
|
|
4836
|
+
// step back with a different word from a page's back (zh reads "previous
|
|
4837
|
+
// step" here and "return" for `common.back`), and the wizard spelling is
|
|
4838
|
+
// the one `grid.import.back` and `grid.bulk.back` already use.
|
|
4839
|
+
back: 'Back',
|
|
4840
|
+
// The final button while the record is being written.
|
|
4841
|
+
submitting: 'Submitting…',
|
|
4842
|
+
// The step indicator's label for a step that declares no `label`.
|
|
4843
|
+
// `{{n}}` is the 1-based step number.
|
|
4844
|
+
stepFallback: 'Step {{n}}',
|
|
4845
|
+
// The step indicator's `aria-label` — what a screen reader calls the list
|
|
4846
|
+
// of steps.
|
|
4847
|
+
progressLabel: 'Progress',
|
|
4848
|
+
// Shown in place of the fields on a step that has none (a final review
|
|
4849
|
+
// step is the usual case).
|
|
4850
|
+
emptyStep: 'No fields configured for this step',
|
|
3620
4851
|
},
|
|
3621
4852
|
// The screen-flow runner dialog (`app-shell/views/FlowRunner`) — the modal a
|
|
3622
4853
|
// `type: 'flow'` action opens when its run pauses at a `screen` node.
|
|
@@ -3704,6 +4935,11 @@ const en = {
|
|
|
3704
4935
|
setDefaultFailed: 'Failed to set default app: {{reason}}',
|
|
3705
4936
|
appDeleted: '{{name}} deleted',
|
|
3706
4937
|
deleteFailed: 'Failed to delete app: {{reason}}',
|
|
4938
|
+
// A `reset: false` answer: no customization row existed, so nothing was
|
|
4939
|
+
// removed. `{{reason}}` is the server's own sentence, passed through raw.
|
|
4940
|
+
nothingToDelete: 'Nothing to delete for {{name}}: {{reason}}',
|
|
4941
|
+
// `{{reason}}` above when that answer carried no sentence of its own.
|
|
4942
|
+
alreadyAtDefault: 'it is already at its package default',
|
|
3707
4943
|
// `{{n}}` is the count that actually LANDED, not the selection size — a
|
|
3708
4944
|
// bulk toggle is N independent writes with no transaction behind them.
|
|
3709
4945
|
bulkEnabled: '{{n}} apps enabled',
|
|
@@ -3720,5 +4956,188 @@ const en = {
|
|
|
3720
4956
|
bulkOperationFailed: 'Bulk operation failed: {{reason}}',
|
|
3721
4957
|
},
|
|
3722
4958
|
},
|
|
4959
|
+
// objectui#6301 — Setup › Packaged automation (ADR-0126 §7.4): the
|
|
4960
|
+
// operational surface for the flows an installed package ships. Authoring
|
|
4961
|
+
// stays in Studio, so this group has no editing vocabulary at all; it is
|
|
4962
|
+
// on/off, clone, and the states those two produce.
|
|
4963
|
+
//
|
|
4964
|
+
// ⛔ No drift or ancestry wording anywhere in this group (ADR-0126 §9). There
|
|
4965
|
+
// is deliberately no "customized", no "based on v3", no "out of date" — the
|
|
4966
|
+
// platform does not track that lineage, and a translatable string for it is
|
|
4967
|
+
// the cheapest way for the surface to grow one.
|
|
4968
|
+
//
|
|
4969
|
+
// ⛔ Server refusals are NOT in this group either. The posture gate, the
|
|
4970
|
+
// subflow guard and the clone name conflict all arrive as server-authored
|
|
4971
|
+
// prose and are rendered verbatim; the four `*Failed*` keys below are the
|
|
4972
|
+
// last-resort fallbacks for a response that carried no message at all.
|
|
4973
|
+
packagedAutomation: {
|
|
4974
|
+
title: 'Packaged automation',
|
|
4975
|
+
// Covers BOTH sections since ADR-0126 §8 item 2 put packaged actions on
|
|
4976
|
+
// this page: only flows can be cloned, so the clone clause names them.
|
|
4977
|
+
subtitle: 'Flows and actions shipped by installed packages. Turn one off for this deployment, or clone a flow under a new name to customize it. Editing happens in Studio.',
|
|
4978
|
+
refresh: 'Refresh',
|
|
4979
|
+
// Section headings — the page carries two tables.
|
|
4980
|
+
flowsHeading: 'Packaged flows',
|
|
4981
|
+
actionsHeading: 'Packaged actions',
|
|
4982
|
+
colFlow: 'Flow',
|
|
4983
|
+
colActivation: 'Activation',
|
|
4984
|
+
colActions: 'Actions',
|
|
4985
|
+
// The switch's accessible name — the only place a row's label is spoken.
|
|
4986
|
+
toggleLabel: 'Activation for {{label}}',
|
|
4987
|
+
on: 'On',
|
|
4988
|
+
off: 'Off',
|
|
4989
|
+
// The Activation badge on a flow whose switch is ON but whose trigger the
|
|
4990
|
+
// engine has not armed on this deployment (objectui#13159): the switch
|
|
4991
|
+
// keeps the flag, this says the flow does not run. The same words as
|
|
4992
|
+
// Studio's rail for the same state (`engine.studio.auto.notRunning`).
|
|
4993
|
+
notRunning: 'Not running here',
|
|
4994
|
+
clone: 'Clone',
|
|
4995
|
+
cloneTitle: 'Clone packaged flow',
|
|
4996
|
+
cloneBody: 'The copy carries the whole definition and takes a new machine name and label. Edit the copy in Studio.',
|
|
4997
|
+
cloneName: 'New machine name',
|
|
4998
|
+
cloneLabel: 'New label',
|
|
4999
|
+
cancel: 'Cancel',
|
|
5000
|
+
cloneConfirm: 'Create clone',
|
|
5001
|
+
cloneCreated: 'Created flow "{{name}}".',
|
|
5002
|
+
// The clone result's next steps (objectui#13270): switch the flow the
|
|
5003
|
+
// admin cloned from off through its own toggle, or open the clone where
|
|
5004
|
+
// it is edited. The sharing-rule clone's words for the same offer.
|
|
5005
|
+
cloneSwitchSourceOff: 'Switch "{{label}}" off',
|
|
5006
|
+
cloneSourceOff: 'The packaged flow "{{label}}" is switched off.',
|
|
5007
|
+
cloneOpen: 'Open the clone in Studio',
|
|
5008
|
+
emptyTitle: 'No packaged flows',
|
|
5009
|
+
emptyBody: 'No installed package ships an automation flow on this deployment. Flows you author yourself live in Studio.',
|
|
5010
|
+
loadFailed: 'Could not load packaged automation.',
|
|
5011
|
+
// Two keys per action, not one: the response arm has an HTTP status to
|
|
5012
|
+
// name and the transport-exception arm does not, and a single key cannot
|
|
5013
|
+
// carry a hole only half its call sites can fill.
|
|
5014
|
+
// Artifact-neutral by wording, and shared by BOTH sections' toggles: the
|
|
5015
|
+
// sentence says nothing about flows, so the actions half reuses it rather
|
|
5016
|
+
// than defining a second key with the same English in ten packs.
|
|
5017
|
+
toggleFailedHttp: 'Could not change activation (HTTP {{status}}).',
|
|
5018
|
+
toggleFailed: 'Could not change activation.',
|
|
5019
|
+
cloneFailedHttp: 'Could not clone this flow (HTTP {{status}}).',
|
|
5020
|
+
cloneFailed: 'Could not clone this flow.',
|
|
5021
|
+
// The chip an unarmed flow row's platform sentence opens from
|
|
5022
|
+
// (objectui#12609). ⛔ Generic on purpose: the same word on every row that
|
|
5023
|
+
// carries a sentence, whatever the sentence says. The sentence itself is
|
|
5024
|
+
// the server's and is never kept in a pack; a label naming its cause would
|
|
5025
|
+
// be the console classifying a field the contract says not to parse.
|
|
5026
|
+
reasonDetails: 'Details',
|
|
5027
|
+
// ── Packaged ACTIONS section (ADR-0126 §8 item 2, ruling 3) ────────────
|
|
5028
|
+
// ⛔ No clone key here on purpose: the action-clone half is unchartered,
|
|
5029
|
+
// and a string is the cheapest way for an unchartered surface to appear.
|
|
5030
|
+
actionsSubtitle: 'Actions shipped by installed packages. Turn one off for this deployment and it stops running everywhere it is offered. Authoring your own action alongside it stays open in Studio.',
|
|
5031
|
+
colAction: 'Action',
|
|
5032
|
+
colObject: 'Object',
|
|
5033
|
+
// The object is part of the accessible name because it is part of the
|
|
5034
|
+
// identity — two objects may declare the same action name.
|
|
5035
|
+
actionToggleLabel: 'Activation for {{label}} on {{object}}',
|
|
5036
|
+
actionsEmptyTitle: 'No packaged actions',
|
|
5037
|
+
actionsEmptyBody: 'No installed package declares an action on this deployment. Actions you author yourself live in Studio.',
|
|
5038
|
+
actionsLoadFailed: 'Could not load packaged actions.',
|
|
5039
|
+
},
|
|
5040
|
+
element: {
|
|
5041
|
+
// objectui#10951 — `element:number` authored with an aggregate and no
|
|
5042
|
+
// `dataSource.object` (objectui#11880: the flat `object` is not read). Kept
|
|
5043
|
+
// terse: this pack is eager, and the console closure budget weighs it.
|
|
5044
|
+
number: {
|
|
5045
|
+
noObject: 'No object named: set dataSource.object.',
|
|
5046
|
+
// objectui#12910 — the title of the panel this block draws when its
|
|
5047
|
+
// `dataSource.view` names nothing.
|
|
5048
|
+
sourceUnresolved: 'This metric’s data source could not be resolved',
|
|
5049
|
+
},
|
|
5050
|
+
// objectui#12910 — `element:image` with no `src`.
|
|
5051
|
+
image: {
|
|
5052
|
+
noSource: 'No image source',
|
|
5053
|
+
},
|
|
5054
|
+
// objectui#12910 — `element:record_picker`'s panel title, same case.
|
|
5055
|
+
recordPicker: {
|
|
5056
|
+
sourceUnresolved: 'This record picker’s data source could not be resolved',
|
|
5057
|
+
},
|
|
5058
|
+
// objectui#12920 — the same panel title for every other data-bound block,
|
|
5059
|
+
// one key per block kind. `element:number` above also titles the
|
|
5060
|
+
// dashboard's `object-metric`; `component` is the @object-ui/react
|
|
5061
|
+
// panel's own default, for a block that passes no title.
|
|
5062
|
+
calendar: {
|
|
5063
|
+
sourceUnresolved: 'This calendar’s data source could not be resolved',
|
|
5064
|
+
},
|
|
5065
|
+
chart: {
|
|
5066
|
+
sourceUnresolved: 'This chart’s data source could not be resolved',
|
|
5067
|
+
},
|
|
5068
|
+
pivotTable: {
|
|
5069
|
+
sourceUnresolved: 'This pivot table’s data source could not be resolved',
|
|
5070
|
+
},
|
|
5071
|
+
detailView: {
|
|
5072
|
+
sourceUnresolved: 'This detail view’s data source could not be resolved',
|
|
5073
|
+
},
|
|
5074
|
+
relatedList: {
|
|
5075
|
+
sourceUnresolved: 'This related list’s data source could not be resolved',
|
|
5076
|
+
// The panel drawn when the list's `parentDataSource` read fails.
|
|
5077
|
+
parentUnreadable: 'This related list’s parent record could not be read',
|
|
5078
|
+
},
|
|
5079
|
+
form: {
|
|
5080
|
+
sourceUnresolved: 'This form’s data source could not be resolved',
|
|
5081
|
+
},
|
|
5082
|
+
lineItems: {
|
|
5083
|
+
sourceUnresolved: 'This line-items panel’s data source could not be resolved',
|
|
5084
|
+
},
|
|
5085
|
+
gantt: {
|
|
5086
|
+
sourceUnresolved: 'This gantt chart’s data source could not be resolved',
|
|
5087
|
+
},
|
|
5088
|
+
grid: {
|
|
5089
|
+
sourceUnresolved: 'This grid’s data source could not be resolved',
|
|
5090
|
+
},
|
|
5091
|
+
board: {
|
|
5092
|
+
sourceUnresolved: 'This board’s data source could not be resolved',
|
|
5093
|
+
},
|
|
5094
|
+
listView: {
|
|
5095
|
+
sourceUnresolved: 'This list view’s data source could not be resolved',
|
|
5096
|
+
},
|
|
5097
|
+
map: {
|
|
5098
|
+
sourceUnresolved: 'This map’s data source could not be resolved',
|
|
5099
|
+
},
|
|
5100
|
+
timeline: {
|
|
5101
|
+
sourceUnresolved: 'This timeline’s data source could not be resolved',
|
|
5102
|
+
},
|
|
5103
|
+
component: {
|
|
5104
|
+
sourceUnresolved: 'This component’s data source could not be resolved',
|
|
5105
|
+
// The panel drawn when a block resolved no adapter at all.
|
|
5106
|
+
noDataSource: 'No data source resolved',
|
|
5107
|
+
// objectui#12197 — the two titles of a page element's API binding
|
|
5108
|
+
// (`dataSource: { provider: 'api', … }`): refused by the spec's schema,
|
|
5109
|
+
// or read and failed.
|
|
5110
|
+
apiRefused: 'This component’s API data source is refused',
|
|
5111
|
+
apiUnreadable: 'This component’s API data source could not be read',
|
|
5112
|
+
},
|
|
5113
|
+
// objectui#12910 — `element:metadata_viewer` (the ```metadata doc fence).
|
|
5114
|
+
// A `{{name}}`-style slot that the renderer draws as a `<code>` chip is
|
|
5115
|
+
// filled with a private-use mark and split on, so each language places
|
|
5116
|
+
// the chip. Counts read as "Label: N" so no key needs a plural family.
|
|
5117
|
+
metadataViewer: {
|
|
5118
|
+
missingKey: 'Missing {{key}} for this view.',
|
|
5119
|
+
loading: 'Loading {{name}}…',
|
|
5120
|
+
loadFailed: 'Failed to load {{name}}: {{message}}',
|
|
5121
|
+
notFound: '{{name}} not found.',
|
|
5122
|
+
stateMachine: 'State machine',
|
|
5123
|
+
flow: 'Flow',
|
|
5124
|
+
permission: 'Permission',
|
|
5125
|
+
noStateMachine: 'No state machine on {{object}}.',
|
|
5126
|
+
noStateMachineNamed: 'No state machine named “{{name}}” on {{object}}.',
|
|
5127
|
+
lifecycle: 'Lifecycle of {{object}}',
|
|
5128
|
+
field: 'field {{field}}',
|
|
5129
|
+
initial: 'initial',
|
|
5130
|
+
final: 'final',
|
|
5131
|
+
steps: 'Steps: {{count}}',
|
|
5132
|
+
noSteps: 'No steps to show.',
|
|
5133
|
+
untitledStep: '(step)',
|
|
5134
|
+
hiddenSteps: 'Technical steps hidden: {{count}} · set {{setting}} to show all',
|
|
5135
|
+
objectAccess: 'Object access: {{count}}',
|
|
5136
|
+
noPermissions: 'No object permissions declared.',
|
|
5137
|
+
object: 'Object',
|
|
5138
|
+
unknownType: 'Unknown metadata view type. Expected {{a}}, {{b}} or {{c}}.',
|
|
5139
|
+
unknownTypeNamed: 'Unknown metadata view type “{{type}}”. Expected {{a}}, {{b}} or {{c}}.',
|
|
5140
|
+
},
|
|
5141
|
+
},
|
|
3723
5142
|
};
|
|
3724
5143
|
export default en;
|