@object-ui/i18n 17.6.0 → 17.7.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 +4320 -0
- package/README.md +192 -13
- 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 +7 -13
- package/dist/index.js +41 -17
- package/dist/locales/ar.d.ts +946 -113
- package/dist/locales/ar.js +1095 -161
- package/dist/locales/de.d.ts +618 -113
- package/dist/locales/de.js +715 -134
- package/dist/locales/en.d.ts +632 -127
- package/dist/locales/en.js +1044 -162
- package/dist/locales/es.d.ts +700 -113
- package/dist/locales/es.js +794 -130
- package/dist/locales/fr.d.ts +700 -113
- package/dist/locales/fr.js +795 -132
- package/dist/locales/index.d.ts +6990 -1169
- package/dist/locales/index.js +48 -9
- package/dist/locales/ja.d.ts +618 -113
- package/dist/locales/ja.js +708 -128
- package/dist/locales/ko.d.ts +618 -113
- package/dist/locales/ko.js +712 -132
- package/dist/locales/pt.d.ts +700 -113
- package/dist/locales/pt.js +794 -130
- 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 +782 -113
- package/dist/locales/ru.js +910 -152
- package/dist/locales/zh.d.ts +635 -130
- package/dist/locales/zh.js +725 -131
- 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 +40 -18
- package/dist/useObjectLabel.js +46 -14
- package/dist/useSafeTranslation.js +40 -42
- package/dist/utils/formatting.d.ts +16 -0
- package/dist/utils/formatting.js +23 -3
- 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
|
@@ -30,35 +30,42 @@ const en = {
|
|
|
30
30
|
manage_users: 'Manage Users',
|
|
31
31
|
manage_org_users: 'Manage Organization Users',
|
|
32
32
|
manage_metadata: 'Manage Metadata',
|
|
33
|
+
manage_org_presentation: 'Manage Organization Presentation',
|
|
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',
|
|
38
|
+
manage_sharing: 'Manage Sharing',
|
|
37
39
|
},
|
|
38
40
|
},
|
|
39
41
|
// objectui#3546 slice six — the read-only facet summary + Studio deep-link a
|
|
40
42
|
// `sys_permission_set` record shows for its six authorization facets
|
|
41
43
|
// (ADR-0056 P1, plugin-detail's PermissionFacetLink).
|
|
42
44
|
//
|
|
43
|
-
// The four count labels are plural families.
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
// language at counts
|
|
45
|
+
// The four count labels are plural families. i18next looks up the ONE suffix
|
|
46
|
+
// a language's rules ask for, so every pack spells out every CLDR category its
|
|
47
|
+
// language selects (`en`: `_one`/`_other`; `ru` adds `_few`/`_many`, `ar`
|
|
48
|
+
// `_zero`/`_two`/`_few`/`_many` — objectui#11432); the BASE key (no suffix)
|
|
49
|
+
// answers a call made without a count. `all-locales-key-parity.test.ts`
|
|
50
|
+
// derives the required slots from `Intl.PluralRules`, and
|
|
51
|
+
// `perm-home-namespace-3546.test.tsx` renders every language at counts
|
|
52
|
+
// 1/2/3/5/11/21/100.
|
|
50
53
|
perm: {
|
|
51
54
|
facet: {
|
|
52
55
|
none: 'None',
|
|
53
56
|
more: '+{{count}} more',
|
|
54
57
|
objects: '{{count}} objects',
|
|
55
58
|
objects_one: '{{count}} object',
|
|
59
|
+
objects_other: '{{count}} objects',
|
|
56
60
|
fields: '{{count}} field rules',
|
|
57
61
|
fields_one: '{{count}} field rule',
|
|
62
|
+
fields_other: '{{count}} field rules',
|
|
58
63
|
rls: '{{count}} RLS policies',
|
|
59
64
|
rls_one: '{{count}} RLS policy',
|
|
65
|
+
rls_other: '{{count}} RLS policies',
|
|
60
66
|
tabs: '{{count}} tab rules',
|
|
61
67
|
tabs_one: '{{count}} tab rule',
|
|
68
|
+
tabs_other: '{{count}} tab rules',
|
|
62
69
|
adminScope: 'Delegated admin configured',
|
|
63
70
|
designInStudio: 'Design in Studio →',
|
|
64
71
|
designInStudioHint: 'Design in Studio',
|
|
@@ -80,7 +87,8 @@ const en = {
|
|
|
80
87
|
selectFirst: 'Select {{fields}} first',
|
|
81
88
|
selectRecord: 'Select record',
|
|
82
89
|
recordCount: '{{count}} records',
|
|
83
|
-
|
|
90
|
+
recordCount_one: '{{count}} record',
|
|
91
|
+
recordCount_other: '{{count}} records',
|
|
84
92
|
pageOf: 'Page {{current}} of {{total}}',
|
|
85
93
|
filters: 'Filters',
|
|
86
94
|
clear: 'Clear',
|
|
@@ -137,10 +145,12 @@ const en = {
|
|
|
137
145
|
closeChat: 'Close chat',
|
|
138
146
|
closePanel: 'Close panel',
|
|
139
147
|
resizeDrawer: 'Resize drawer',
|
|
140
|
-
// Count badge on a tab / section header.
|
|
141
|
-
//
|
|
148
|
+
// Count badge on a tab / section header. An i18next count family
|
|
149
|
+
// (objectui#11445): the badge passes `count` and i18next picks the slot
|
|
150
|
+
// each pack's CLDR rules select.
|
|
142
151
|
itemCount: '{{count}} items',
|
|
143
|
-
|
|
152
|
+
itemCount_one: '{{count}} item',
|
|
153
|
+
itemCount_other: '{{count}} items',
|
|
144
154
|
toggleSidebar: 'Toggle sidebar',
|
|
145
155
|
package: 'Package',
|
|
146
156
|
done: 'Done',
|
|
@@ -148,6 +158,16 @@ const en = {
|
|
|
148
158
|
record: 'Record',
|
|
149
159
|
retry: 'Retry',
|
|
150
160
|
printDialogHint: 'Opens your browser’s print dialog (not a PDF export)',
|
|
161
|
+
// The non-grid row ceiling's footnote (objectui#7210). Two keys because
|
|
162
|
+
// there are two conditions: a reported `total` states the fact with BOTH
|
|
163
|
+
// numbers, a missing one cannot name how many. Kept terse deliberately —
|
|
164
|
+
// this copy is eagerly loaded, and since objectui#7399 these bytes are
|
|
165
|
+
// budgeted by the `i18n-locales` chunk, not `framework`. ⛔ That ceiling's
|
|
166
|
+
// headroom is deliberately NOT restated here — it moves on every
|
|
167
|
+
// re-baseline, and the figure that was here went stale.
|
|
168
|
+
// `pnpm check:eager-closure` prints it.
|
|
169
|
+
rowCeilingNote: 'Showing the first {{shown}} of {{total}} records. Narrow the filter.',
|
|
170
|
+
rowCeilingNoteUnknownTotal: 'Showing the first {{shown}} records. Narrow the filter.',
|
|
151
171
|
},
|
|
152
172
|
actions: {
|
|
153
173
|
decisionOutput: {
|
|
@@ -159,6 +179,32 @@ const en = {
|
|
|
159
179
|
acknowledge: 'I have saved this',
|
|
160
180
|
copyAll: 'Copy all',
|
|
161
181
|
},
|
|
182
|
+
// The refusal notice for an action whose `autoTrigger` its own declared
|
|
183
|
+
// `visible` gate outranks (objectui#4191) — the deep link or host asked
|
|
184
|
+
// for it, but the author hid it on this surface.
|
|
185
|
+
notAvailableHere: '"{{action}}" is not available on the current page.',
|
|
186
|
+
// The success toast the action runner shows when no `outcomeMessages`
|
|
187
|
+
// entry applies to the answer and the action declares no `successMessage`;
|
|
188
|
+
// the server's message plays no part (objectui#11344). It is the one
|
|
189
|
+
// success-toast text the runner writes itself (objectui#10900).
|
|
190
|
+
completedSuccessfully: 'Action completed successfully',
|
|
191
|
+
// The runner's other own text (objectui#10969): the error fallbacks when no
|
|
192
|
+
// readable error message reached it, and the Undo label it hands the toast
|
|
193
|
+
// handler for an undoable success toast.
|
|
194
|
+
failed: 'Action failed',
|
|
195
|
+
parallelFailed: 'One or more parallel actions failed',
|
|
196
|
+
undo: 'Undo',
|
|
197
|
+
// The confirmation toast after that Undo has run — written by the console's
|
|
198
|
+
// two undo handlers (`useConsoleActionRuntime` and `RecordDetailView`), not
|
|
199
|
+
// by the runner (objectui#11056).
|
|
200
|
+
undone: 'Change undone',
|
|
201
|
+
// The console's global Ctrl+Z / Ctrl+Shift+Z toasts, raised by
|
|
202
|
+
// `AppContent`'s `useGlobalUndo` handlers once the operation has been
|
|
203
|
+
// undone / redone (objectui#11080). `{{description}}` is the operation's
|
|
204
|
+
// own description, passed through unchanged; the pack owns the words and
|
|
205
|
+
// the word order around it.
|
|
206
|
+
undoneOperation: 'Undo: {{description}}',
|
|
207
|
+
redoneOperation: 'Redo: {{description}}',
|
|
162
208
|
},
|
|
163
209
|
validation: {
|
|
164
210
|
required: '{{field}} is required',
|
|
@@ -181,8 +227,26 @@ const en = {
|
|
|
181
227
|
},
|
|
182
228
|
form: {
|
|
183
229
|
noPermissionToSave: "You don't have permission to save this record.",
|
|
230
|
+
// The notice a record form shows when every field is locked because the
|
|
231
|
+
// object's affordance for the form's mode is closed for this user
|
|
232
|
+
// (objectui#11000). `{{object}}` is the object's label.
|
|
233
|
+
noPermissionToCreate: "You don't have permission to create {{object}} records. The fields are read-only.",
|
|
234
|
+
noPermissionToEdit: "You don't have permission to edit {{object}} records. The fields are read-only.",
|
|
184
235
|
submitFailed: 'Could not save. Please try again.',
|
|
185
|
-
|
|
236
|
+
uploadInFlight: 'Wait for the upload to finish before saving.',
|
|
237
|
+
// The notice the record form raises when a field's own `visibleWhen` turns
|
|
238
|
+
// it invisible and the form clears the value it held (objectui#8070 names
|
|
239
|
+
// the `6a449fc49` clear). `{{fields}}` is the cleared fields' labels joined
|
|
240
|
+
// with `validation.formInvalidJoiner`. A list after a colon, so no word has
|
|
241
|
+
// to agree with how many fields were cleared.
|
|
242
|
+
clearedOnHide: 'Cleared — no longer applicable given the current values: {{fields}}',
|
|
243
|
+
// The refusal a record form raises at SUBMIT when a field's own
|
|
244
|
+
// `visibleWhen` could not be evaluated (objectui#8069, ADR-0137 D2 as ruled:
|
|
245
|
+
// the client refuses the one rule no server judges). It names the rule and
|
|
246
|
+
// the fields — `{{fields}}` is their labels joined with
|
|
247
|
+
// `validation.formInvalidJoiner` — because the fix is to the metadata, not
|
|
248
|
+
// to anything the person filling the form can type.
|
|
249
|
+
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
250
|
removeItem: 'Remove item',
|
|
187
251
|
fieldRequired: 'This field is required',
|
|
188
252
|
invalidFormat: 'Invalid format',
|
|
@@ -197,6 +261,57 @@ const en = {
|
|
|
197
261
|
// only displace it by authoring a `description`, which makes a VISIBLE
|
|
198
262
|
// subtitle appear on every form — so the fallback has to come from here.
|
|
199
263
|
dialogDescriptionFallback: 'Complete the form fields, then submit or cancel.',
|
|
264
|
+
// The hint under a field the caller may read but not write, shown when the
|
|
265
|
+
// field declares no description of its own (objectui#11071).
|
|
266
|
+
deniedDescription: 'You do not have edit access to this field.',
|
|
267
|
+
// The master-detail form's own chrome (objectui#11071): the collection
|
|
268
|
+
// placeholder while its columns resolve, the document totals stack
|
|
269
|
+
// (`{{rate}}` is the header's tax rate), the row editor's title
|
|
270
|
+
// (`{{title}}` is the collection's authored title, or `lineItem` when it
|
|
271
|
+
// has none; `{{row}}` is the 1-based row number), its Apply button, and the
|
|
272
|
+
// sr-only description of the dialog that hosts the form. The verbs `Add`,
|
|
273
|
+
// `Close` and `Saving…` come from `detail.add`, `common.close` and
|
|
274
|
+
// `detail.saving`.
|
|
275
|
+
masterDetail: {
|
|
276
|
+
loadingColumns: 'Loading columns…',
|
|
277
|
+
subtotal: 'Subtotal',
|
|
278
|
+
tax: 'Tax ({{rate}}%)',
|
|
279
|
+
total: 'Total',
|
|
280
|
+
lineItem: 'Line item',
|
|
281
|
+
rowTitle: '{{title}} — row {{row}}',
|
|
282
|
+
applyRow: 'Apply',
|
|
283
|
+
editorDescription: 'Enter the record and its line items, then save.',
|
|
284
|
+
// A collection's configuration hints (objectui#11160): no `childObject`
|
|
285
|
+
// (the twin of `lineItems.noChildObject`, which names the panel), a
|
|
286
|
+
// child schema that failed to load, and no lookup or master_detail
|
|
287
|
+
// field on the child that references the parent. `{{property}}` is a
|
|
288
|
+
// property name and `{{object}}` / `{{parent}}` are object names; each
|
|
289
|
+
// is rendered as code and never translated. `lookup` and
|
|
290
|
+
// `master_detail` are field type names, so every pack keeps them as
|
|
291
|
+
// written.
|
|
292
|
+
noChildObject: 'This collection has no child object configured: set {{property}} to the object whose rows it lists.',
|
|
293
|
+
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.',
|
|
294
|
+
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.',
|
|
295
|
+
},
|
|
296
|
+
// The record page's `record:line_items` panel (objectui#11131): its
|
|
297
|
+
// title when the author declared none. Its Save / Saving… button reads
|
|
298
|
+
// `common.save` / `detail.saving`. `MasterDetailForm` reads `title` too,
|
|
299
|
+
// for a collection that authors no heading (objectui#11145).
|
|
300
|
+
//
|
|
301
|
+
// The rest is the panel's own states (objectui#11145): no parent record
|
|
302
|
+
// bound yet, rows held for another parent, and the two fallbacks for a
|
|
303
|
+
// failed load or save, shown when the server sent no message of its own.
|
|
304
|
+
// Its loading line reads `common.loading`. `noChildObject` is the config
|
|
305
|
+
// hint for a panel with no `childObject`: `{{property}}` is filled with
|
|
306
|
+
// the property name, rendered as code and never translated.
|
|
307
|
+
lineItems: {
|
|
308
|
+
title: 'Line Items',
|
|
309
|
+
saveRecordFirst: 'Save the record first to add line items.',
|
|
310
|
+
notLoaded: 'This record’s line items have not been loaded.',
|
|
311
|
+
loadFailed: 'Failed to load line items',
|
|
312
|
+
saveFailed: 'Failed to save line items',
|
|
313
|
+
noChildObject: 'This panel has no child object configured: set {{property}} to the object whose rows it lists.',
|
|
314
|
+
},
|
|
200
315
|
keepEditing: 'Keep editing',
|
|
201
316
|
discard: 'Discard',
|
|
202
317
|
conflictTitle: 'Save conflict',
|
|
@@ -214,6 +329,26 @@ const en = {
|
|
|
214
329
|
createSuccess: '{{object}} created successfully',
|
|
215
330
|
updateSuccess: '{{object}} updated successfully',
|
|
216
331
|
deleteSuccess: '{{object}} deleted successfully',
|
|
332
|
+
// plugin-form's own feedback chrome (objectui#11039): the success toast
|
|
333
|
+
// a form raises when the author declared no `successMessage` (`created`
|
|
334
|
+
// after a create, `saved` after an edit), the master-detail form's edit
|
|
335
|
+
// toast when the form has a `title` (`{{title}}` is that title), and the
|
|
336
|
+
// console form page's toast after a submit. An authored message always
|
|
337
|
+
// wins; these are only the defaults. The form's loading line and its
|
|
338
|
+
// thank-you panel read `publicForm.loading` / `publicForm.thankYouTitle` /
|
|
339
|
+
// `publicForm.thankYouMessage`, which say the same thing.
|
|
340
|
+
created: 'Created',
|
|
341
|
+
saved: 'Saved',
|
|
342
|
+
savedNamed: '{{title}} saved',
|
|
343
|
+
submitted: 'Submitted',
|
|
344
|
+
// The heading of the panel a form shows when its object schema or its
|
|
345
|
+
// record could not be loaded; the error's own message follows it.
|
|
346
|
+
errorLoading: 'Error loading form',
|
|
347
|
+
// Rides the success toast when a DECLARED `navigateOnSuccess` produced no
|
|
348
|
+
// destination (objectui#5034): the write succeeded, the declared
|
|
349
|
+
// navigation did not happen. `navigateOnSuccess` is the metadata key's
|
|
350
|
+
// name, so every pack keeps it as written.
|
|
351
|
+
navigateRefused: 'The `navigateOnSuccess` destination declared for this form was refused, so the navigation did not happen.',
|
|
217
352
|
fullscreen: {
|
|
218
353
|
title: 'Edit text',
|
|
219
354
|
description: 'Edit the full text value, then save or cancel your changes.',
|
|
@@ -225,6 +360,8 @@ const en = {
|
|
|
225
360
|
fields: {
|
|
226
361
|
relativeDate: {
|
|
227
362
|
overdue: 'Overdue {{count}}d',
|
|
363
|
+
overdue_one: 'Overdue {{count}}d',
|
|
364
|
+
overdue_other: 'Overdue {{count}}d',
|
|
228
365
|
},
|
|
229
366
|
file: {
|
|
230
367
|
dragDropHere: 'Drag & drop files here',
|
|
@@ -241,6 +378,7 @@ const en = {
|
|
|
241
378
|
remove: 'Remove {{name}}',
|
|
242
379
|
exceedsMaxSize: '"{{name}}" exceeds max size ({{max}} MB)',
|
|
243
380
|
uploadFailed: 'Failed to upload "{{name}}": {{error}}',
|
|
381
|
+
uploadIncomplete: 'Upload of "{{name}}" did not complete: no file id was returned, so nothing was saved',
|
|
244
382
|
},
|
|
245
383
|
image: {
|
|
246
384
|
upload: 'Upload image',
|
|
@@ -285,6 +423,9 @@ const en = {
|
|
|
285
423
|
selectBusinessUnit: 'Select a business unit',
|
|
286
424
|
selectPosition: 'Select a position',
|
|
287
425
|
selectUnitAndSubordinates: 'Select a business unit',
|
|
426
|
+
selectField: 'Select a user field',
|
|
427
|
+
noUserFields: 'No user fields on this object',
|
|
428
|
+
fieldNotUserTyped: '{{name}} — not a user field',
|
|
288
429
|
},
|
|
289
430
|
filterCondition: {
|
|
290
431
|
selectObjectFirst: 'Select an object first.',
|
|
@@ -295,6 +436,83 @@ const en = {
|
|
|
295
436
|
editAsJson: 'Edit as JSON',
|
|
296
437
|
useVisualBuilder: 'Use visual builder',
|
|
297
438
|
},
|
|
439
|
+
// objectui#6755 — a widget's OWN refusal sentence: `ObjectField`'s
|
|
440
|
+
// unparsable JSON draft, and `LocationField`'s format and range refusals
|
|
441
|
+
// (objectui#6716 / #6714). They were string literals in the widgets, so a
|
|
442
|
+
// zh / ja / ar user who mistyped a coordinate or a JSON blob was told why in
|
|
443
|
+
// English inside a form whose every other word was translated.
|
|
444
|
+
//
|
|
445
|
+
// KEYED, where objectui#4028 DROPPED the five address placeholders in the
|
|
446
|
+
// namespace below — and the difference is what that decision's own comment
|
|
447
|
+
// records about them: "The right example is a function of the address's
|
|
448
|
+
// COUNTRY, not the reader's language", and "Each box here already has a
|
|
449
|
+
// visible label naming exactly what it wants". Neither reaches a refusal
|
|
450
|
+
// sentence: nothing else on the screen says why the edit was refused, and
|
|
451
|
+
// what that sentence must say IS a function of the reader's language. What
|
|
452
|
+
// #4028 does establish for both is the COST — ten pack entries per key,
|
|
453
|
+
// bound from then on by `check:i18n-drift` — and the 2026-08-29 maintainer
|
|
454
|
+
// ruling accepted that cost for these three sentences.
|
|
455
|
+
//
|
|
456
|
+
// Values are byte-identical to the literals they replace (`FIELD_DEFAULTS`
|
|
457
|
+
// in `packages/fields/src/widgets/useFieldTranslation.ts` carries the same
|
|
458
|
+
// three), so English and provider-less rendering are unchanged.
|
|
459
|
+
//
|
|
460
|
+
// `{{detail}}` is the SPEC's own complaint about the refused pair.
|
|
461
|
+
// `LocationField` refuses to restate `LocationValueSchema`'s bounds — a
|
|
462
|
+
// hand-copied range is a second contract — so this key translates the frame
|
|
463
|
+
// and interpolates whatever the schema said.
|
|
464
|
+
object: {
|
|
465
|
+
invalidJson: 'Invalid JSON',
|
|
466
|
+
},
|
|
467
|
+
location: {
|
|
468
|
+
refusedFormat: 'Not saved: enter a latitude, longitude pair (example: 30.2741, 120.1551).',
|
|
469
|
+
refusedRange: 'Not saved: {{detail}}',
|
|
470
|
+
latitude: 'latitude',
|
|
471
|
+
longitude: 'longitude',
|
|
472
|
+
refusedResidueOne: 'Not saved: {{name}} "{{text}}" is not a number. Enter plain decimals (example: 30.2741, 120.1551).',
|
|
473
|
+
refusedResidue: 'Not saved: {{name}} "{{text}}" and {{otherName}} "{{otherText}}" are not numbers. Enter plain decimals (example: 30.2741, 120.1551).',
|
|
474
|
+
},
|
|
475
|
+
// objectui#8148 — the FIFTH refusal sentence of objectui#6755's class, and
|
|
476
|
+
// the only SHARED one. The four above are each ONE widget's; this one is
|
|
477
|
+
// produced by `numberBadInput.tsx` for `NumberField`, `CurrencyField`,
|
|
478
|
+
// `PercentField` and both of `GeolocationField`'s boxes. That last is the
|
|
479
|
+
// sharpest case: it sits beside `LocationField`, whose refusals are keyed
|
|
480
|
+
// right above, so two adjacent coordinate widgets refused bad input in two
|
|
481
|
+
// different languages on the same form.
|
|
482
|
+
//
|
|
483
|
+
// ⭐ `{{example}}` is a HOLE, and that is what keeps decimal numerals out
|
|
484
|
+
// of every pack. Five different values reach this one sentence (`1234`,
|
|
485
|
+
// `1234.56`, `12.5`, `30.2741`, `120.1551`), so keying the example per
|
|
486
|
+
// widget would be five keys times ten packs — and each pack would then
|
|
487
|
+
// hold a decimal it could legitimately re-punctuate, where `1234,56` reads
|
|
488
|
+
// as the `latitude, longitude` PAIR `refusedFormat` above asks for. The
|
|
489
|
+
// widget fills the hole in ASCII; no pack spells a digit.
|
|
490
|
+
//
|
|
491
|
+
// The English value is byte-identical to the literal it replaces
|
|
492
|
+
// (`FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
493
|
+
// carries the same one), so English and provider-less rendering are
|
|
494
|
+
// unchanged.
|
|
495
|
+
// objectui#10567 — the editable date-only face's notice for a stored value
|
|
496
|
+
// written on a day that does not exist, the date-only sibling of
|
|
497
|
+
// `dateTime.impossibleDay` below: an `<input type="date">` can only paint
|
|
498
|
+
// such a value blank, so the widget names the stored string beside it.
|
|
499
|
+
// `FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
500
|
+
// carries the same English value for provider-less rendering.
|
|
501
|
+
date: {
|
|
502
|
+
impossibleDay: 'The stored value "{{value}}" is not a real date. Pick a date to replace it.',
|
|
503
|
+
},
|
|
504
|
+
// objectui#10474 — the editable date-time face's notice for a stored value
|
|
505
|
+
// written on a day that does not exist. The `datetime-local` control can
|
|
506
|
+
// only paint such a value blank, so the widget names the stored string
|
|
507
|
+
// beside it; a blank control alone would hide it (objectui#3127).
|
|
508
|
+
// `FIELD_DEFAULTS` in `packages/fields/src/widgets/useFieldTranslation.ts`
|
|
509
|
+
// carries the same English value for provider-less rendering.
|
|
510
|
+
dateTime: {
|
|
511
|
+
impossibleDay: 'The stored value "{{value}}" is not a real date. Pick a date and time to replace it.',
|
|
512
|
+
},
|
|
513
|
+
number: {
|
|
514
|
+
badInput: 'Not saved: the text in this box is not a number. Enter a plain decimal (example: {{example}}).',
|
|
515
|
+
},
|
|
298
516
|
// objectui#3342 — the tags widget's input hint, shown while the tag list
|
|
299
517
|
// is empty. The author-declared `field.placeholder` always wins over this.
|
|
300
518
|
tags: {
|
|
@@ -345,6 +563,26 @@ const en = {
|
|
|
345
563
|
characterCount: 'Character count: {{count}} of {{max}}',
|
|
346
564
|
charactersRemaining: 'Characters remaining: {{count}}',
|
|
347
565
|
},
|
|
566
|
+
// objectui#11131 — the line-items grid's default chrome (`GridField`):
|
|
567
|
+
// its Add button, the read-only grid's empty state, and the list-mode
|
|
568
|
+
// grid's empty state. An authored `add_label` still wins over `addLine`,
|
|
569
|
+
// and it fills the `{{label}}` hole (`detail.add` when none is authored).
|
|
570
|
+
//
|
|
571
|
+
// objectui#11145 — the rest of that chrome: the column chooser's heading,
|
|
572
|
+
// the computed cell's tooltip, and the row actions. Each row action has
|
|
573
|
+
// one key, read by both its `aria-label` and its `title`. The chooser's
|
|
574
|
+
// button reads `table.columns`, the footer `form.masterDetail.total` and
|
|
575
|
+
// the drag handle `view.dragToReorder`.
|
|
576
|
+
grid: {
|
|
577
|
+
addLine: 'Add line',
|
|
578
|
+
noItems: 'No items',
|
|
579
|
+
noItemsAddHint: 'No items yet — click “{{label}}” to begin.',
|
|
580
|
+
optionalColumns: 'Optional columns',
|
|
581
|
+
computed: 'Computed',
|
|
582
|
+
openRow: 'Open row',
|
|
583
|
+
duplicateRow: 'Duplicate row',
|
|
584
|
+
removeRow: 'Remove row',
|
|
585
|
+
},
|
|
348
586
|
},
|
|
349
587
|
table: {
|
|
350
588
|
rowsPerPage: 'Rows per page',
|
|
@@ -373,8 +611,12 @@ const en = {
|
|
|
373
611
|
open: 'Open',
|
|
374
612
|
search: 'Search…',
|
|
375
613
|
modified: '{{count}} row modified',
|
|
614
|
+
modified_one: '{{count}} row modified',
|
|
615
|
+
modified_other: '{{count}} rows modified',
|
|
376
616
|
saveFailed: 'Save failed',
|
|
377
617
|
selected: '{{count}} selected',
|
|
618
|
+
selected_one: '{{count}} selected',
|
|
619
|
+
selected_other: '{{count}} selected',
|
|
378
620
|
edit: 'Edit',
|
|
379
621
|
delete: 'Delete',
|
|
380
622
|
},
|
|
@@ -391,9 +633,13 @@ const en = {
|
|
|
391
633
|
openRecord: 'Open record',
|
|
392
634
|
openMenu: 'Open menu',
|
|
393
635
|
bulkSelected: '{{count}} selected',
|
|
636
|
+
bulkSelected_one: '{{count}} selected',
|
|
637
|
+
bulkSelected_other: '{{count}} selected',
|
|
394
638
|
bulkSelectedAllMatches: '{{count}} selected (all matches)',
|
|
395
639
|
bulkClear: 'Clear',
|
|
396
640
|
bulkAllOnPage: 'All {{count}} on this page are selected.',
|
|
641
|
+
bulkAllOnPage_one: '{{count}} record on this page is selected.',
|
|
642
|
+
bulkAllOnPage_other: 'All {{count}} on this page are selected.',
|
|
397
643
|
bulkSelectAllMatching: 'Select all {{count}} matching',
|
|
398
644
|
bulkAllMatchingSelected: 'All {{count}} matching records are selected.',
|
|
399
645
|
rowHeight: 'Row height: {{mode}}',
|
|
@@ -401,6 +647,14 @@ const en = {
|
|
|
401
647
|
yes: 'Yes',
|
|
402
648
|
no: 'No',
|
|
403
649
|
systemFields: 'System',
|
|
650
|
+
// objectui#10881 — the grouped grid's two refusals: over a data source
|
|
651
|
+
// that cannot answer the group header query, and over rows a host
|
|
652
|
+
// handed in while declaring them one page of more. `queryGroupHeaders`
|
|
653
|
+
// is the member's name and stays untranslated.
|
|
654
|
+
grouping: {
|
|
655
|
+
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.',
|
|
656
|
+
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.',
|
|
657
|
+
},
|
|
404
658
|
// Column-footer aggregate prefixes, keyed by the spec's `ColumnSummary`
|
|
405
659
|
// vocabulary (objectui#4024). The footer already formatted its NUMBER
|
|
406
660
|
// through the locale-aware formatter and then put a hardcoded English
|
|
@@ -446,8 +700,10 @@ const en = {
|
|
|
446
700
|
dragDrop: 'Drag & drop a CSV or Excel file here, or click to browse',
|
|
447
701
|
browseFiles: 'Browse Files',
|
|
448
702
|
downloadTemplate: 'Download template',
|
|
449
|
-
downloadTemplateHint: 'Get
|
|
703
|
+
downloadTemplateHint: 'Get an Excel file of the columns you can import (required fields marked *), with instructions for filling it in.',
|
|
450
704
|
templateFileName: '{{object}}-import-template',
|
|
705
|
+
templateDownloadFailed: 'Could not download the template. Please try again.',
|
|
706
|
+
templateNotPermitted: 'You do not have permission to create records of this object, so its import template is not available.',
|
|
451
707
|
parsing: 'Parsing…',
|
|
452
708
|
pasteHint: 'or paste (Ctrl/⌘+V) rows copied from Excel or Google Sheets',
|
|
453
709
|
legacyXls: 'Legacy .xls files aren\'t supported — please re-save as .xlsx.',
|
|
@@ -473,6 +729,8 @@ const en = {
|
|
|
473
729
|
typeMismatch: 'Looks like {{type}}',
|
|
474
730
|
autoMatched: 'Auto-matched',
|
|
475
731
|
autoMatchedSummary: 'Auto-matched {{count}} column(s) — review and adjust below.',
|
|
732
|
+
autoMatchedSummary_one: 'Auto-matched {{count}} column — review and adjust below.',
|
|
733
|
+
autoMatchedSummary_other: 'Auto-matched {{count}} columns — review and adjust below.',
|
|
476
734
|
confidence: {
|
|
477
735
|
high: 'High confidence',
|
|
478
736
|
medium: 'Medium confidence',
|
|
@@ -491,7 +749,11 @@ const en = {
|
|
|
491
749
|
mapped: 'Mapped',
|
|
492
750
|
skipped: 'Skipped',
|
|
493
751
|
rowsWithErrors: '{{count}} row(s) with errors',
|
|
752
|
+
rowsWithErrors_one: '{{count}} row with errors',
|
|
753
|
+
rowsWithErrors_other: '{{count}} rows with errors',
|
|
494
754
|
rowsCorrected: '{{count}} row(s) corrected',
|
|
755
|
+
rowsCorrected_one: '{{count}} row corrected',
|
|
756
|
+
rowsCorrected_other: '{{count}} rows corrected',
|
|
495
757
|
clickToFix: '— click a highlighted cell to fix it inline.',
|
|
496
758
|
showingRows: 'Showing {{shown}} of {{total}} rows',
|
|
497
759
|
importing: 'Importing… {{progress}}%',
|
|
@@ -502,12 +764,20 @@ const en = {
|
|
|
502
764
|
cancelImport: 'Cancel import',
|
|
503
765
|
importCancelled: 'Import cancelled',
|
|
504
766
|
resultsTruncated: 'Showing the first {{count}} row results (of {{total}}).',
|
|
767
|
+
resultsTruncated_one: 'Showing the first {{count}} row result (of {{total}}).',
|
|
768
|
+
resultsTruncated_other: 'Showing the first {{count}} row results (of {{total}}).',
|
|
505
769
|
importComplete: 'Import Complete',
|
|
506
770
|
imported: '{{count}} imported',
|
|
507
771
|
createdCount: '{{count}} created',
|
|
772
|
+
createdCount_one: '{{count}} created',
|
|
773
|
+
createdCount_other: '{{count}} created',
|
|
508
774
|
updatedCount: '{{count}} updated',
|
|
775
|
+
updatedCount_one: '{{count}} updated',
|
|
776
|
+
updatedCount_other: '{{count}} updated',
|
|
509
777
|
skippedCount: '{{count}} skipped',
|
|
510
778
|
moreErrors: '…and {{count}} more errors',
|
|
779
|
+
moreErrors_one: '…and {{count}} more error',
|
|
780
|
+
moreErrors_other: '…and {{count}} more errors',
|
|
511
781
|
downloadFailed: 'Download failed rows',
|
|
512
782
|
options: 'Import options',
|
|
513
783
|
writeMode: 'When a row matches an existing record',
|
|
@@ -555,6 +825,8 @@ const en = {
|
|
|
555
825
|
historyColResult: 'Result',
|
|
556
826
|
historyColTime: 'When',
|
|
557
827
|
errorCount: '{{count}} errors',
|
|
828
|
+
errorCount_one: '{{count}} error',
|
|
829
|
+
errorCount_other: '{{count}} errors',
|
|
558
830
|
undoImport: 'Undo import',
|
|
559
831
|
undoing: 'Undoing…',
|
|
560
832
|
undoConfirm: 'Undo this import? Records it created will be deleted and records it updated will be restored to their previous values.',
|
|
@@ -571,6 +843,8 @@ const en = {
|
|
|
571
843
|
next: 'Next',
|
|
572
844
|
close: 'Close',
|
|
573
845
|
importNRows: 'Import {{count}} Rows',
|
|
846
|
+
importNRows_one: 'Import {{count}} Row',
|
|
847
|
+
importNRows_other: 'Import {{count}} Rows',
|
|
574
848
|
importingProgress: 'Importing…',
|
|
575
849
|
required: 'Required',
|
|
576
850
|
invalidType: 'Invalid {{type}}',
|
|
@@ -582,9 +856,13 @@ const en = {
|
|
|
582
856
|
},
|
|
583
857
|
bulk: {
|
|
584
858
|
confirmDefault: 'This will apply to {{count}} record(s).',
|
|
859
|
+
confirmDefault_one: 'This will apply to {{count}} record.',
|
|
860
|
+
confirmDefault_other: 'This will apply to {{count}} records.',
|
|
585
861
|
overLimit: 'Selection ({{count}}) exceeds the action limit ({{limit}}). Reduce the selection to proceed.',
|
|
586
862
|
affectedRecords: 'Affected records ({{count}}):',
|
|
587
863
|
skippedIneligible: '{{count}} selected record(s) are not eligible for this action and will be skipped.',
|
|
864
|
+
skippedIneligible_one: '{{count}} selected record is not eligible for this action and will be skipped.',
|
|
865
|
+
skippedIneligible_other: '{{count}} selected records are not eligible for this action and will be skipped.',
|
|
588
866
|
rowFallback: 'Row {{index}}',
|
|
589
867
|
andMore: '\u2026 and {{count}} more',
|
|
590
868
|
processed: '{{count}} / {{total}} processed',
|
|
@@ -602,7 +880,6 @@ const en = {
|
|
|
602
880
|
undo: 'Undo',
|
|
603
881
|
undoing: 'Undoing\u2026',
|
|
604
882
|
done: 'Done',
|
|
605
|
-
selectPlaceholder: 'Select\u2026',
|
|
606
883
|
loading: 'Loading\u2026',
|
|
607
884
|
},
|
|
608
885
|
},
|
|
@@ -611,16 +888,43 @@ const en = {
|
|
|
611
888
|
month: 'Month',
|
|
612
889
|
week: 'Week',
|
|
613
890
|
day: 'Day',
|
|
614
|
-
agenda: 'Agenda',
|
|
615
891
|
allDay: 'All Day',
|
|
616
|
-
noEvents: 'No events',
|
|
617
892
|
newEvent: 'New event',
|
|
618
893
|
moreEvents: '+{{count}} more',
|
|
894
|
+
unscheduled: 'Unscheduled ({{count}})',
|
|
895
|
+
loading: 'Loading calendar…',
|
|
896
|
+
loadError: 'Error: {{message}}',
|
|
897
|
+
configRequired: 'Calendar configuration required. Please specify startDateField, the calendar\'s one required key; the event title resolves without titleField.',
|
|
898
|
+
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.',
|
|
899
|
+
eventDetails: 'Event Details',
|
|
900
|
+
pullToRefresh: 'Pull to refresh',
|
|
901
|
+
refreshing: 'Refreshing…',
|
|
902
|
+
onDate: 'On {{date}}',
|
|
903
|
+
eventTitle: 'Title',
|
|
904
|
+
eventTitlePlaceholder: 'What\'s this event about?',
|
|
905
|
+
creating: 'Creating…',
|
|
906
|
+
titleRequired: 'Title is required',
|
|
907
|
+
a11y: {
|
|
908
|
+
region: 'Calendar',
|
|
909
|
+
grid: 'Calendar grid',
|
|
910
|
+
goToToday: 'Go to today',
|
|
911
|
+
previousPeriod: 'Previous period',
|
|
912
|
+
nextPeriod: 'Next period',
|
|
913
|
+
currentDate: 'Current date: {{date}}',
|
|
914
|
+
dayCell: '{{date}}, {{count}} events',
|
|
915
|
+
dayCell_one: '{{date}}, {{count}} event',
|
|
916
|
+
dayCell_other: '{{date}}, {{count}} events',
|
|
917
|
+
resizeEventEnd: 'Resize event end',
|
|
918
|
+
resizeEventEndHint: 'Drag to change end date',
|
|
919
|
+
resizeStart: 'Resize start',
|
|
920
|
+
resizeEnd: 'Resize end',
|
|
921
|
+
},
|
|
619
922
|
},
|
|
620
923
|
list: {
|
|
621
924
|
loading: 'Loading records…',
|
|
622
925
|
recordCount: '{{count}} records',
|
|
623
|
-
|
|
926
|
+
recordCount_one: '{{count}} record',
|
|
927
|
+
recordCount_other: '{{count}} records',
|
|
624
928
|
addRecord: 'Add record',
|
|
625
929
|
tabs: 'Tabs',
|
|
626
930
|
allRecords: 'All Records',
|
|
@@ -690,7 +994,7 @@ const en = {
|
|
|
690
994
|
hideFieldsTitle: 'Hide Fields',
|
|
691
995
|
dataLimitReached: 'Showing first {{limit}} records. More data may be available.',
|
|
692
996
|
viewSettings: 'View settings',
|
|
693
|
-
viewSettingsHint: 'Grouping, color, density, and visible fields.',
|
|
997
|
+
viewSettingsHint: 'Grouping, color, density, and visible fields. Applies to everyone who uses this view.',
|
|
694
998
|
addGroup: 'Add group field',
|
|
695
999
|
collapsedByDefault: 'Collapsed by default',
|
|
696
1000
|
removeGroup: 'Remove',
|
|
@@ -755,6 +1059,17 @@ const en = {
|
|
|
755
1059
|
},
|
|
756
1060
|
gantt: {
|
|
757
1061
|
rowLabel: 'Items',
|
|
1062
|
+
unusableRange: {
|
|
1063
|
+
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.',
|
|
1064
|
+
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.',
|
|
1065
|
+
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.',
|
|
1066
|
+
},
|
|
1067
|
+
},
|
|
1068
|
+
unsupported: {
|
|
1069
|
+
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.',
|
|
1070
|
+
},
|
|
1071
|
+
unconfigured: {
|
|
1072
|
+
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
1073
|
},
|
|
759
1074
|
},
|
|
760
1075
|
gantt: {
|
|
@@ -800,6 +1115,7 @@ const en = {
|
|
|
800
1115
|
},
|
|
801
1116
|
aria: {
|
|
802
1117
|
taskList: 'Task list',
|
|
1118
|
+
refreshing: 'Refreshing…',
|
|
803
1119
|
},
|
|
804
1120
|
tooltip: {
|
|
805
1121
|
days: 'd',
|
|
@@ -845,13 +1161,19 @@ const en = {
|
|
|
845
1161
|
conflict: {
|
|
846
1162
|
title: 'Schedule conflict',
|
|
847
1163
|
body: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected task(s)?',
|
|
1164
|
+
body_one: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected task?',
|
|
1165
|
+
body_other: 'This move conflicts with dependency constraints. Auto-reschedule {{count}} affected tasks?',
|
|
848
1166
|
confirm: 'Auto-reschedule',
|
|
849
1167
|
cancel: 'Keep as is',
|
|
850
1168
|
},
|
|
851
1169
|
autoScheduleDlg: {
|
|
852
1170
|
title: 'Auto-schedule',
|
|
853
1171
|
body: 'Shift {{count}} task(s) later to satisfy dependency links?',
|
|
1172
|
+
body_one: 'Shift {{count}} task later to satisfy dependency links?',
|
|
1173
|
+
body_other: 'Shift {{count}} tasks later to satisfy dependency links?',
|
|
854
1174
|
skipped: '{{count}} locked task(s) also violate links and were skipped.',
|
|
1175
|
+
skipped_one: '{{count}} locked task also violates links and was skipped.',
|
|
1176
|
+
skipped_other: '{{count}} locked tasks also violate links and were skipped.',
|
|
855
1177
|
confirm: 'Apply',
|
|
856
1178
|
cancel: 'Cancel',
|
|
857
1179
|
none: 'All dependencies satisfied — nothing to reschedule.',
|
|
@@ -908,6 +1230,7 @@ const en = {
|
|
|
908
1230
|
tabActionsFor: 'View actions for {{name}}',
|
|
909
1231
|
readonlyAriaLabel: 'Read-only view',
|
|
910
1232
|
readonlyTooltip: 'System view — defined in code, read-only.',
|
|
1233
|
+
malformedFilter: 'This view’s filter is malformed, so no records are shown: the {{subject}} condition cannot be applied.',
|
|
911
1234
|
},
|
|
912
1235
|
detail: {
|
|
913
1236
|
back: 'Back',
|
|
@@ -924,6 +1247,7 @@ const en = {
|
|
|
924
1247
|
writeStrippedReadonly: 'Read-only, so it did not take effect: {{fields}}',
|
|
925
1248
|
writeStrippedByState: "Not editable in this record's current state, so it did not take effect: {{fields}}",
|
|
926
1249
|
writeStrippedPrimaryKey: "The record's identifier cannot be changed by a save, so it did not take effect: {{fields}}",
|
|
1250
|
+
writeStrippedComputed: 'Calculated by the server from a formula, so the value sent did not take effect: {{fields}}',
|
|
927
1251
|
writeStrippedUnknownReason: 'Not applied by the server: {{fields}}',
|
|
928
1252
|
approvalPendingEditable: 'In approval · editable',
|
|
929
1253
|
approvalPendingTooltip: 'This record has a pending approval request; this step still allows editing',
|
|
@@ -950,6 +1274,8 @@ const en = {
|
|
|
950
1274
|
pathStageLostUpcoming: '{{stage}}, closed lost, not reached',
|
|
951
1275
|
pathStageWonUpcoming: '{{stage}}, goal stage, not reached',
|
|
952
1276
|
linkCopied: 'Link copied to clipboard',
|
|
1277
|
+
commentFailed: 'Your comment was not posted. Nothing was saved — please try again.',
|
|
1278
|
+
reactionFailed: 'Your reaction was not saved. Please try again.',
|
|
953
1279
|
linkCopyFailed: 'Failed to copy link',
|
|
954
1280
|
cancel: 'Cancel',
|
|
955
1281
|
cancelEdit: 'Discard changes',
|
|
@@ -976,7 +1302,8 @@ const en = {
|
|
|
976
1302
|
pageHeaderActions: 'Page header actions',
|
|
977
1303
|
emojiPicker: 'Emoji picker',
|
|
978
1304
|
reactionCount: '{{emoji}} {{count}} reactions',
|
|
979
|
-
|
|
1305
|
+
reactionCount_one: '{{emoji}} {{count}} reaction',
|
|
1306
|
+
reactionCount_other: '{{emoji}} {{count}} reactions',
|
|
980
1307
|
// Record-overlay chrome (objectstack#5506). `recordDetail` is the VISIBLE
|
|
981
1308
|
// heading the overlay falls back to when the host passes no title;
|
|
982
1309
|
// `openAsFullPage` is the icon-only expand button's default accessible
|
|
@@ -1016,7 +1343,6 @@ const en = {
|
|
|
1016
1343
|
viewAll: 'View All',
|
|
1017
1344
|
new: 'New',
|
|
1018
1345
|
add: 'Add',
|
|
1019
|
-
emptyValue: '—',
|
|
1020
1346
|
activity: 'Activity',
|
|
1021
1347
|
history: 'History',
|
|
1022
1348
|
historyEmpty: 'No history yet',
|
|
@@ -1031,6 +1357,7 @@ const en = {
|
|
|
1031
1357
|
sortBy: 'Sort by',
|
|
1032
1358
|
filterPlaceholder: 'Filter…',
|
|
1033
1359
|
highlightFields: 'Key Fields',
|
|
1360
|
+
highlightsLabel: 'Record highlights',
|
|
1034
1361
|
// Comments
|
|
1035
1362
|
comments: 'Comments',
|
|
1036
1363
|
searchComments: 'Search comments…',
|
|
@@ -1042,8 +1369,14 @@ const en = {
|
|
|
1042
1369
|
unpin: 'Unpin',
|
|
1043
1370
|
justNow: 'just now',
|
|
1044
1371
|
minutesAgo: '{{count}}m ago',
|
|
1372
|
+
minutesAgo_one: '{{count}}m ago',
|
|
1373
|
+
minutesAgo_other: '{{count}}m ago',
|
|
1045
1374
|
hoursAgo: '{{count}}h ago',
|
|
1375
|
+
hoursAgo_one: '{{count}}h ago',
|
|
1376
|
+
hoursAgo_other: '{{count}}h ago',
|
|
1046
1377
|
daysAgo: '{{count}}d ago',
|
|
1378
|
+
daysAgo_one: '{{count}}d ago',
|
|
1379
|
+
daysAgo_other: '{{count}}d ago',
|
|
1047
1380
|
// Activity feed actors
|
|
1048
1381
|
systemActor: 'System',
|
|
1049
1382
|
unknownUser: 'Unknown',
|
|
@@ -1057,7 +1390,8 @@ const en = {
|
|
|
1057
1390
|
// Attachments
|
|
1058
1391
|
dropFilesToUpload: 'Drop files here or click to upload',
|
|
1059
1392
|
attachmentCount: '{{count}} attachment',
|
|
1060
|
-
|
|
1393
|
+
attachmentCount_one: '{{count}} attachment',
|
|
1394
|
+
attachmentCount_other: '{{count}} attachments',
|
|
1061
1395
|
removeAttachment: 'Remove attachment',
|
|
1062
1396
|
// Record Attachments panel (enable.files, objectstack#4358)
|
|
1063
1397
|
attachments: 'Attachments',
|
|
@@ -1075,12 +1409,6 @@ const en = {
|
|
|
1075
1409
|
attachmentsLoadFailed: "We couldn't load the attachments for this record.",
|
|
1076
1410
|
attachmentsApiUnavailable: 'The attachments list is not available on this object.',
|
|
1077
1411
|
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
1412
|
// Discussion
|
|
1085
1413
|
discussion: 'Discussion',
|
|
1086
1414
|
showDiscussion: 'Show Discussion ({{count}})',
|
|
@@ -1098,23 +1426,16 @@ const en = {
|
|
|
1098
1426
|
// Subscription
|
|
1099
1427
|
subscribedTooltip: 'Subscribed — click to unsubscribe',
|
|
1100
1428
|
unsubscribedTooltip: 'Subscribe to notifications',
|
|
1101
|
-
//
|
|
1102
|
-
firstRecord: 'First record (Home)',
|
|
1103
|
-
previousRecordKey: 'Previous record (←)',
|
|
1104
|
-
nextRecordKey: 'Next record (→)',
|
|
1105
|
-
lastRecord: 'Last record (End)',
|
|
1429
|
+
// The reference rail's empty related-record list
|
|
1106
1430
|
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.
|
|
1431
|
+
// objectui#3863 — the BASE key; since objectui#11432 every pack also spells out
|
|
1432
|
+
// each CLDR category its language selects, so with a count no pack reaches the
|
|
1433
|
+
// base. In `en` this value is parity ballast — and it must stay byte-identical to
|
|
1434
|
+
// the call site's inline `defaultValue` in `record-reference-rail.tsx`, which
|
|
1435
|
+
// `check:i18n-keys` now judges as class 3.
|
|
1113
1436
|
showEmptyRelated: '+ {{count}} empty',
|
|
1114
1437
|
showEmptyRelated_one: '+ {{count}} empty',
|
|
1115
1438
|
showEmptyRelated_other: '+ {{count}} empty',
|
|
1116
|
-
searchWhileNavigating: 'Search while navigating',
|
|
1117
|
-
searchRecords: 'Search records…',
|
|
1118
1439
|
// Activity timeline
|
|
1119
1440
|
allActivity: 'All Activity',
|
|
1120
1441
|
commentsOnly: 'Comments Only',
|
|
@@ -1122,13 +1443,29 @@ const en = {
|
|
|
1122
1443
|
tasksOnly: 'Tasks Only',
|
|
1123
1444
|
leaveCommentPlaceholder: 'Leave a comment… (Ctrl+Enter to submit)',
|
|
1124
1445
|
noActivity: 'No activity recorded',
|
|
1446
|
+
activityAccessDenied: "You don't have permission to view activity on this record.",
|
|
1447
|
+
commentsAccessDenied: "You don't have permission to view comments on this record.",
|
|
1448
|
+
// objectui#7149 — the rest of `ActivityTimeline`. The four chip labels the
|
|
1449
|
+
// `detail.*` pack did not already name, and the `formatFieldChange`
|
|
1450
|
+
// sentences, which are assembled in code and so need interpolation holes.
|
|
1451
|
+
allFilter: 'All',
|
|
1452
|
+
createsFilter: 'Creates',
|
|
1453
|
+
deletesFilter: 'Deletes',
|
|
1454
|
+
statusChangesFilter: 'Status Changes',
|
|
1455
|
+
activityEmptyValue: '(empty)',
|
|
1456
|
+
activityFieldChanged: 'Changed {{field}} from "{{old}}" to "{{new}}"',
|
|
1457
|
+
activityCreated: 'Created this record',
|
|
1458
|
+
activityDeleted: 'Deleted this record',
|
|
1459
|
+
activityStatusChanged: 'Changed status to "{{value}}"',
|
|
1460
|
+
activityUpdated: 'Updated record',
|
|
1125
1461
|
loadMore: 'Load more',
|
|
1126
1462
|
edited: '(edited)',
|
|
1127
1463
|
via: 'via {{source}}',
|
|
1128
1464
|
viewSource: 'View source',
|
|
1129
1465
|
// Replies
|
|
1130
1466
|
replyCount: '{{count}} reply',
|
|
1131
|
-
|
|
1467
|
+
replyCount_one: '{{count}} reply',
|
|
1468
|
+
replyCount_other: '{{count}} replies',
|
|
1132
1469
|
replyPlaceholder: 'Reply…',
|
|
1133
1470
|
// Aria labels
|
|
1134
1471
|
filterActivity: 'Filter activity',
|
|
@@ -1141,13 +1478,54 @@ const en = {
|
|
|
1141
1478
|
copyPhone: 'Copy phone number',
|
|
1142
1479
|
copyRecordId: 'Copy record ID',
|
|
1143
1480
|
showEmptyFields: 'Show {{count}} empty fields',
|
|
1481
|
+
showEmptyFields_one: 'Show {{count}} empty field',
|
|
1482
|
+
showEmptyFields_other: 'Show {{count}} empty fields',
|
|
1144
1483
|
hideEmptyFields: 'Hide empty fields',
|
|
1145
1484
|
noValue: 'No value',
|
|
1485
|
+
unresolvedReference: 'Unresolved reference: {{value}} was not resolved to a user',
|
|
1486
|
+
unresolvedLookupReference: 'Unresolved reference: {{value}} was not resolved to a record on this screen',
|
|
1487
|
+
// Cell-level COUNT phrases for the `repeater` and file cells
|
|
1488
|
+
// (objectui#8441). Both were written straight into the renderer before this
|
|
1489
|
+
// — `repeater` as a number plus a hardcoded Chinese unit word, which every
|
|
1490
|
+
// reader on every locale saw, and `FileCellRenderer` as an English-only
|
|
1491
|
+
// `count === 1 ? 'file' : 'files'`, which is not plural-safe anywhere else.
|
|
1492
|
+
// One channel, two call sites.
|
|
1493
|
+
//
|
|
1494
|
+
// REAL i18next plural families — the one count shape this repo uses since
|
|
1495
|
+
// objectui#11445 retired the code-selected `xxxCountOne` / `xxxCountPlural`
|
|
1496
|
+
// sibling keys. i18next asks `Intl.PluralRules` for the
|
|
1497
|
+
// ONE suffix a number needs, so each pack carries every category its language
|
|
1498
|
+
// selects (`ru` `_few`/`_many`, `ar` `_zero`/`_two`/`_few`/`_many` —
|
|
1499
|
+
// objectui#11432) plus the base key (objectui#3863).
|
|
1500
|
+
// `all-locales-key-parity.test.ts` owns both rules.
|
|
1501
|
+
repeaterItemCount: '{{count}} items',
|
|
1502
|
+
repeaterItemCount_one: '{{count}} item',
|
|
1503
|
+
repeaterItemCount_other: '{{count}} items',
|
|
1504
|
+
fileCount: '{{count}} files',
|
|
1505
|
+
fileCount_one: '{{count}} file',
|
|
1506
|
+
fileCount_other: '{{count}} files',
|
|
1146
1507
|
},
|
|
1147
1508
|
chart: {
|
|
1148
|
-
noData: 'No chart data available',
|
|
1149
1509
|
loading: 'Loading chart…',
|
|
1510
|
+
refreshing: 'Refreshing…',
|
|
1150
1511
|
nullCategory: '(None)',
|
|
1512
|
+
// The refusal a scatter renders when handed more than one series
|
|
1513
|
+
// (objectui#7194): it binds ONE measure, so a second series was painted at
|
|
1514
|
+
// the first one's y values. One short sentence on purpose — this pack is
|
|
1515
|
+
// eagerly loaded and the `framework` chunk's gzip ceiling has ~0.2 KB of
|
|
1516
|
+
// headroom; the series keys are rendered by the chart as data, after it.
|
|
1517
|
+
scatterOneMeasure: 'A scatter plots one measure. Keep exactly one series:',
|
|
1518
|
+
// The refusal an object-bound chart renders when it declares no category
|
|
1519
|
+
// axis (objectui#8168) — `aggregate.groupBy` / `xAxisKey` / `xAxis.field`
|
|
1520
|
+
// all absent, so `runAggregate` would have grouped on a name nobody wrote.
|
|
1521
|
+
// The twin of `timeline.unconfigured.noDateAxis`. ONE short sentence, for
|
|
1522
|
+
// the same reason `scatterOneMeasure` above is one: the packs ship it ten
|
|
1523
|
+
// times, and the binding names are rendered by the component after it
|
|
1524
|
+
// rather than interpolated, so a rung added to or retired from the
|
|
1525
|
+
// resolver cannot leave this sentence naming a stale vocabulary.
|
|
1526
|
+
unconfigured: {
|
|
1527
|
+
noCategoryAxis: 'Chart category axis required — an object-bound chart will not invent one. Declare one of:',
|
|
1528
|
+
},
|
|
1151
1529
|
},
|
|
1152
1530
|
report: {
|
|
1153
1531
|
total: 'Total',
|
|
@@ -1189,30 +1567,38 @@ const en = {
|
|
|
1189
1567
|
panelTitle: 'Edit report',
|
|
1190
1568
|
},
|
|
1191
1569
|
},
|
|
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
1570
|
designer: {
|
|
1200
1571
|
undo: 'Undo',
|
|
1201
1572
|
redo: 'Redo',
|
|
1202
1573
|
},
|
|
1203
1574
|
dashboard: {
|
|
1204
1575
|
addWidget: 'Add widget',
|
|
1205
|
-
removeWidget: 'Remove widget',
|
|
1206
1576
|
editLayout: 'Edit layout',
|
|
1207
1577
|
saveLayout: 'Save layout',
|
|
1208
1578
|
resetLayout: 'Reset layout',
|
|
1209
1579
|
total: 'Total',
|
|
1210
|
-
noDataAvailable: 'No data available',
|
|
1211
1580
|
noDataSourceFor: 'No data source available for',
|
|
1212
|
-
|
|
1581
|
+
// objectui#7063 — the DEFAULT empty state every dashboard widget renders
|
|
1582
|
+
// when its query SUCCEEDED and returned nothing. It replaced the terse
|
|
1583
|
+
// per-widget `noRows` / `noDataAvailable` fragments at the render site;
|
|
1584
|
+
// objectui#7125 deleted those two keys from all ten packs once nothing
|
|
1585
|
+
// read them. The copy here has to read as a state rather than a failure,
|
|
1586
|
+
// which is why it says the widget loaded. `sourceLabel` carries its own
|
|
1587
|
+
// punctuation so the call site concatenates no separator (see
|
|
1588
|
+
// `WidgetEmptyState`).
|
|
1589
|
+
empty: {
|
|
1590
|
+
title: 'No data yet',
|
|
1591
|
+
message: 'This widget loaded successfully and its query returned no records yet.',
|
|
1592
|
+
sourceLabel: 'Source:',
|
|
1593
|
+
},
|
|
1213
1594
|
loading: 'Loading…',
|
|
1595
|
+
refreshing: 'Refreshing…',
|
|
1596
|
+
refreshAll: 'Refresh All',
|
|
1597
|
+
refreshDashboard: 'Refresh dashboard',
|
|
1214
1598
|
pickMeasures: 'Pick measures (values) for this dataset widget.',
|
|
1215
1599
|
datasetUnsupported: 'This data source does not support dataset queries.',
|
|
1600
|
+
widgetForbiddenTitle: 'You don’t have access',
|
|
1601
|
+
widgetForbiddenMessage: 'You don’t have permission to view the data behind this widget.',
|
|
1216
1602
|
details: 'Details',
|
|
1217
1603
|
exportCsv: 'Export CSV',
|
|
1218
1604
|
openInList: 'Open in list',
|
|
@@ -1359,10 +1745,6 @@ const en = {
|
|
|
1359
1745
|
appDescription: 'Description',
|
|
1360
1746
|
appIcon: 'Icon',
|
|
1361
1747
|
template: 'Template',
|
|
1362
|
-
layout: 'Layout',
|
|
1363
|
-
layoutSidebar: 'Sidebar',
|
|
1364
|
-
layoutHeader: 'Header',
|
|
1365
|
-
layoutEmpty: 'Empty',
|
|
1366
1748
|
selectObjects: 'Select Objects',
|
|
1367
1749
|
searchObjects: 'Search objects…',
|
|
1368
1750
|
selectAll: 'Select All',
|
|
@@ -1371,7 +1753,6 @@ const en = {
|
|
|
1371
1753
|
addGroup: 'Add Group',
|
|
1372
1754
|
addUrl: 'Add URL',
|
|
1373
1755
|
addSeparator: 'Add Separator',
|
|
1374
|
-
noNavItems: 'No navigation items yet.',
|
|
1375
1756
|
logoUrl: 'Logo URL',
|
|
1376
1757
|
primaryColor: 'Primary Color',
|
|
1377
1758
|
faviconUrl: 'Favicon URL',
|
|
@@ -1398,13 +1779,12 @@ const en = {
|
|
|
1398
1779
|
appearance: 'Appearance',
|
|
1399
1780
|
rowHeight: 'Row Height',
|
|
1400
1781
|
livePreview: 'Live Preview',
|
|
1401
|
-
stepBasicDesc: 'Name, title, and
|
|
1782
|
+
stepBasicDesc: 'Name, title, and icon',
|
|
1402
1783
|
stepObjectsDesc: 'Select business objects',
|
|
1403
1784
|
stepNavigationDesc: 'Build navigation tree',
|
|
1404
1785
|
stepBrandingDesc: 'Logo, colors, and favicon',
|
|
1405
1786
|
noObjectsFound: 'No objects found.',
|
|
1406
1787
|
noNavItemsHint: 'No navigation items yet. Select objects in the previous step or add items manually.',
|
|
1407
|
-
separator: 'Separator',
|
|
1408
1788
|
separatorLabel: '— Separator —',
|
|
1409
1789
|
newGroup: 'New Group',
|
|
1410
1790
|
newLink: 'New Link',
|
|
@@ -1438,6 +1818,7 @@ const en = {
|
|
|
1438
1818
|
navTypeSeparator: 'Separator',
|
|
1439
1819
|
navTypeAction: 'Action',
|
|
1440
1820
|
navTypeComponent: 'Component',
|
|
1821
|
+
navTypeDoc: 'Doc',
|
|
1441
1822
|
navEditIcon: 'Edit icon',
|
|
1442
1823
|
navToggleVisible: 'Toggle visibility',
|
|
1443
1824
|
navHidden: 'Hidden',
|
|
@@ -1515,11 +1896,8 @@ const en = {
|
|
|
1515
1896
|
defaultValue: 'Default Value',
|
|
1516
1897
|
placeholder: 'Placeholder',
|
|
1517
1898
|
referenceTo: 'Reference To',
|
|
1518
|
-
formula: 'Formula',
|
|
1519
1899
|
options: 'Options',
|
|
1520
1900
|
addOption: 'Add Option',
|
|
1521
|
-
validationRules: 'Validation Rules',
|
|
1522
|
-
addRule: 'Add Rule',
|
|
1523
1901
|
systemBadge: 'System',
|
|
1524
1902
|
ungrouped: 'General',
|
|
1525
1903
|
deleteConfirmTitle: 'Delete Field?',
|
|
@@ -1538,7 +1916,24 @@ const en = {
|
|
|
1538
1916
|
},
|
|
1539
1917
|
},
|
|
1540
1918
|
console: {
|
|
1919
|
+
// The Studio front door's wordmark (objectui#10043). Its sibling one
|
|
1920
|
+
// route away -- `StudioDesignSurface`'s header Home button -- walks back
|
|
1921
|
+
// to the same place, so both read as the same affordance.
|
|
1922
|
+
studio: {
|
|
1923
|
+
backToHome: 'Back to home',
|
|
1924
|
+
},
|
|
1541
1925
|
saveAdvisoryTitle: 'Saved — the authoring check raised {{count}} advisory finding(s)',
|
|
1926
|
+
saveAdvisoryTitle_one: 'Saved — the authoring check raised {{count}} advisory finding',
|
|
1927
|
+
saveAdvisoryTitle_other: 'Saved — the authoring check raised {{count}} advisory findings',
|
|
1928
|
+
publishAdvisoryTitle: 'Published — the authoring check raised {{count}} advisory finding(s)',
|
|
1929
|
+
publishAdvisoryTitle_one: 'Published — the authoring check raised {{count}} advisory finding',
|
|
1930
|
+
publishAdvisoryTitle_other: 'Published — the authoring check raised {{count}} advisory findings',
|
|
1931
|
+
importMappingsUnavailable: 'Saved import mappings for {{object}} could not be loaded',
|
|
1932
|
+
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.',
|
|
1933
|
+
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.',
|
|
1934
|
+
savedViewsUnavailable: 'Saved views for {{object}} could not be loaded',
|
|
1935
|
+
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.',
|
|
1936
|
+
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
1937
|
title: 'ObjectOS',
|
|
1543
1938
|
initializing: 'Initializing application…',
|
|
1544
1939
|
search: 'Search…',
|
|
@@ -1547,12 +1942,24 @@ const en = {
|
|
|
1547
1942
|
pages: 'Pages',
|
|
1548
1943
|
reports: 'Reports',
|
|
1549
1944
|
system: 'System',
|
|
1945
|
+
// The Setup system page segment after `System` (objectui#10900).
|
|
1946
|
+
marketplace: 'Marketplace',
|
|
1947
|
+
// The console app's own `system/*` pages after `System` (objectui#10969).
|
|
1948
|
+
settings: 'Settings',
|
|
1949
|
+
apps: 'Apps',
|
|
1950
|
+
profile: 'Profile',
|
|
1951
|
+
approvals: 'Approvals',
|
|
1952
|
+
aiApprovals: 'AI Approvals',
|
|
1953
|
+
auditLog: 'Audit Log',
|
|
1550
1954
|
},
|
|
1551
1955
|
nav: {
|
|
1552
1956
|
pinItem: 'Pin {{name}}',
|
|
1553
1957
|
unpinItem: 'Unpin {{name}}',
|
|
1554
1958
|
dragToReorder: 'Drag to reorder',
|
|
1555
1959
|
favorites: 'Favorites',
|
|
1960
|
+
launcherLabel: 'App launcher',
|
|
1961
|
+
menuLabel: 'App navigation',
|
|
1962
|
+
menuEmpty: 'This app has no navigation entries you can open.',
|
|
1556
1963
|
},
|
|
1557
1964
|
settingsHub: {
|
|
1558
1965
|
title: 'Settings',
|
|
@@ -1600,15 +2007,12 @@ const en = {
|
|
|
1600
2007
|
discard: 'Discard',
|
|
1601
2008
|
saveChanges: 'Save changes',
|
|
1602
2009
|
// Save-bar counter. A REAL i18next plural family, not an English-only
|
|
1603
|
-
// `change(s)
|
|
1604
|
-
// elsewhere in this file.
|
|
2010
|
+
// `change(s)`.
|
|
1605
2011
|
//
|
|
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.
|
|
2012
|
+
// i18next asks `Intl.PluralRules` for the one suffix a language needs, so
|
|
2013
|
+
// each pack spells out every category its language selects — `ru` has
|
|
2014
|
+
// four, `ar` six (objectui#11432) — and keeps the base key
|
|
2015
|
+
// (objectui#3863). `all-locales-key-parity.test.ts` owns both rules.
|
|
1612
2016
|
unsavedCount: '{{count}} unsaved changes',
|
|
1613
2017
|
unsavedCount_one: '{{count}} unsaved change',
|
|
1614
2018
|
unsavedCount_other: '{{count}} unsaved changes',
|
|
@@ -1709,9 +2113,24 @@ const en = {
|
|
|
1709
2113
|
statusFull: 'Limit reached',
|
|
1710
2114
|
resetsDaily: 'Resets tonight',
|
|
1711
2115
|
resetsMonthly: 'Resets next cycle',
|
|
2116
|
+
// `resetKind: 'weekly'` (free plan's rolling 7-day window, cloud PR
|
|
2117
|
+
// #1852): "N days" (or "N hours" inside the final day). A REAL
|
|
2118
|
+
// i18next plural family — see the `unsavedCount` note above — so the
|
|
2119
|
+
// BASE key carries no suffix and must stay in every pack's lookup
|
|
2120
|
+
// chain (`all-locales-key-parity.test.ts`'s base-key rule).
|
|
2121
|
+
resetsWeeklyDays: 'Resets in {{count}} days',
|
|
2122
|
+
resetsWeeklyDays_one: 'Resets in {{count}} day',
|
|
2123
|
+
resetsWeeklyDays_other: 'Resets in {{count}} days',
|
|
2124
|
+
resetsWeeklyHours: 'Resets in {{count}} hours',
|
|
2125
|
+
resetsWeeklyHours_one: 'Resets in {{count}} hour',
|
|
2126
|
+
resetsWeeklyHours_other: 'Resets in {{count}} hours',
|
|
1712
2127
|
ctaUpgrade: 'Upgrade to keep going',
|
|
1713
2128
|
ctaTopUp: 'Add credits to continue',
|
|
1714
2129
|
ariaLabel: 'AI usage: {{status}}',
|
|
2130
|
+
// objectui#8524 — heading over the pool's read-only split (`breakdown`:
|
|
2131
|
+
// app-building vs data Q&A) in the popover. The rows reuse `meterBuild` /
|
|
2132
|
+
// `meterAsk`; each is a share of the ONE pool, never a second budget.
|
|
2133
|
+
breakdownTitle: 'Used so far',
|
|
1715
2134
|
},
|
|
1716
2135
|
workspaceTitle: 'AI Workspace',
|
|
1717
2136
|
workspaceSubtitle: 'Ask, inspect, and resume conversations',
|
|
@@ -1721,6 +2140,38 @@ const en = {
|
|
|
1721
2140
|
share: 'Share',
|
|
1722
2141
|
shareTitle: 'Share this conversation',
|
|
1723
2142
|
shareDisabledTitle: 'Start chatting to enable sharing',
|
|
2143
|
+
// The build conversation's Build Doctor button (its accessible name,
|
|
2144
|
+
// and its tooltip enabled / before the first message) and the drawer
|
|
2145
|
+
// title it opens (objectui#10900).
|
|
2146
|
+
buildDoctor: 'Build Doctor',
|
|
2147
|
+
buildDoctorTitle: 'Build Doctor — what actually landed?',
|
|
2148
|
+
buildDoctorDisabledTitle: 'Send a message first',
|
|
2149
|
+
// The Build Doctor drawer's body (objectui#10969): its description, the
|
|
2150
|
+
// loading and not-found states, the summary line, the verdict, and each
|
|
2151
|
+
// section's title and hint. What the report itself carries (tool, artifact
|
|
2152
|
+
// and status names, timeline text) is data and stays verbatim.
|
|
2153
|
+
buildDoctorDrawer: {
|
|
2154
|
+
description: 'What the agent claimed vs what is actually live. Read-only diagnostic.',
|
|
2155
|
+
reconciling: 'Reconciling…',
|
|
2156
|
+
notAvailable: 'Not available — the conversation was not found or you are not authorized.',
|
|
2157
|
+
untitled: '(untitled)',
|
|
2158
|
+
summary: '{{turns}} turn(s) · {{messages}} msgs · {{tokens}} tok · {{seconds}}s LLM',
|
|
2159
|
+
allLive: 'All {{count}} attempted change(s) are live — nothing evaporated.',
|
|
2160
|
+
discrepancies: "{{count}} discrepancy(ies) — what the chat said doesn't match what's live.",
|
|
2161
|
+
orphanedTitle: 'Proposed but never applied',
|
|
2162
|
+
orphanedHint: 'A confirm card the agent proposed but no later turn applied — the change silently evaporated.',
|
|
2163
|
+
missingTitle: 'Claimed but missing',
|
|
2164
|
+
missingHint: "A tool result said it was applied, but the artifact isn't live in sys_metadata.",
|
|
2165
|
+
toolErrorsTitle: 'Tool errors',
|
|
2166
|
+
toolErrorsHint: 'Tool calls that returned an error during the build.',
|
|
2167
|
+
verifyTitle: 'Build check (verify_build)',
|
|
2168
|
+
yourApp: 'Your app:',
|
|
2169
|
+
noIssues: '0 issues',
|
|
2170
|
+
issueCount: '{{count}} issue(s)',
|
|
2171
|
+
platformNoise: '{{count}} platform sys_* finding(s) hidden',
|
|
2172
|
+
pendingActions: 'Pending actions',
|
|
2173
|
+
timeline: 'Timeline ({{count}})',
|
|
2174
|
+
},
|
|
1724
2175
|
newChat: 'New',
|
|
1725
2176
|
searchChats: 'Search chats…',
|
|
1726
2177
|
noChatsYet: 'No chats yet',
|
|
@@ -1747,10 +2198,33 @@ const en = {
|
|
|
1747
2198
|
emptyDescription: 'Ask anything — the assistant has access to your current app context.',
|
|
1748
2199
|
switchAssistant: 'Switch assistant',
|
|
1749
2200
|
chooseAgent: 'Choose assistant…',
|
|
2201
|
+
// objectui#8329 — the maker's empty-state prose, and the FIRST sentence a
|
|
2202
|
+
// new user reads on the build surface (it sits above the start chips).
|
|
2203
|
+
// Same ADR-0112 v1 boundary the chips answer to (cloud#1984 /
|
|
2204
|
+
// objectui#7709 for the starters, cloud#2022 for the model's own closing
|
|
2205
|
+
// suggestions): these two descriptions are the product PROMISING, so they
|
|
2206
|
+
// may only name what v1 BUILDS — objects, fields, views, pages,
|
|
2207
|
+
// dashboards, sample data, apps and navigation. `build.description` used
|
|
2208
|
+
// to offer "an app or workflow … objects, screens and automations" and
|
|
2209
|
+
// `editApp.description` "… view or automation"; v1 has no flows, actions
|
|
2210
|
+
// or schedules, so a user who took either at its word was refused
|
|
2211
|
+
// outright — the worst possible answer to the first line on the page.
|
|
2212
|
+
//
|
|
2213
|
+
// NOT the same thing as the platform's manual automation surfaces, which
|
|
2214
|
+
// are real and stay as they are: `home.build.subtitle` (that card opens
|
|
2215
|
+
// Studio, which does author flows), `engine.studio.landing.description`,
|
|
2216
|
+
// `dataImport.optRunAutomations`, `packagedAutomation.*` and the
|
|
2217
|
+
// marketplace `automation` category. The boundary is v1 AI AUTHORING, not
|
|
2218
|
+
// the word "automation".
|
|
2219
|
+
//
|
|
2220
|
+
// REVERT both sentences when ADR-0112 v2 re-adds flows and actions — same
|
|
2221
|
+
// line of the version roadmap as the chips. Every pack's wording is
|
|
2222
|
+
// guarded, in its own script, by
|
|
2223
|
+
// `packages/i18n/src/__tests__/makerEmptyState-v1-scope-8329.test.ts`.
|
|
1750
2224
|
empty: {
|
|
1751
2225
|
build: {
|
|
1752
2226
|
title: 'Build with AI',
|
|
1753
|
-
description: 'Describe an app
|
|
2227
|
+
description: 'Describe an app in plain language — I draft the objects, screens and sample data, then you review and publish.',
|
|
1754
2228
|
},
|
|
1755
2229
|
ask: {
|
|
1756
2230
|
title: 'Ask your data',
|
|
@@ -1759,7 +2233,7 @@ const en = {
|
|
|
1759
2233
|
editApp: {
|
|
1760
2234
|
title: 'Editing “{{app}}”',
|
|
1761
2235
|
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
|
|
2236
|
+
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
2237
|
},
|
|
1764
2238
|
},
|
|
1765
2239
|
clearConversation: 'Clear',
|
|
@@ -1843,23 +2317,41 @@ const en = {
|
|
|
1843
2317
|
recentRecords: 'List the 5 most recently created records.',
|
|
1844
2318
|
recordCounts: 'Count records for each object.',
|
|
1845
2319
|
},
|
|
2320
|
+
// cloud#1984 — these five chips are the maker's own recommendations, so
|
|
2321
|
+
// they may only ask for what ADR-0112 v1 BUILDS: objects, fields, views
|
|
2322
|
+
// (grid/kanban/calendar/gallery), pages, dashboards and sample data. No
|
|
2323
|
+
// wording that promises autonomous behaviour (alert / remind / notify /
|
|
2324
|
+
// automate / status workflow) — v1 has no flows, actions or schedules, and
|
|
2325
|
+
// the model silently degrades such a request into a board or a filtered
|
|
2326
|
+
// view, so the chip would promise an alert and deliver a page. REVERT to
|
|
2327
|
+
// the automation wording when ADR-0112 v2 re-adds flows and actions.
|
|
1846
2328
|
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
|
|
2329
|
+
buildCrm: 'Build a sales CRM — customers, contacts, and deals with a stage field, plus a dashboard that totals deal value by stage.',
|
|
2330
|
+
buildApp: 'Create a project tracker — projects, tasks with owners and due dates, a board grouped by status, and a calendar of due dates.',
|
|
2331
|
+
buildFlow: 'Design a support desk — tickets with priority and status fields, a board grouped by status, and links to customers.',
|
|
2332
|
+
buildInventory: 'Build an inventory app — products, stock levels, suppliers, and a view that filters the items below their reorder point.',
|
|
2333
|
+
buildRecruiting: 'Make an applicant tracker — candidates, open roles, an interview-stage field, and a board grouped by stage.',
|
|
1852
2334
|
},
|
|
1853
2335
|
generic: {
|
|
1854
2336
|
help: 'What can you help me with?',
|
|
1855
2337
|
availableObjects: 'List the available data objects.',
|
|
1856
2338
|
recentActivity: 'Summarize my recent activity.',
|
|
1857
2339
|
},
|
|
2340
|
+
// objectui#7709 — the edit-mode starters, shown when the maker is bound
|
|
2341
|
+
// to an EXISTING app (`?package=`). Same rule as the five above: they
|
|
2342
|
+
// may only ask for what ADR-0112 v1 BUILDS. The fourth chip used to be
|
|
2343
|
+
// `addAutomation` ("an approval, a status flow, or a notification") and
|
|
2344
|
+
// every capability it named is refused by v1 (cloud#1956 / PR #1970), so
|
|
2345
|
+
// it now asks for sample data — `seed` IS on v1's whitelist, and having
|
|
2346
|
+
// no data is what an existing app most often lacks. REVERT: when
|
|
2347
|
+
// ADR-0112 v2 re-adds flows and actions, THIS chip's automation wording
|
|
2348
|
+
// comes back as `addAutomation`; the retired string is pinned for every
|
|
2349
|
+
// pack in `packages/i18n/src/__tests__/makerEditChips-v1-scope-7709.test.ts`.
|
|
1858
2350
|
editApp: {
|
|
1859
2351
|
addField: 'Add a field to one of the objects.',
|
|
1860
2352
|
addObject: 'Add a new object and relate it to an existing one.',
|
|
1861
2353
|
addDashboard: 'Add a dashboard for the key metrics.',
|
|
1862
|
-
|
|
2354
|
+
addSampleData: 'Fill the existing objects with realistic sample records so I can demo the app.',
|
|
1863
2355
|
},
|
|
1864
2356
|
},
|
|
1865
2357
|
// objectui#3546 slice four — the AI console surfaces: the /ai chat page's app switcher,
|
|
@@ -1914,6 +2406,29 @@ const en = {
|
|
|
1914
2406
|
older: 'Older',
|
|
1915
2407
|
},
|
|
1916
2408
|
},
|
|
2409
|
+
// objectui#9954 — the environment admin's read-rate report (cloud#2333).
|
|
2410
|
+
// Two anomalous cases, two sets of words: an ABSENT `readsPerWrite` means the
|
|
2411
|
+
// environment wrote nothing at all, so the ratio is unbounded — the most
|
|
2412
|
+
// severe reading, and never a missing number. `{{threshold}}` always comes
|
|
2413
|
+
// from the wire; this repo holds no copy of the line. Report only — the copy
|
|
2414
|
+
// states that nothing is limited or blocked, and must keep doing so.
|
|
2415
|
+
readRate: {
|
|
2416
|
+
ratioTitle: 'Unusual read volume in this environment',
|
|
2417
|
+
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.',
|
|
2418
|
+
noWritesTitle: 'Reads with no writes at all in this environment',
|
|
2419
|
+
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.',
|
|
2420
|
+
},
|
|
2421
|
+
// objectui#10439 — the environment admin's storage-capacity banner (cloud#2135).
|
|
2422
|
+
// Raised by the tenant runtime's own verdict on `/api/v1/usage/storage`: `warn`
|
|
2423
|
+
// (80% and up) or `blocked` (uploads and bulk imports refused). `{{used}}` and
|
|
2424
|
+
// `{{limit}}` are that response's `usedMb` / `limitMb`, already formatted.
|
|
2425
|
+
storageUsage: {
|
|
2426
|
+
warningTitle: 'Storage is filling up',
|
|
2427
|
+
warning: '{{used}} MB of {{limit}} MB used. Uploads and imports pause once storage is full.',
|
|
2428
|
+
blockedTitle: 'Storage is full: uploads and imports are paused',
|
|
2429
|
+
blocked: '{{used}} MB of {{limit}} MB used. Existing data is untouched, and reading, exporting and editing single records still work.',
|
|
2430
|
+
upgrade: 'Upgrade to continue',
|
|
2431
|
+
},
|
|
1917
2432
|
errors: {
|
|
1918
2433
|
somethingWentWrong: 'Something went wrong',
|
|
1919
2434
|
unexpectedError: 'An unexpected error occurred while rendering this view.',
|
|
@@ -1971,6 +2486,7 @@ const en = {
|
|
|
1971
2486
|
// (rename / pin / set-as-default / configure), so the copy has to cover
|
|
1972
2487
|
// any change to a built-in view rather than name one operation.
|
|
1973
2488
|
cannotEditMetaView: 'This view is built in and defined in code — it cannot be changed.',
|
|
2489
|
+
viewConfigPermissionDenied: 'View settings apply to everyone who uses this view, so changing them requires the Manage Metadata permission. Ask an administrator to make this change.',
|
|
1974
2490
|
cannotDeleteMetaView: 'This view is built in and defined in code — it cannot be deleted.',
|
|
1975
2491
|
expandToPage: 'Open as full page',
|
|
1976
2492
|
allRecords: 'All Records',
|
|
@@ -1978,14 +2494,17 @@ const en = {
|
|
|
1978
2494
|
import: 'Import',
|
|
1979
2495
|
importTitle: 'Import from CSV',
|
|
1980
2496
|
importedToast: 'Imported {{count}} row(s).',
|
|
2497
|
+
importedToast_one: 'Imported {{count}} row.',
|
|
2498
|
+
importedToast_other: 'Imported {{count}} rows.',
|
|
1981
2499
|
importedWithSkipped: 'Imported {{ok}} row(s); skipped {{skipped}}.',
|
|
1982
2500
|
configureView: 'Configure View',
|
|
1983
|
-
toolbar: 'Toolbar',
|
|
1984
2501
|
toolbarEnabledCount: '{{count}} of {{total}} enabled',
|
|
1985
2502
|
searchFields: 'Search fields…',
|
|
1986
2503
|
title: 'Title',
|
|
1987
2504
|
viewType: 'View type',
|
|
1988
2505
|
recordCount: '{{count}} records',
|
|
2506
|
+
recordCount_one: '{{count}} record',
|
|
2507
|
+
recordCount_other: '{{count}} records',
|
|
1989
2508
|
save: 'Save',
|
|
1990
2509
|
discard: 'Discard',
|
|
1991
2510
|
createView: 'Create View',
|
|
@@ -1996,6 +2515,8 @@ const en = {
|
|
|
1996
2515
|
deleteViewTitle: 'Delete view',
|
|
1997
2516
|
deleteViewConfirm: 'Are you sure you want to delete the view "{{name}}"? This cannot be undone.',
|
|
1998
2517
|
bulkDeleteConfirm: 'Delete {{count}} selected records? This cannot be undone.',
|
|
2518
|
+
bulkDeleteConfirm_one: 'Delete {{count}} selected record? This cannot be undone.',
|
|
2519
|
+
bulkDeleteConfirm_other: 'Delete {{count}} selected records? This cannot be undone.',
|
|
1999
2520
|
duplicateViewName: 'A view with this name already exists.',
|
|
2000
2521
|
viewTypeGrid: 'Grid',
|
|
2001
2522
|
viewTypeGridDesc: 'A spreadsheet-style table of records.',
|
|
@@ -2048,11 +2569,14 @@ const en = {
|
|
|
2048
2569
|
chartTypePie: 'Pie chart',
|
|
2049
2570
|
chartTypeArea: 'Area chart',
|
|
2050
2571
|
chartTypeScatter: 'Scatter chart',
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2572
|
+
dataset: 'Dataset',
|
|
2573
|
+
datasetHelp: 'The chart reads its numbers from this dataset of the object.',
|
|
2574
|
+
chartMeasure: 'Measure',
|
|
2575
|
+
chartMeasureHelp: 'The dataset measure plotted on the value axis.',
|
|
2576
|
+
chartDimension: 'Dimension',
|
|
2577
|
+
chartDimensionHelp: 'The dataset dimension the values are grouped by (optional).',
|
|
2578
|
+
viewTypeUnavailableDataset: 'This object exposes no dataset to chart.',
|
|
2579
|
+
noDatasetMeasure: 'This dataset declares no measure to chart.',
|
|
2056
2580
|
endDateField: 'End date field',
|
|
2057
2581
|
ufTabs: 'Tabs',
|
|
2058
2582
|
ufAddField: '+ Add filter field…',
|
|
@@ -2078,7 +2602,7 @@ const en = {
|
|
|
2078
2602
|
signingIn: 'Signing you in…',
|
|
2079
2603
|
ssoHandoff: 'Continue to {{target}}',
|
|
2080
2604
|
// Phone/OTP sign-in labels. `LoginForm` interpolates `{seconds}` with a
|
|
2081
|
-
// literal `.replace()` of its own (
|
|
2605
|
+
// literal `.replace('{seconds}', …)` of its own (in `LoginForm`),
|
|
2082
2606
|
// so those SINGLE braces must survive translation — i18next never sees
|
|
2083
2607
|
// them.
|
|
2084
2608
|
emailOrPhoneLabel: 'Email or phone number',
|
|
@@ -2091,6 +2615,13 @@ const en = {
|
|
|
2091
2615
|
resendOtpCountdownText: 'Resend in {seconds}s',
|
|
2092
2616
|
usePhoneOtpText: 'Sign in with verification code',
|
|
2093
2617
|
usePasswordSignInText: 'Sign in with password instead',
|
|
2618
|
+
// The social provider buttons and the divider under them
|
|
2619
|
+
// (`SocialSignInButtons`, fed through `LoginForm`'s labels).
|
|
2620
|
+
// `{provider}` is the component's own single-brace hole, filled by a
|
|
2621
|
+
// literal `.replace()` with the provider's name as the server reports
|
|
2622
|
+
// it — the same convention as `{seconds}` above (objectui#10900).
|
|
2623
|
+
socialButton: 'Continue with {provider}',
|
|
2624
|
+
orText: 'or continue with email',
|
|
2094
2625
|
devAdminHint: {
|
|
2095
2626
|
title: 'Development instance',
|
|
2096
2627
|
body: 'Sign in with the seeded dev admin:',
|
|
@@ -2119,8 +2650,13 @@ const en = {
|
|
|
2119
2650
|
submittingButton: 'Creating account…',
|
|
2120
2651
|
hasAccountText: 'Already have an account?',
|
|
2121
2652
|
signInText: 'Sign in',
|
|
2653
|
+
// Same pair as `auth.login.socialButton` / `orText`, for sign-up.
|
|
2654
|
+
socialButton: 'Sign up with {provider}',
|
|
2655
|
+
orText: 'or continue with email',
|
|
2122
2656
|
errors: {
|
|
2123
2657
|
userExists: 'An account with this email already exists. Try signing in instead.',
|
|
2658
|
+
selfRegistrationClosed: 'Self-registration is not open on this environment. Ask an administrator for an invitation.',
|
|
2659
|
+
emailDomainNotAllowed: "This email's domain is not allowed to register here. Use your organization email, or ask an administrator for an invitation.",
|
|
2124
2660
|
},
|
|
2125
2661
|
verifyInbox: {
|
|
2126
2662
|
title: 'Check your inbox',
|
|
@@ -2349,6 +2885,15 @@ const en = {
|
|
|
2349
2885
|
role: 'Role',
|
|
2350
2886
|
save: 'Save Changes',
|
|
2351
2887
|
},
|
|
2888
|
+
language: {
|
|
2889
|
+
title: 'Language',
|
|
2890
|
+
description: 'The language used for notifications and messages sent to you. The interface language is chosen separately, from the globe menu.',
|
|
2891
|
+
label: 'Preferred language',
|
|
2892
|
+
systemDefault: 'Use the deployment default',
|
|
2893
|
+
save: 'Save',
|
|
2894
|
+
saved: 'Language preference updated.',
|
|
2895
|
+
readOnly: 'Your administrator manages the language for your account.',
|
|
2896
|
+
},
|
|
2352
2897
|
password: {
|
|
2353
2898
|
changeTitle: 'Change Password',
|
|
2354
2899
|
setTitle: 'Set Local Password',
|
|
@@ -2380,7 +2925,6 @@ const en = {
|
|
|
2380
2925
|
label: 'Workspaces',
|
|
2381
2926
|
default: 'My Workspace',
|
|
2382
2927
|
switch: 'Switch workspace',
|
|
2383
|
-
create: 'Create workspace',
|
|
2384
2928
|
createTitle: 'Create a workspace',
|
|
2385
2929
|
createDescription: 'A workspace is a shared space for your team to collaborate.',
|
|
2386
2930
|
createButton: 'Create workspace',
|
|
@@ -2403,7 +2947,6 @@ const en = {
|
|
|
2403
2947
|
},
|
|
2404
2948
|
sidebar: {
|
|
2405
2949
|
settings: 'Settings',
|
|
2406
|
-
help: 'Help',
|
|
2407
2950
|
helpTooltip: 'Help & Documentation',
|
|
2408
2951
|
activityFeed: 'Activity feed',
|
|
2409
2952
|
notifications: 'Notifications',
|
|
@@ -2443,7 +2986,6 @@ const en = {
|
|
|
2443
2986
|
},
|
|
2444
2987
|
home: {
|
|
2445
2988
|
title: 'Home',
|
|
2446
|
-
subtitle: 'Your workspace dashboard',
|
|
2447
2989
|
nav: 'Home',
|
|
2448
2990
|
allApps: 'All Applications',
|
|
2449
2991
|
yourApps: 'Your apps',
|
|
@@ -2470,14 +3012,7 @@ const en = {
|
|
|
2470
3012
|
marketplaceDisabled: 'This runtime has no app marketplace configured, so there are no templates to install here.',
|
|
2471
3013
|
},
|
|
2472
3014
|
open: 'Open',
|
|
2473
|
-
stats: {
|
|
2474
|
-
apps: 'Applications',
|
|
2475
|
-
starred: 'Starred',
|
|
2476
|
-
recent: 'Recent items',
|
|
2477
|
-
},
|
|
2478
3015
|
loading: 'Loading workspace…',
|
|
2479
|
-
recent: 'Recent',
|
|
2480
|
-
starred: 'Starred',
|
|
2481
3016
|
welcome: 'Build your business system with AI',
|
|
2482
3017
|
welcomeDescription: 'Describe your business in one sentence — AI generates the objects, screens, APIs and agent tools. Or start from scratch.',
|
|
2483
3018
|
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.',
|
|
@@ -2494,6 +3029,8 @@ const en = {
|
|
|
2494
3029
|
},
|
|
2495
3030
|
pendingDrafts: {
|
|
2496
3031
|
message: 'You have {{count}} unpublished change(s) — publish to make them live.',
|
|
3032
|
+
message_one: 'You have {{count}} unpublished change — publish to make it live.',
|
|
3033
|
+
message_other: 'You have {{count}} unpublished changes — publish to make them live.',
|
|
2497
3034
|
cta: 'Publish',
|
|
2498
3035
|
publishing: 'Publishing…',
|
|
2499
3036
|
published: 'Published! Your changes are live.',
|
|
@@ -2513,8 +3050,6 @@ const en = {
|
|
|
2513
3050
|
browseMarketplace: 'Browse App Marketplace',
|
|
2514
3051
|
quickActions: {
|
|
2515
3052
|
title: 'Quick Actions',
|
|
2516
|
-
createApp: 'Create App',
|
|
2517
|
-
createAppDesc: 'Start with a new application',
|
|
2518
3053
|
manageObjects: 'Manage Objects',
|
|
2519
3054
|
manageObjectsDesc: 'Configure data models',
|
|
2520
3055
|
systemSettings: 'System Settings',
|
|
@@ -2526,7 +3061,9 @@ const en = {
|
|
|
2526
3061
|
object: 'Object',
|
|
2527
3062
|
dashboard: 'Dashboard',
|
|
2528
3063
|
page: 'Page',
|
|
3064
|
+
report: 'Report',
|
|
2529
3065
|
record: 'Record',
|
|
3066
|
+
metadata: 'Metadata',
|
|
2530
3067
|
},
|
|
2531
3068
|
},
|
|
2532
3069
|
starredApps: {
|
|
@@ -2563,7 +3100,6 @@ const en = {
|
|
|
2563
3100
|
organizations: 'Organizations',
|
|
2564
3101
|
roles: 'Roles',
|
|
2565
3102
|
configuration: 'Configuration',
|
|
2566
|
-
createApp: 'Create App',
|
|
2567
3103
|
administration: 'Administration',
|
|
2568
3104
|
datasources: 'Datasources',
|
|
2569
3105
|
documentation: 'Documentation',
|
|
@@ -2578,6 +3114,7 @@ const en = {
|
|
|
2578
3114
|
typeUpdate: 'Update',
|
|
2579
3115
|
typeDelete: 'Delete',
|
|
2580
3116
|
typeComment: 'Comment',
|
|
3117
|
+
typeSystem: 'System',
|
|
2581
3118
|
relativeJustNow: 'just now',
|
|
2582
3119
|
relativeSecondsAgo: '{{count}}s ago',
|
|
2583
3120
|
relativeMinutesAgo: '{{count}}m ago',
|
|
@@ -2598,8 +3135,11 @@ const en = {
|
|
|
2598
3135
|
placeholder: 'Search objects, dashboards, pages, reports…',
|
|
2599
3136
|
inputAriaLabel: 'Search objects, dashboards, pages, reports',
|
|
2600
3137
|
resultsCount: '{{count}} result for "{{query}}"',
|
|
2601
|
-
|
|
3138
|
+
resultsCount_one: '{{count}} result for "{{query}}"',
|
|
3139
|
+
resultsCount_other: '{{count}} results for "{{query}}"',
|
|
2602
3140
|
itemsAvailable: '{{count}} items available',
|
|
3141
|
+
itemsAvailable_one: '{{count}} item available',
|
|
3142
|
+
itemsAvailable_other: '{{count}} items available',
|
|
2603
3143
|
noResults: 'No results found',
|
|
2604
3144
|
noResultsHint: 'Try adjusting your search terms',
|
|
2605
3145
|
typeObjects: 'Objects',
|
|
@@ -2626,7 +3166,11 @@ const en = {
|
|
|
2626
3166
|
noAppsConfigured: 'No Apps Configured',
|
|
2627
3167
|
noAppsConfiguredDescription: 'No applications have been registered. Create your first app or visit System Settings to configure your environment.',
|
|
2628
3168
|
appNotAvailable: 'App not available',
|
|
2629
|
-
appNotAvailableDescription: 'This app is not available
|
|
3169
|
+
appNotAvailableDescription: 'This app is not available — try again in a moment.',
|
|
3170
|
+
appNotFound: "This app can't be opened",
|
|
3171
|
+
appNotFoundDescription: 'The server did not return this app for your account.',
|
|
3172
|
+
appUnreachable: "Couldn't reach the server",
|
|
3173
|
+
appUnreachableDescription: 'This app could not be checked. Try again in a moment.',
|
|
2630
3174
|
appAccessDenied: "You don't have access to this app",
|
|
2631
3175
|
appAccessDeniedDescription: 'This app exists, but your account is not authorized to open it. Ask an administrator to grant you access.',
|
|
2632
3176
|
appAccessDeniedHome: 'Back to home',
|
|
@@ -2670,11 +3214,15 @@ const en = {
|
|
|
2670
3214
|
detailNone: 'No differences detected — the draft matches the published version.',
|
|
2671
3215
|
detailChangedKeys: 'Also changed:',
|
|
2672
3216
|
confirmNote: 'Publishing releases all {{count}} pending drafts of this package atomically.',
|
|
3217
|
+
confirmNote_one: 'Publishing releases the {{count}} pending draft of this package atomically.',
|
|
3218
|
+
confirmNote_other: 'Publishing releases all {{count}} pending drafts of this package atomically.',
|
|
2673
3219
|
publishConfirm: 'Publish all',
|
|
2674
|
-
// [
|
|
3220
|
+
// [`7a90afdf9`] Pre-publish security-posture findings, shown next to
|
|
2675
3221
|
// the confirm button so a refusal the door would issue is read BEFORE
|
|
2676
3222
|
// the click rather than as a toast after the batch rolled back.
|
|
2677
3223
|
securityBlockTitle: 'Publishing will be refused — {{count}} item(s) need a decision first',
|
|
3224
|
+
securityBlockTitle_one: 'Publishing will be refused — {{count}} item needs a decision first',
|
|
3225
|
+
securityBlockTitle_other: 'Publishing will be refused — {{count}} items need a decision first',
|
|
2678
3226
|
securityBlockWhere: 'Fix it on the object under Settings → Record sharing, then publish again.',
|
|
2679
3227
|
},
|
|
2680
3228
|
// ADR-0045 — the materialized-but-unlisted app banner
|
|
@@ -2702,7 +3250,19 @@ const en = {
|
|
|
2702
3250
|
revertLabel: 'Reverted a change',
|
|
2703
3251
|
applyLabel: 'Build change',
|
|
2704
3252
|
revert: 'revert',
|
|
2705
|
-
|
|
3253
|
+
// objectui#9266 — the count is INSIDE the value, one interpolated string
|
|
3254
|
+
// per pack. It used to be a bare unit word that `CommitTimeline` glued to
|
|
3255
|
+
// a number it rendered itself, which no pack could make agree: `de` read
|
|
3256
|
+
// `1 Elemente`, `ru` `1 элементов`, `ar` `1 عناصر`. Each pack now states
|
|
3257
|
+
// the count in its own count-INVARIANT idiom — `en` keeps the `(s)` marker
|
|
3258
|
+
// it already dodged with, `zh`/`ja`/`ko` keep the inline counter their
|
|
3259
|
+
// grammar needs no plural for, and `de`/`fr`/`es`/`pt`/`ru`/`ar` use the
|
|
3260
|
+
// label-colon form (`Elemente: 3`, `Элементов: 3`), which is the shape
|
|
3261
|
+
// `fields.textarea.charactersRemaining` already uses for this exact
|
|
3262
|
+
// reason. It needs no family: every pack's form reads at any number,
|
|
3263
|
+
// which is why `count-families-11445.test.ts` names it on its
|
|
3264
|
+
// count-neutral list rather than holding it to the family rule.
|
|
3265
|
+
items: '{{count}} item(s)',
|
|
2706
3266
|
revertAction: 'Revert',
|
|
2707
3267
|
reverted: 'Reverted — the change has been undone.',
|
|
2708
3268
|
revertFailed: 'Revert failed',
|
|
@@ -2718,22 +3278,17 @@ const en = {
|
|
|
2718
3278
|
requiredError: '{{label}} is required',
|
|
2719
3279
|
lookupPlaceholder: 'Record id for {{label}}',
|
|
2720
3280
|
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.',
|
|
3281
|
+
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.',
|
|
3282
|
+
carryOverHint: 'Carried over unchanged (read-only)',
|
|
2721
3283
|
cancel: 'Cancel',
|
|
2722
3284
|
confirm: 'Confirm',
|
|
2723
3285
|
uploading: 'Uploading…',
|
|
2724
|
-
defaultActionTitle: 'Action',
|
|
2725
|
-
ok: 'OK',
|
|
2726
3286
|
},
|
|
2727
3287
|
actionConfirm: {
|
|
2728
3288
|
title: 'Confirm Action',
|
|
2729
3289
|
confirm: 'Continue',
|
|
2730
3290
|
cancel: 'Cancel',
|
|
2731
3291
|
},
|
|
2732
|
-
rowAction: {
|
|
2733
|
-
openMenu: 'Open menu',
|
|
2734
|
-
edit: 'Edit',
|
|
2735
|
-
delete: 'Delete',
|
|
2736
|
-
},
|
|
2737
3292
|
navigationSync: {
|
|
2738
3293
|
addedPage: 'Navigation updated: added page "{{name}}"',
|
|
2739
3294
|
addedDashboard: 'Navigation updated: added dashboard "{{name}}"',
|
|
@@ -2755,6 +3310,8 @@ const en = {
|
|
|
2755
3310
|
'Deleting resets it to the shipped baseline and discards your environment customization. Continue?',
|
|
2756
3311
|
resetPackageSetSuccess: 'Permission set reset to its shipped baseline',
|
|
2757
3312
|
bulkDeleteSuccess: 'Deleted {{count}} {{label}} records',
|
|
3313
|
+
bulkDeleteSuccess_one: 'Deleted {{count}} {{label}} record',
|
|
3314
|
+
bulkDeleteSuccess_other: 'Deleted {{count}} {{label}} records',
|
|
2758
3315
|
bulkDeletePartial: '{{succeeded}} deleted, {{failed}} failed',
|
|
2759
3316
|
},
|
|
2760
3317
|
objectViewActions: {
|
|
@@ -2766,15 +3323,6 @@ const en = {
|
|
|
2766
3323
|
exportFailed: 'Export failed: {{message}}',
|
|
2767
3324
|
forecastSoon: 'Forecast view coming soon',
|
|
2768
3325
|
},
|
|
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
3326
|
user: {
|
|
2779
3327
|
profile: 'Profile',
|
|
2780
3328
|
settings: 'Settings',
|
|
@@ -2953,18 +3501,35 @@ const en = {
|
|
|
2953
3501
|
viewAll: 'View all notifications',
|
|
2954
3502
|
groupCount: '{{count}} notifications',
|
|
2955
3503
|
groupUnread: '{{count}} unread',
|
|
3504
|
+
groupUnread_one: '{{count}} unread',
|
|
3505
|
+
groupUnread_other: '{{count}} unread',
|
|
2956
3506
|
groupMarkRead: 'Mark read',
|
|
2957
3507
|
groupMarkReadTitle: 'Mark all of this type read',
|
|
2958
3508
|
approvalsPending: '{{count}} pending approvals',
|
|
3509
|
+
approvalsPending_one: '{{count}} pending approval',
|
|
3510
|
+
approvalsPending_other: '{{count}} pending approvals',
|
|
2959
3511
|
viewApprovals: 'View approvals',
|
|
2960
3512
|
noPendingApprovals: 'No pending approvals',
|
|
2961
3513
|
openApprovalsInbox: 'Open Approvals Inbox',
|
|
2962
|
-
// Bell-badge breakdown (#7233): the badge sums unread notification topics
|
|
3514
|
+
// Bell-badge breakdown (objectstack-ai/objectstack#7233): the badge sums unread notification topics
|
|
2963
3515
|
// and pending approvals, then clamps at "9+". These three spell the sum
|
|
2964
3516
|
// out inside the popover so the number is explainable.
|
|
2965
3517
|
badgeTotal: '{{total}} total',
|
|
2966
3518
|
badgeNotifications: '{{unread}} notifications',
|
|
2967
3519
|
badgeApprovals: '{{approvals}} pending approvals',
|
|
3520
|
+
// objectui#7011 — the arrival announcement (toast / desktop notification)
|
|
3521
|
+
// and the two switches that govern it.
|
|
3522
|
+
arrivalMany: '{{count}} new messages',
|
|
3523
|
+
arrivalMany_one: '{{count}} new message',
|
|
3524
|
+
arrivalMany_other: '{{count}} new messages',
|
|
3525
|
+
arrivalRepeats: '{{count}} new messages on this topic',
|
|
3526
|
+
arrivalRepeats_one: '{{count}} new message on this topic',
|
|
3527
|
+
arrivalRepeats_other: '{{count}} new messages on this topic',
|
|
3528
|
+
arrivalOpen: 'View',
|
|
3529
|
+
toastEnabled: 'In-app alerts',
|
|
3530
|
+
desktopEnabled: 'Desktop notifications',
|
|
3531
|
+
desktopBlocked: 'Blocked. Allow notifications for this site in your browser settings.',
|
|
3532
|
+
desktopUnsupported: 'This browser does not support desktop notifications.',
|
|
2968
3533
|
},
|
|
2969
3534
|
publicForm: {
|
|
2970
3535
|
submit: 'Submit',
|
|
@@ -2975,12 +3540,20 @@ const en = {
|
|
|
2975
3540
|
thankYouTitle: 'Thank you!',
|
|
2976
3541
|
thankYouMessage: 'Your submission has been received successfully.',
|
|
2977
3542
|
redirecting: 'Redirecting in {{seconds}} seconds…',
|
|
3543
|
+
// The console form page's line for a submit whose declared redirect is
|
|
3544
|
+
// pending (objectui#11071). `redirecting` above is the embeddable form's
|
|
3545
|
+
// countdown and carries a `{{seconds}}` hole this page has no value for.
|
|
3546
|
+
redirectPending: 'Redirecting…',
|
|
2978
3547
|
unavailableTitle: 'Form unavailable',
|
|
2979
3548
|
unavailableDescription: 'No public form is available at this URL. Make sure the underlying view has anonymous sharing enabled and matches this slug.',
|
|
2980
3549
|
tryDemo: 'Try the demo',
|
|
2981
3550
|
retry: 'Retry',
|
|
2982
3551
|
loading: 'Loading form…',
|
|
2983
3552
|
requiredHint: '* Required field',
|
|
3553
|
+
// The console form page's client-side refusal when required rows are empty
|
|
3554
|
+
// (objectui#11071). `{{fields}}` is the empty rows' labels joined with a
|
|
3555
|
+
// comma; the colon, its spacing and the order are the pack's.
|
|
3556
|
+
requiredFields: 'Required: {{fields}}',
|
|
2984
3557
|
consentLabelDefault: 'I agree to the privacy policy and consent to my data being processed for this request.',
|
|
2985
3558
|
consentLink: 'Privacy policy',
|
|
2986
3559
|
consentRequired: 'Please accept the privacy policy to continue.',
|
|
@@ -3031,6 +3604,8 @@ const en = {
|
|
|
3031
3604
|
noImportableFields: 'That object has no importable fields.',
|
|
3032
3605
|
schemaReadFailed: 'Could not read the object schema.',
|
|
3033
3606
|
imported: 'Imported {{count}} row(s) into {{object}}.',
|
|
3607
|
+
imported_one: 'Imported {{count}} row into {{object}}.',
|
|
3608
|
+
imported_other: 'Imported {{count}} rows into {{object}}.',
|
|
3034
3609
|
importFrom: 'Import the real rows from',
|
|
3035
3610
|
into: 'into',
|
|
3036
3611
|
opening: 'Opening…',
|
|
@@ -3044,6 +3619,88 @@ const en = {
|
|
|
3044
3619
|
openProduction: 'Open Production',
|
|
3045
3620
|
manageEnvironments: 'Manage environments',
|
|
3046
3621
|
},
|
|
3622
|
+
// `cloud:plan-status` — the Cloud pricing page's current-plan marker (objectui#10919).
|
|
3623
|
+
cloudPlanStatus: {
|
|
3624
|
+
current: 'Current plan',
|
|
3625
|
+
},
|
|
3626
|
+
// `@object-ui/plugin-ai` — the `nl-query`, `ai-form-assist` and
|
|
3627
|
+
// `ai-recommendations` components (objectui#10232). The two count labels are
|
|
3628
|
+
// i18next count families (objectui#11445): the component passes `count` and
|
|
3629
|
+
// each pack carries every CLDR category its language selects.
|
|
3630
|
+
ai: {
|
|
3631
|
+
nlQuery: {
|
|
3632
|
+
placeholder: 'Ask a question about your data…',
|
|
3633
|
+
ask: 'Ask',
|
|
3634
|
+
results: 'Results',
|
|
3635
|
+
match: '{{percent}} match',
|
|
3636
|
+
simulatedSummary: 'Results for: {{query}}',
|
|
3637
|
+
noResults: 'No matching records found',
|
|
3638
|
+
recentQueries: 'Recent Queries',
|
|
3639
|
+
},
|
|
3640
|
+
formAssist: {
|
|
3641
|
+
title: 'AI Suggestions',
|
|
3642
|
+
suggestionCount: '{{count}} suggestions',
|
|
3643
|
+
suggestionCount_one: '{{count}} suggestion',
|
|
3644
|
+
suggestionCount_other: '{{count}} suggestions',
|
|
3645
|
+
applyAll: 'Apply All',
|
|
3646
|
+
confidence: '{{percent}} confidence',
|
|
3647
|
+
appliedCount: '{{count}} suggestions applied',
|
|
3648
|
+
appliedCount_one: '{{count}} suggestion applied',
|
|
3649
|
+
appliedCount_other: '{{count}} suggestions applied',
|
|
3650
|
+
},
|
|
3651
|
+
recommendations: {
|
|
3652
|
+
title: 'Recommendations',
|
|
3653
|
+
generating: 'Generating recommendations…',
|
|
3654
|
+
empty: 'No recommendations available',
|
|
3655
|
+
},
|
|
3656
|
+
},
|
|
3657
|
+
// The AI HITL approval inbox (`@object-ui/plugin-chatbot`'s
|
|
3658
|
+
// `AiPendingActionsInbox`) — objectui#7173. Its four relative-time phrases
|
|
3659
|
+
// are NOT here: it borrows `detail.justNow` / `minutesAgo` / `hoursAgo` /
|
|
3660
|
+
// `daysAgo`, already translated in all ten packs, the way `ObjectGrid` and
|
|
3661
|
+
// `ObjectKanban` borrow `detail.recordDetail`. Distinct from
|
|
3662
|
+
// `approvalsInbox` above, which is the human approval-PROCESS inbox:
|
|
3663
|
+
// different surface, different feature, so no rows are shared with it.
|
|
3664
|
+
aiApprovals: {
|
|
3665
|
+
title: 'AI Approvals',
|
|
3666
|
+
description: 'Actions an AI agent proposed that need a human review before execution.',
|
|
3667
|
+
tabPending: 'Pending',
|
|
3668
|
+
tabDecided: 'Decided',
|
|
3669
|
+
tabAll: 'All',
|
|
3670
|
+
statusPending: 'Pending',
|
|
3671
|
+
statusApproved: 'Approved',
|
|
3672
|
+
statusExecuted: 'Executed',
|
|
3673
|
+
statusFailed: 'Failed',
|
|
3674
|
+
statusRejected: 'Rejected',
|
|
3675
|
+
colTool: 'Tool',
|
|
3676
|
+
colAction: 'Action',
|
|
3677
|
+
colObject: 'Object',
|
|
3678
|
+
colStatus: 'Status',
|
|
3679
|
+
colProposed: 'Proposed',
|
|
3680
|
+
colDecision: 'Decision',
|
|
3681
|
+
emptyTitle: 'No actions waiting',
|
|
3682
|
+
emptyDescription: 'When the AI proposes a sensitive action it will appear here for review.',
|
|
3683
|
+
view: 'View',
|
|
3684
|
+
approve: 'Approve',
|
|
3685
|
+
reject: 'Reject',
|
|
3686
|
+
working: 'Working…',
|
|
3687
|
+
approveAndExecute: 'Approve & Execute',
|
|
3688
|
+
outcomeApprove: 'Approve for {{id}}: {{message}}',
|
|
3689
|
+
outcomeReject: 'Reject for {{id}}: {{message}}',
|
|
3690
|
+
outcomeExecuteFailed: 'Action failed during execution',
|
|
3691
|
+
drawerFallbackTitle: 'Pending action',
|
|
3692
|
+
drawerSubtitle: 'Tool {{tool}} on {{object}}',
|
|
3693
|
+
fieldProposedBy: 'Proposed by',
|
|
3694
|
+
fieldDecidedBy: 'Decided by',
|
|
3695
|
+
fieldConversation: 'Conversation',
|
|
3696
|
+
fieldToolInput: 'Tool input',
|
|
3697
|
+
fieldResult: 'Result',
|
|
3698
|
+
fieldError: 'Error',
|
|
3699
|
+
fieldRejectionReason: 'Rejection reason',
|
|
3700
|
+
rejectTitle: 'Reject this action?',
|
|
3701
|
+
rejectBody: 'The reason is shown back to the AI so it can adjust its next response.',
|
|
3702
|
+
rejectPlaceholder: "Optional reason (e.g. 'Wrong record id — please confirm with the user first.')",
|
|
3703
|
+
},
|
|
3047
3704
|
aiModelStatus: {
|
|
3048
3705
|
summary: 'Build / Ask uses {{conversational}} ({{conversationalSource}}); structured uses {{structured}} ({{structuredSource}}).',
|
|
3049
3706
|
summaryRouting: 'Routing policy: free plans → {{free}}, paid plans → {{paid}}.',
|
|
@@ -3061,6 +3718,118 @@ const en = {
|
|
|
3061
3718
|
sourceInherits: 'same as build/ask',
|
|
3062
3719
|
sourcePinned: 'pinned by {{source}}',
|
|
3063
3720
|
},
|
|
3721
|
+
// objectui#7254 — the AI copilot's tool cards. Three families, all of them
|
|
3722
|
+
// English-only until this landed while every other string on the same screen
|
|
3723
|
+
// was translated:
|
|
3724
|
+
//
|
|
3725
|
+
// `tool.*` — one entry per PLATFORM-PROVIDED tool name
|
|
3726
|
+
// (@objectstack/spec `PLATFORM_TOOLS_BY_PACKAGE`, the
|
|
3727
|
+
// closed registry those runtimes are conformance-tested
|
|
3728
|
+
// against). `humanizeToolName` looks each up as
|
|
3729
|
+
// `chatbot.tool.<tool_name>` and falls back to its English
|
|
3730
|
+
// title-caser for a custom / third-party tool, so a name
|
|
3731
|
+
// missing here is degraded, never broken. The `en` values
|
|
3732
|
+
// are deliberately EQUAL to what that title-caser produces:
|
|
3733
|
+
// adding the key must not silently reword the English UI.
|
|
3734
|
+
// `toolState.*` — the card-header badge + activity-chip vocabulary. ONE
|
|
3735
|
+
// set for both surfaces (they used to carry separate
|
|
3736
|
+
// tables and disagreed on casing).
|
|
3737
|
+
// `build.*` — the apply_blueprint BUILD PANEL's own copy (objectui#7388).
|
|
3738
|
+
// Everything else on that panel is fed by the host as an
|
|
3739
|
+
// already-translated prop; these strings were literals in
|
|
3740
|
+
// the component, so they stayed English in every language.
|
|
3741
|
+
// `building`/`built` interpolate `appFallback` when the
|
|
3742
|
+
// build has no app label, so each pack must keep BOTH
|
|
3743
|
+
// frames in the one case/gender that noun phrase is in.
|
|
3744
|
+
// `plan.*` — the "N objects · N views · N dashboards" strip. Plural
|
|
3745
|
+
// FAMILIES: one slot per CLDR category the pack's language
|
|
3746
|
+
// selects (objectui#11432), plus the base key for a call
|
|
3747
|
+
// made without a count. `all-locales-key-parity.test.ts`
|
|
3748
|
+
// derives the required slots from `Intl.PluralRules`.
|
|
3749
|
+
//
|
|
3750
|
+
// objectui#7481 — five `tool.*` entries are NEWER than the registry above:
|
|
3751
|
+
// `get_authoring_rules` (cloud#1837), `load_tools`, `open_record`, `test_flow`
|
|
3752
|
+
// and `toggle_flow` are registered by cloud `service-ai-studio` but the pinned
|
|
3753
|
+
// `@objectstack/spec` snapshot does not list them yet. They are kept here on
|
|
3754
|
+
// purpose: a step label the user reads must not wait on a pin bump. When the
|
|
3755
|
+
// pin advances, `chatbotToolLabels-locale-parity-7481` starts checking them
|
|
3756
|
+
// against the registry instead of against its own hand-held list.
|
|
3757
|
+
chatbot: {
|
|
3758
|
+
tool: {
|
|
3759
|
+
aggregate_data: 'Aggregate data',
|
|
3760
|
+
get_record: 'Get record',
|
|
3761
|
+
query_data: 'Query data',
|
|
3762
|
+
query_records: 'Query records',
|
|
3763
|
+
search_knowledge: 'Search knowledge',
|
|
3764
|
+
visualize_data: 'Visualize data',
|
|
3765
|
+
add_field: 'Add field',
|
|
3766
|
+
apply_blueprint: 'Apply blueprint',
|
|
3767
|
+
apply_edit: 'Apply edit',
|
|
3768
|
+
create_metadata: 'Create metadata',
|
|
3769
|
+
create_object: 'Create object',
|
|
3770
|
+
create_package: 'Create package',
|
|
3771
|
+
create_seed: 'Create seed',
|
|
3772
|
+
delete_field: 'Delete field',
|
|
3773
|
+
describe_metadata: 'Describe metadata',
|
|
3774
|
+
describe_object: 'Describe object',
|
|
3775
|
+
get_active_package: 'Get active package',
|
|
3776
|
+
get_authoring_rules: 'Get authoring rules',
|
|
3777
|
+
get_metadata_schema: 'Get metadata schema',
|
|
3778
|
+
get_package: 'Get package',
|
|
3779
|
+
list_metadata: 'List metadata',
|
|
3780
|
+
list_objects: 'List objects',
|
|
3781
|
+
list_packages: 'List packages',
|
|
3782
|
+
load_tools: 'Load tools',
|
|
3783
|
+
modify_field: 'Modify field',
|
|
3784
|
+
open_record: 'Open record',
|
|
3785
|
+
propose_blueprint: 'Propose blueprint',
|
|
3786
|
+
set_active_package: 'Set active package',
|
|
3787
|
+
suggest_builder: 'Suggest builder',
|
|
3788
|
+
test_flow: 'Test flow',
|
|
3789
|
+
todo_write: 'Todo write',
|
|
3790
|
+
toggle_flow: 'Toggle flow',
|
|
3791
|
+
update_metadata: 'Update metadata',
|
|
3792
|
+
validate_expression: 'Validate expression',
|
|
3793
|
+
verify_build: 'Verify build',
|
|
3794
|
+
},
|
|
3795
|
+
toolState: {
|
|
3796
|
+
agentActivity: 'Agent activity',
|
|
3797
|
+
pending: 'Pending',
|
|
3798
|
+
running: 'Running',
|
|
3799
|
+
awaitingApproval: 'Awaiting approval',
|
|
3800
|
+
responded: 'Responded',
|
|
3801
|
+
completed: 'Completed',
|
|
3802
|
+
error: 'Error',
|
|
3803
|
+
denied: 'Denied',
|
|
3804
|
+
failed: 'Failed',
|
|
3805
|
+
},
|
|
3806
|
+
plan: {
|
|
3807
|
+
countObjects: '{{count}} objects',
|
|
3808
|
+
countObjects_one: '{{count}} object',
|
|
3809
|
+
countObjects_other: '{{count}} objects',
|
|
3810
|
+
countViews: '{{count}} views',
|
|
3811
|
+
countViews_one: '{{count}} view',
|
|
3812
|
+
countViews_other: '{{count}} views',
|
|
3813
|
+
countDashboards: '{{count}} dashboards',
|
|
3814
|
+
countDashboards_one: '{{count}} dashboard',
|
|
3815
|
+
countDashboards_other: '{{count}} dashboards',
|
|
3816
|
+
countSeedData: 'sample data',
|
|
3817
|
+
},
|
|
3818
|
+
build: {
|
|
3819
|
+
building: 'Building {{app}}…',
|
|
3820
|
+
built: 'Built {{app}}',
|
|
3821
|
+
appFallback: 'your app',
|
|
3822
|
+
addingSampleData: 'adding sample data',
|
|
3823
|
+
group: {
|
|
3824
|
+
object: 'Objects',
|
|
3825
|
+
view: 'Views',
|
|
3826
|
+
dashboard: 'Dashboards',
|
|
3827
|
+
app: 'App',
|
|
3828
|
+
seed: 'Sample data',
|
|
3829
|
+
},
|
|
3830
|
+
moreArtifacts: '+{{n}} more',
|
|
3831
|
+
},
|
|
3832
|
+
},
|
|
3064
3833
|
chatbotError: {
|
|
3065
3834
|
title: 'Response failed',
|
|
3066
3835
|
fallbackDetail: 'Something went wrong. Please try again.',
|
|
@@ -3133,7 +3902,7 @@ const en = {
|
|
|
3133
3902
|
marketplace: {
|
|
3134
3903
|
title: 'App Marketplace',
|
|
3135
3904
|
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
|
|
3905
|
+
searchPlaceholder: 'Search apps by name or app ID…',
|
|
3137
3906
|
searchAria: 'Search marketplace apps',
|
|
3138
3907
|
installed: 'Installed',
|
|
3139
3908
|
installedCount: 'Installed ({{count}})',
|
|
@@ -3181,10 +3950,15 @@ const en = {
|
|
|
3181
3950
|
purgeSampleData: 'Purge sample data',
|
|
3182
3951
|
purgeConfirm: 'Delete all sample records seeded by this package? User-added records will NOT be touched.',
|
|
3183
3952
|
purgeSuccess: 'Removed {{count}} sample record(s).',
|
|
3953
|
+
purgeSuccess_one: 'Removed {{count}} sample record.',
|
|
3954
|
+
purgeSuccess_other: 'Removed {{count}} sample records.',
|
|
3184
3955
|
purgeNoData: 'No sample records found to purge.',
|
|
3185
3956
|
reseedQueued: 'Sample data will be re-seeded on next environment access.',
|
|
3186
3957
|
reseedLocalSuccess: 'Re-seeded sample data: {{inserted}} inserted, {{updated}} updated.',
|
|
3187
3958
|
reseedPartialErrors: '({{count}} record(s) failed to write)',
|
|
3959
|
+
reseedPartialErrors_one: '({{count}} record failed to write)',
|
|
3960
|
+
reseedPartialErrors_other: '({{count}} records failed to write)',
|
|
3961
|
+
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
3962
|
updateAvailable: 'Update available',
|
|
3189
3963
|
},
|
|
3190
3964
|
action: {
|
|
@@ -3237,7 +4011,8 @@ const en = {
|
|
|
3237
4011
|
reviewed: 'Reviewed & approved',
|
|
3238
4012
|
unreviewed: 'Not yet reviewed',
|
|
3239
4013
|
signed: 'Signed',
|
|
3240
|
-
grantsIntro: '
|
|
4014
|
+
grantsIntro: 'This package requests:',
|
|
4015
|
+
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
4016
|
services: 'Platform services',
|
|
3242
4017
|
hooks: 'Lifecycle hooks',
|
|
3243
4018
|
network: 'Network access',
|
|
@@ -3288,30 +4063,19 @@ const en = {
|
|
|
3288
4063
|
storage: 'Storage',
|
|
3289
4064
|
other: 'Other',
|
|
3290
4065
|
},
|
|
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
4066
|
relativeTime: {
|
|
3300
4067
|
today: 'today',
|
|
3301
4068
|
daysAgo: '{{count}}d ago',
|
|
3302
4069
|
monthsAgo: '{{count}}mo ago',
|
|
4070
|
+
monthsAgo_one: '{{count}}mo ago',
|
|
4071
|
+
monthsAgo_other: '{{count}}mo ago',
|
|
3303
4072
|
yearsAgo: '{{count}}y ago',
|
|
4073
|
+
yearsAgo_one: '{{count}}y ago',
|
|
4074
|
+
yearsAgo_other: '{{count}}y ago',
|
|
3304
4075
|
},
|
|
3305
4076
|
},
|
|
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
4077
|
approvalsInbox: {
|
|
4078
|
+
recordUnresolvable: 'This record cannot be opened',
|
|
3315
4079
|
loadMore: 'Load more',
|
|
3316
4080
|
loadingMore: 'Loading…',
|
|
3317
4081
|
loadedOf: 'Loaded {{loaded}} of {{total}}',
|
|
@@ -3330,6 +4094,8 @@ const en = {
|
|
|
3330
4094
|
requestInfoSent: 'Sent back to the requester for more information',
|
|
3331
4095
|
remindBtn: 'Send reminder',
|
|
3332
4096
|
remindSuccess: 'Reminder sent to {{count}} approver(s)',
|
|
4097
|
+
remindSuccess_one: 'Reminder sent to {{count}} approver',
|
|
4098
|
+
remindSuccess_other: 'Reminder sent to {{count}} approvers',
|
|
3333
4099
|
remindThrottled: 'A reminder was sent recently — try again later.',
|
|
3334
4100
|
replyPlaceholder: 'Reply on this request…',
|
|
3335
4101
|
slaRemaining: 'SLA {{dur}} left',
|
|
@@ -3346,6 +4112,8 @@ const en = {
|
|
|
3346
4112
|
progressApprovals: 'Approvals — {{got}} of {{need}}',
|
|
3347
4113
|
progressGroups: 'Sign-off progress — {{got}} of {{need}} groups',
|
|
3348
4114
|
progressEligible: '{{count}} eligible approver(s)',
|
|
4115
|
+
progressEligible_one: '{{count}} eligible approver',
|
|
4116
|
+
progressEligible_other: '{{count}} eligible approvers',
|
|
3349
4117
|
progressBar: 'Decision progress',
|
|
3350
4118
|
declaredActions: 'Actions',
|
|
3351
4119
|
attachmentChip: 'Attachment',
|
|
@@ -3377,6 +4145,8 @@ const en = {
|
|
|
3377
4145
|
filterCount: '{{shown}} of {{total}}',
|
|
3378
4146
|
selected: 'selected',
|
|
3379
4147
|
actionableCount: '({{count}} actionable)',
|
|
4148
|
+
actionableCount_one: '({{count}} actionable)',
|
|
4149
|
+
actionableCount_other: '({{count}} actionable)',
|
|
3380
4150
|
selectAll: 'Select all',
|
|
3381
4151
|
selectRow: 'Select request',
|
|
3382
4152
|
colRequest: 'Request',
|
|
@@ -3450,11 +4220,19 @@ const en = {
|
|
|
3450
4220
|
approveN: 'Approve {{count}}',
|
|
3451
4221
|
rejectN: 'Reject {{count}}',
|
|
3452
4222
|
bulkApproveTitle: 'Approve {{count}} requests?',
|
|
4223
|
+
bulkApproveTitle_one: 'Approve {{count}} request?',
|
|
4224
|
+
bulkApproveTitle_other: 'Approve {{count}} requests?',
|
|
3453
4225
|
bulkApproveBody: 'Each request is approved with your identity and its flow continues down the approve branch.',
|
|
3454
4226
|
bulkRejectTitle: 'Reject {{count}} requests?',
|
|
4227
|
+
bulkRejectTitle_one: 'Reject {{count}} request?',
|
|
4228
|
+
bulkRejectTitle_other: 'Reject {{count}} requests?',
|
|
3455
4229
|
bulkRejectBody: 'This rejects the selected requests and notifies their submitters.',
|
|
3456
4230
|
bulkApproved: 'Approved {{count}} requests',
|
|
4231
|
+
bulkApproved_one: 'Approved {{count}} request',
|
|
4232
|
+
bulkApproved_other: 'Approved {{count}} requests',
|
|
3457
4233
|
bulkRejected: 'Rejected {{count}} requests',
|
|
4234
|
+
bulkRejected_one: 'Rejected {{count}} request',
|
|
4235
|
+
bulkRejected_other: 'Rejected {{count}} requests',
|
|
3458
4236
|
bulkPartial: '{{ok}} succeeded, {{fail}} failed: {{which}}',
|
|
3459
4237
|
rejectOneTitle: 'Reject "{{title}}"?',
|
|
3460
4238
|
rejectOneBody: 'This rejects the request and notifies the submitter.',
|
|
@@ -3479,8 +4257,14 @@ const en = {
|
|
|
3479
4257
|
alreadyDecided: 'This request was already decided. Refresh the list.',
|
|
3480
4258
|
justNow: 'just now',
|
|
3481
4259
|
minutesAgo: '{{count}}m ago',
|
|
4260
|
+
minutesAgo_one: '{{count}}m ago',
|
|
4261
|
+
minutesAgo_other: '{{count}}m ago',
|
|
3482
4262
|
hoursAgo: '{{count}}h ago',
|
|
4263
|
+
hoursAgo_one: '{{count}}h ago',
|
|
4264
|
+
hoursAgo_other: '{{count}}h ago',
|
|
3483
4265
|
daysAgo: '{{count}}d ago',
|
|
4266
|
+
daysAgo_one: '{{count}}d ago',
|
|
4267
|
+
daysAgo_other: '{{count}}d ago',
|
|
3484
4268
|
},
|
|
3485
4269
|
filterBuilder: {
|
|
3486
4270
|
where: 'Where',
|
|
@@ -3504,25 +4288,25 @@ const en = {
|
|
|
3504
4288
|
rangeEnd: 'To',
|
|
3505
4289
|
operators: {
|
|
3506
4290
|
equals: 'Equals',
|
|
3507
|
-
|
|
4291
|
+
not_equals: 'Does not equal',
|
|
3508
4292
|
contains: 'Contains',
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
4293
|
+
icontains: 'Contains (ignore case)',
|
|
4294
|
+
not_contains: 'Does not contain',
|
|
4295
|
+
is_empty: 'Is empty',
|
|
4296
|
+
is_not_empty: 'Is not empty',
|
|
4297
|
+
greater_than: 'Greater than',
|
|
4298
|
+
less_than: 'Less than',
|
|
4299
|
+
greater_than_or_equal: 'Greater than or equal',
|
|
4300
|
+
less_than_or_equal: 'Less than or equal',
|
|
3517
4301
|
before: 'Before',
|
|
3518
4302
|
after: 'After',
|
|
3519
4303
|
between: 'Between',
|
|
3520
4304
|
in: 'In',
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
4305
|
+
not_in: 'Not in',
|
|
4306
|
+
starts_with: 'Starts with',
|
|
4307
|
+
ends_with: 'Ends with',
|
|
4308
|
+
is_null: 'Is null',
|
|
4309
|
+
is_not_null: 'Is not null',
|
|
3526
4310
|
exists: 'Is set',
|
|
3527
4311
|
notExists: 'Is not set',
|
|
3528
4312
|
},
|
|
@@ -3545,13 +4329,11 @@ const en = {
|
|
|
3545
4329
|
// The generic action words (Save / Cancel / Edit / Delete) are NOT repeated
|
|
3546
4330
|
// here — the thread reads them from `common`.
|
|
3547
4331
|
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.
|
|
4332
|
+
// Thread header. An i18next count family (objectui#11445): the component
|
|
4333
|
+
// passes `count` and i18next picks the slot each pack's CLDR rules select.
|
|
3553
4334
|
commentCount: '{{count}} comments',
|
|
3554
|
-
|
|
4335
|
+
commentCount_one: '{{count}} comment',
|
|
4336
|
+
commentCount_other: '{{count}} comments',
|
|
3555
4337
|
// Appended to the count, separator included, so a translator owns the
|
|
3556
4338
|
// whole phrase rather than inheriting an English-shaped ` · ` glue.
|
|
3557
4339
|
resolvedSuffix: ' · Resolved',
|
|
@@ -3564,14 +4346,21 @@ const en = {
|
|
|
3564
4346
|
// existing minute/hour/day buckets and no date library was introduced.
|
|
3565
4347
|
justNow: 'just now',
|
|
3566
4348
|
minutesAgo: '{{count}}m ago',
|
|
4349
|
+
minutesAgo_one: '{{count}}m ago',
|
|
4350
|
+
minutesAgo_other: '{{count}}m ago',
|
|
3567
4351
|
hoursAgo: '{{count}}h ago',
|
|
4352
|
+
hoursAgo_one: '{{count}}h ago',
|
|
4353
|
+
hoursAgo_other: '{{count}}h ago',
|
|
3568
4354
|
daysAgo: '{{count}}d ago',
|
|
4355
|
+
daysAgo_one: '{{count}}d ago',
|
|
4356
|
+
daysAgo_other: '{{count}}d ago',
|
|
3569
4357
|
edited: '(edited)',
|
|
3570
4358
|
// Reaction-chip tooltip. A DEDICATED pair rather than `detail.reactionCount`:
|
|
3571
4359
|
// that one interpolates `{{emoji}}`, and here the emoji is the chip's
|
|
3572
4360
|
// visible label with nothing to hand the placeholder.
|
|
3573
4361
|
reactionCount: '{{count}} reactions',
|
|
3574
|
-
|
|
4362
|
+
reactionCount_one: '{{count}} reaction',
|
|
4363
|
+
reactionCount_other: '{{count}} reactions',
|
|
3575
4364
|
addThumbsUp: 'Add thumbs up',
|
|
3576
4365
|
reply: 'Reply',
|
|
3577
4366
|
// Accessible names for the three emoji-only controls (objectui#3441).
|
|
@@ -3597,12 +4386,14 @@ const en = {
|
|
|
3597
4386
|
send: 'Send',
|
|
3598
4387
|
// Presence avatar stack (objectui#3440). `presentUserCount*` is the avatar
|
|
3599
4388
|
// group's `aria-label` — with only images and initials inside, that label
|
|
3600
|
-
// IS the control for a screen reader.
|
|
3601
|
-
//
|
|
4389
|
+
// IS the control for a screen reader. Count families, like `commentCount`
|
|
4390
|
+
// above.
|
|
3602
4391
|
presentUserCount: '{{count}} users present',
|
|
3603
|
-
|
|
4392
|
+
presentUserCount_one: '{{count}} user present',
|
|
4393
|
+
presentUserCount_other: '{{count}} users present',
|
|
3604
4394
|
moreUserCount: '{{count}} more users',
|
|
3605
|
-
|
|
4395
|
+
moreUserCount_one: '{{count}} more user',
|
|
4396
|
+
moreUserCount_other: '{{count}} more users',
|
|
3606
4397
|
// Avatar tooltip. The parentheses are part of the translation, spacing
|
|
3607
4398
|
// included, so the CJK packs can drop the space English puts before `(`.
|
|
3608
4399
|
userStatusTitle: '{{name}} ({{status}})',
|
|
@@ -3617,6 +4408,25 @@ const en = {
|
|
|
3617
4408
|
// comma-joined, already-truncated label list built at the call site.
|
|
3618
4409
|
wizard: {
|
|
3619
4410
|
missingRequired: 'Please complete the required fields: {{fields}}',
|
|
4411
|
+
// The wizard's footer and step chrome (objectui#10999). The generic verbs
|
|
4412
|
+
// it shows come from `common.cancel`, `common.next`, `form.create`,
|
|
4413
|
+
// `form.update` and `form.stepOf`; these five are the wizard's own.
|
|
4414
|
+
// The Previous-step button. Not `common.back`: some packs say a wizard's
|
|
4415
|
+
// step back with a different word from a page's back (zh reads "previous
|
|
4416
|
+
// step" here and "return" for `common.back`), and the wizard spelling is
|
|
4417
|
+
// the one `grid.import.back` and `grid.bulk.back` already use.
|
|
4418
|
+
back: 'Back',
|
|
4419
|
+
// The final button while the record is being written.
|
|
4420
|
+
submitting: 'Submitting…',
|
|
4421
|
+
// The step indicator's label for a step that declares no `label`.
|
|
4422
|
+
// `{{n}}` is the 1-based step number.
|
|
4423
|
+
stepFallback: 'Step {{n}}',
|
|
4424
|
+
// The step indicator's `aria-label` — what a screen reader calls the list
|
|
4425
|
+
// of steps.
|
|
4426
|
+
progressLabel: 'Progress',
|
|
4427
|
+
// Shown in place of the fields on a step that has none (a final review
|
|
4428
|
+
// step is the usual case).
|
|
4429
|
+
emptyStep: 'No fields configured for this step',
|
|
3620
4430
|
},
|
|
3621
4431
|
// The screen-flow runner dialog (`app-shell/views/FlowRunner`) — the modal a
|
|
3622
4432
|
// `type: 'flow'` action opens when its run pauses at a `screen` node.
|
|
@@ -3720,5 +4530,77 @@ const en = {
|
|
|
3720
4530
|
bulkOperationFailed: 'Bulk operation failed: {{reason}}',
|
|
3721
4531
|
},
|
|
3722
4532
|
},
|
|
4533
|
+
// objectui#6301 — Setup › Packaged automation (ADR-0126 §7.4): the
|
|
4534
|
+
// operational surface for the flows an installed package ships. Authoring
|
|
4535
|
+
// stays in Studio, so this group has no editing vocabulary at all; it is
|
|
4536
|
+
// on/off, clone, and the states those two produce.
|
|
4537
|
+
//
|
|
4538
|
+
// ⛔ No drift or ancestry wording anywhere in this group (ADR-0126 §9). There
|
|
4539
|
+
// is deliberately no "customized", no "based on v3", no "out of date" — the
|
|
4540
|
+
// platform does not track that lineage, and a translatable string for it is
|
|
4541
|
+
// the cheapest way for the surface to grow one.
|
|
4542
|
+
//
|
|
4543
|
+
// ⛔ Server refusals are NOT in this group either. The posture gate, the
|
|
4544
|
+
// subflow guard and the clone name conflict all arrive as server-authored
|
|
4545
|
+
// prose and are rendered verbatim; the four `*Failed*` keys below are the
|
|
4546
|
+
// last-resort fallbacks for a response that carried no message at all.
|
|
4547
|
+
packagedAutomation: {
|
|
4548
|
+
title: 'Packaged automation',
|
|
4549
|
+
// Covers BOTH sections since ADR-0126 §8 item 2 put packaged actions on
|
|
4550
|
+
// this page: only flows can be cloned, so the clone clause names them.
|
|
4551
|
+
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.',
|
|
4552
|
+
refresh: 'Refresh',
|
|
4553
|
+
// Section headings — the page carries two tables.
|
|
4554
|
+
flowsHeading: 'Packaged flows',
|
|
4555
|
+
actionsHeading: 'Packaged actions',
|
|
4556
|
+
colFlow: 'Flow',
|
|
4557
|
+
colActivation: 'Activation',
|
|
4558
|
+
colActions: 'Actions',
|
|
4559
|
+
// The switch's accessible name — the only place a row's label is spoken.
|
|
4560
|
+
toggleLabel: 'Activation for {{label}}',
|
|
4561
|
+
on: 'On',
|
|
4562
|
+
off: 'Off',
|
|
4563
|
+
clone: 'Clone',
|
|
4564
|
+
cloneTitle: 'Clone packaged flow',
|
|
4565
|
+
cloneBody: 'The copy carries the whole definition and takes a new machine name and label. Edit the copy in Studio.',
|
|
4566
|
+
cloneName: 'New machine name',
|
|
4567
|
+
cloneLabel: 'New label',
|
|
4568
|
+
cancel: 'Cancel',
|
|
4569
|
+
cloneConfirm: 'Create clone',
|
|
4570
|
+
cloneCreated: 'Created flow "{{name}}".',
|
|
4571
|
+
emptyTitle: 'No packaged flows',
|
|
4572
|
+
emptyBody: 'No installed package ships an automation flow on this deployment. Flows you author yourself live in Studio.',
|
|
4573
|
+
loadFailed: 'Could not load packaged automation.',
|
|
4574
|
+
// Two keys per action, not one: the response arm has an HTTP status to
|
|
4575
|
+
// name and the transport-exception arm does not, and a single key cannot
|
|
4576
|
+
// carry a hole only half its call sites can fill.
|
|
4577
|
+
// Artifact-neutral by wording, and shared by BOTH sections' toggles: the
|
|
4578
|
+
// sentence says nothing about flows, so the actions half reuses it rather
|
|
4579
|
+
// than defining a second key with the same English in ten packs.
|
|
4580
|
+
toggleFailedHttp: 'Could not change activation (HTTP {{status}}).',
|
|
4581
|
+
toggleFailed: 'Could not change activation.',
|
|
4582
|
+
cloneFailedHttp: 'Could not clone this flow (HTTP {{status}}).',
|
|
4583
|
+
cloneFailed: 'Could not clone this flow.',
|
|
4584
|
+
// ── Packaged ACTIONS section (ADR-0126 §8 item 2, ruling 3) ────────────
|
|
4585
|
+
// ⛔ No clone key here on purpose: the action-clone half is unchartered,
|
|
4586
|
+
// and a string is the cheapest way for an unchartered surface to appear.
|
|
4587
|
+
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.',
|
|
4588
|
+
colAction: 'Action',
|
|
4589
|
+
colObject: 'Object',
|
|
4590
|
+
// The object is part of the accessible name because it is part of the
|
|
4591
|
+
// identity — two objects may declare the same action name.
|
|
4592
|
+
actionToggleLabel: 'Activation for {{label}} on {{object}}',
|
|
4593
|
+
actionsEmptyTitle: 'No packaged actions',
|
|
4594
|
+
actionsEmptyBody: 'No installed package declares an action on this deployment. Actions you author yourself live in Studio.',
|
|
4595
|
+
actionsLoadFailed: 'Could not load packaged actions.',
|
|
4596
|
+
},
|
|
4597
|
+
element: {
|
|
4598
|
+
// objectui#10951 — `element:number` authored with an aggregate and no
|
|
4599
|
+
// object (neither `object` nor `dataSource.object`). Kept terse: this pack
|
|
4600
|
+
// is eager, and the console closure budget weighs it.
|
|
4601
|
+
number: {
|
|
4602
|
+
noObject: 'No object named: set object or dataSource.object.',
|
|
4603
|
+
},
|
|
4604
|
+
},
|
|
3723
4605
|
};
|
|
3724
4606
|
export default en;
|