@object-ui/i18n 16.1.0 → 17.1.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.
@@ -89,6 +89,10 @@ const en = {
89
89
  package: 'Package',
90
90
  },
91
91
  actions: {
92
+ decisionOutput: {
93
+ help: 'Handed to the flow as a decision output.',
94
+ helpMultiValue: 'Handed to the flow as a decision output. Comma-separate multiple values.',
95
+ },
92
96
  resultDialog: {
93
97
  defaultTitle: 'Save this value now',
94
98
  acknowledge: 'I have saved this',
@@ -109,6 +113,8 @@ const en = {
109
113
  type: '{{field}} must be a valid {{type}}',
110
114
  },
111
115
  form: {
116
+ noPermissionToSave: "You don't have permission to save this record.",
117
+ submitFailed: 'Could not save. Please try again.',
112
118
  addItem: 'Add item',
113
119
  removeItem: 'Remove item',
114
120
  fieldRequired: 'This field is required',
@@ -120,11 +126,13 @@ const en = {
120
126
  discardMessage: 'You have unsaved changes. If you close this form now, your edits will be lost.',
121
127
  keepEditing: 'Keep editing',
122
128
  discard: 'Discard',
129
+ conflictTitle: 'Save conflict',
130
+ conflictMessage: 'This record was changed by someone else while you were editing. Overwriting will replace their changes with yours.',
131
+ conflictLatestVersion: 'Their save: {{time}}',
132
+ conflictOverwrite: 'Overwrite',
123
133
  stepOf: 'Step {{current}} of {{total}}',
124
134
  createTitle: 'Create {{object}}',
125
135
  editTitle: 'Edit {{object}}',
126
- createDescription: 'Add a new {{object}} to your database.',
127
- editDescription: 'Update details for {{object}}',
128
136
  saveRecord: 'Save',
129
137
  create: 'Create',
130
138
  update: 'Update',
@@ -136,11 +144,67 @@ const en = {
136
144
  relativeDate: {
137
145
  overdue: 'Overdue {{count}}d',
138
146
  },
147
+ file: {
148
+ dragDropHere: 'Drag & drop files here',
149
+ dropFilesHere: 'Drop files here',
150
+ browseHint: 'or click to browse',
151
+ browseHintCamera: 'or click to browse • use the camera button below',
152
+ takePhoto: 'Take photo',
153
+ takeSelfie: 'Take selfie',
154
+ cameraCapture: 'Camera capture',
155
+ uploading: 'Uploading…',
156
+ uploadingPct: 'Uploading… ({{pct}}%)',
157
+ fileFallback: 'File',
158
+ upload: 'Upload',
159
+ remove: 'Remove {{name}}',
160
+ exceedsMaxSize: '"{{name}}" exceeds max size ({{max}} MB)',
161
+ uploadFailed: 'Failed to upload "{{name}}": {{error}}',
162
+ },
163
+ image: {
164
+ upload: 'Upload image',
165
+ addMore: 'Add more images',
166
+ uploading: 'Uploading…',
167
+ imageAlt: 'Image {{index}}',
168
+ crop: 'Crop image {{index}}',
169
+ remove: 'Remove image {{index}}',
170
+ enlarge: 'Enlarge {{name}}',
171
+ preview: 'Image preview',
172
+ previous: 'Previous image',
173
+ next: 'Next image',
174
+ counter: '{{current}} / {{total}}',
175
+ },
139
176
  richText: {
140
177
  format: 'Format: {{format}}',
141
178
  basicEditorHint: 'Rich text editor (basic)',
142
179
  placeholder: 'Enter text...',
143
180
  },
181
+ objectRef: {
182
+ loading: 'Loading objects…',
183
+ placeholder: 'Select an object',
184
+ search: 'Search objects…',
185
+ empty: 'No objects found',
186
+ },
187
+ recipient: {
188
+ selectTypeFirst: 'Select a recipient type first.',
189
+ loading: 'Loading…',
190
+ search: 'Search…',
191
+ empty: 'No matches',
192
+ select: 'Select a recipient',
193
+ selectUser: 'Select a user',
194
+ selectTeam: 'Select a team',
195
+ selectBusinessUnit: 'Select a business unit',
196
+ selectPosition: 'Select a position',
197
+ selectUnitAndSubordinates: 'Select a business unit',
198
+ },
199
+ filterCondition: {
200
+ selectObjectFirst: 'Select an object first.',
201
+ noCriteria: 'No criteria — this rule shares nothing',
202
+ criteriaRequired: 'Add at least one condition. A rule with no criteria would share every record, so it cannot be saved.',
203
+ invalidJson: 'Invalid JSON — the rule will match no records until fixed.',
204
+ jsonOnly: 'This criteria can only be edited as JSON',
205
+ editAsJson: 'Edit as JSON',
206
+ useVisualBuilder: 'Use visual builder',
207
+ },
144
208
  },
145
209
  table: {
146
210
  rowsPerPage: 'Rows per page',
@@ -215,9 +279,12 @@ const en = {
215
279
  previewDescription: 'Review data before importing.',
216
280
  dragDrop: 'Drag & drop a CSV or Excel file here, or click to browse',
217
281
  browseFiles: 'Browse Files',
282
+ downloadTemplate: 'Download template',
283
+ downloadTemplateHint: 'Get a CSV with the right columns (required fields marked *).',
284
+ templateFileName: '{{object}}-import-template',
218
285
  parsing: 'Parsing…',
219
286
  pasteHint: 'or paste (Ctrl/⌘+V) rows copied from Excel or Google Sheets',
220
- legacyXls: "Legacy .xls files aren't supported — please re-save as .xlsx.",
287
+ legacyXls: 'Legacy .xls files aren\'t supported — please re-save as .xlsx.',
221
288
  unsupportedFile: 'Unsupported file type. Use CSV, TSV, or Excel (.xlsx).',
222
289
  parseFailed: 'Could not read this file. Please check the format and try again.',
223
290
  fileNeedsHeader: 'File must contain a header row and at least one data row.',
@@ -238,6 +305,13 @@ const en = {
238
305
  csvColumn: 'Column',
239
306
  mapsTo: 'Maps To',
240
307
  typeMismatch: 'Looks like {{type}}',
308
+ autoMatched: 'Auto-matched',
309
+ autoMatchedSummary: 'Auto-matched {{count}} column(s) — review and adjust below.',
310
+ confidence: {
311
+ high: 'High confidence',
312
+ medium: 'Medium confidence',
313
+ low: 'Low confidence',
314
+ },
241
315
  type: {
242
316
  number: 'Number',
243
317
  boolean: 'Boolean',
@@ -255,25 +329,96 @@ const en = {
255
329
  clickToFix: '— click a highlighted cell to fix it inline.',
256
330
  showingRows: 'Showing {{shown}} of {{total}} rows',
257
331
  importing: 'Importing… {{progress}}%',
332
+ asyncQueued: 'Queued — preparing to import…',
333
+ asyncProcessing: 'Importing {{processed}} of {{total}} rows… {{progress}}%',
334
+ asyncLargeHint: 'This file is large, so it will be imported in the background.',
335
+ largeSampleNotice: 'Previewing the first {{shown}} of {{total}} rows.',
336
+ cancelImport: 'Cancel import',
337
+ importCancelled: 'Import cancelled',
338
+ resultsTruncated: 'Showing the first {{count}} row results (of {{total}}).',
258
339
  importComplete: 'Import Complete',
259
340
  imported: '{{count}} imported',
341
+ createdCount: '{{count}} created',
342
+ updatedCount: '{{count}} updated',
260
343
  skippedCount: '{{count}} skipped',
261
344
  moreErrors: '…and {{count}} more errors',
345
+ downloadFailed: 'Download failed rows',
346
+ options: 'Import options',
347
+ writeMode: 'When a row matches an existing record',
348
+ writeModeOpt: {
349
+ insert: 'Always create new',
350
+ update: 'Update existing (skip if no match)',
351
+ upsert: 'Update if matched, else create',
352
+ },
353
+ matchFields: 'Match on',
354
+ matchFieldsPlaceholder: 'Choose match field(s)…',
355
+ matchFieldsHint: 'Rows are matched to existing records by these field(s).',
356
+ needMatchFields: 'Select at least one field to match on.',
357
+ matchOnlyField: '(match only)',
358
+ optCreateOptions: 'Keep unknown option values',
359
+ optRunAutomations: 'Run automations & triggers',
360
+ optTreatHistorical: 'Import as historical data',
361
+ optTreatHistoricalHint: '(import completed records as-is — skip state-machine checks and keep their original timestamps & author instead of stamping now)',
362
+ optSkipBlankKey: 'Skip rows with a blank match value',
363
+ optBackground: 'Import in the background',
364
+ optBackgroundHint: '(runs as an undoable job)',
365
+ validate: 'Validate data',
366
+ validating: 'Validating…',
367
+ validateHint: 'Check every row against the server before importing.',
368
+ validatePassed: 'All {{ok}} rows are valid.',
369
+ validateFailed: '{{ok}} valid, {{errors}} with errors.',
370
+ errorRowPrefix: 'Row {{row}}: ',
371
+ referenceNotFound: 'No matching record for "{{value}}"',
372
+ referenceAmbiguous: '"{{value}}" matches more than one record — use a unique value or the record id',
373
+ invalidBoolean: '"{{value}}" is not a valid true/false value',
374
+ invalidNumber: '"{{value}}" is not a valid number',
375
+ invalidDate: '"{{value}}" is not a valid date',
376
+ invalidOption: '"{{value}}" is not one of the allowed options',
377
+ requiredValue: 'This field is required',
378
+ matchAmbiguous: 'Matches more than one existing record — use a unique value or the record id',
379
+ history: 'History',
380
+ historyBack: 'Back to import',
381
+ historyDescription: 'Recent imports for this object.',
382
+ historyHint: 'Background import jobs, newest first.',
383
+ historyRefresh: 'Refresh',
384
+ historyLoading: 'Loading…',
385
+ historyEmpty: 'No imports yet.',
386
+ historyUnsupported: 'Import history isn’t available for this data source.',
387
+ historyColStatus: 'Status',
388
+ historyColRows: 'Rows',
389
+ historyColResult: 'Result',
390
+ historyColTime: 'When',
391
+ errorCount: '{{count}} errors',
392
+ undoImport: 'Undo import',
393
+ undoing: 'Undoing…',
394
+ undoConfirm: 'Undo this import? Records it created will be deleted and records it updated will be restored to their previous values.',
395
+ reverted: 'Undone',
396
+ jobStatus: {
397
+ pending: 'Pending',
398
+ running: 'Running',
399
+ succeeded: 'Succeeded',
400
+ failed: 'Failed',
401
+ cancelled: 'Cancelled',
402
+ },
262
403
  cancel: 'Cancel',
263
404
  back: 'Back',
264
405
  next: 'Next',
265
406
  close: 'Close',
266
407
  importNRows: 'Import {{count}} Rows',
267
408
  importingProgress: 'Importing…',
268
- requiredMark: '*',
269
409
  required: 'Required',
270
410
  invalidType: 'Invalid {{type}}',
271
- legacyReferenceBlocked: 'Import blocked: {{fields}} are relation fields that need the server import route to resolve names into record IDs, and this connection doesn\u2019t support it. Importing them as plain text would corrupt the data. Upgrade the backend/client, or unmap these columns and import them separately.',
411
+ legacyReferenceBlocked: 'Import blocked: {{fields}} are relation fields that need the server import route to resolve names into record IDs, and this connection doesn’t support it. Importing them as plain text would corrupt the data. Upgrade the backend/client, or unmap these columns and import them separately.',
412
+ missingRequiredHint: 'Can’t continue — required field(s) not mapped: {{fields}}. Add a matching column to your file, or go back and upload one that includes it.',
413
+ legacyFallbackNotice: 'Imported via a compatibility fallback: this connection doesn’t support the server import route, so values were saved as text without server-side type coercion. Upgrade the backend/client for full import support (type coercion and relation lookups).',
414
+ notAllowed: 'This object is not open for import.',
415
+ requiredMark: '*',
272
416
  },
273
417
  bulk: {
274
418
  confirmDefault: 'This will apply to {{count}} record(s).',
275
419
  overLimit: 'Selection ({{count}}) exceeds the action limit ({{limit}}). Reduce the selection to proceed.',
276
420
  affectedRecords: 'Affected records ({{count}}):',
421
+ skippedIneligible: '{{count}} selected record(s) are not eligible for this action and will be skipped.',
277
422
  rowFallback: 'Row {{index}}',
278
423
  andMore: '\u2026 and {{count}} more',
279
424
  processed: '{{count}} / {{total}} processed',
@@ -318,6 +463,8 @@ const en = {
318
463
  filterRecords: 'Filter Records',
319
464
  sort: 'Sort',
320
465
  sortRecords: 'Sort Records',
466
+ sortByIdSuffix: '(by ID)',
467
+ sortRelationalHint: 'Columns that link to another record are not listed: they can only be sorted by the stored ID, not by the name shown in the cell. To sort by that name, add a formula field holding it.',
321
468
  group: 'Group',
322
469
  groupBy: 'Group By',
323
470
  export: 'Export',
@@ -336,6 +483,12 @@ const en = {
336
483
  noMatchesMessage: 'No records match your current filters or search. Try adjusting or clearing them.',
337
484
  loadErrorTitle: 'Couldn\u2019t load records',
338
485
  loadErrorMessage: 'Something went wrong while loading this data. Check your connection and try again.',
486
+ loadErrorForbiddenTitle: 'You don\u2019t have access',
487
+ loadErrorForbiddenMessage: 'You don\u2019t have permission to view these records. Contact your administrator if you think you should have access.',
488
+ loadErrorUnauthorizedTitle: 'Sign in required',
489
+ loadErrorUnauthorizedMessage: 'Your session has expired or you are signed out. Sign in again to view these records.',
490
+ loadErrorRejectedTitle: 'This view’s query was rejected',
491
+ loadErrorRejectedMessage: 'The server could not process this view’s filter or query options. Clearing the filters usually fixes it; if the view is saved this way, an administrator needs to correct it.',
339
492
  retry: 'Retry',
340
493
  managedBy: {
341
494
  system: {
@@ -411,6 +564,7 @@ const en = {
411
564
  deleteColumn: 'Delete column',
412
565
  noCards: 'No cards',
413
566
  cardTitlePlaceholder: 'Enter card title...',
567
+ uncategorized: 'Uncategorized',
414
568
  },
415
569
  timeline: {
416
570
  bucket: {
@@ -562,9 +716,15 @@ const en = {
562
716
  editInlineHint: 'Double-click to edit',
563
717
  lockedByApproval: 'Locked for approval',
564
718
  lockedTooltip: 'This record has a pending approval request; editing is locked',
719
+ writeStrippedTitle: 'Some fields were not saved',
720
+ writeStrippedReadonly: 'Read-only, so it was not saved: {{fields}}',
721
+ writeStrippedByState: "Not editable in this record's current state, so it was not saved: {{fields}}",
722
+ approvalPendingEditable: 'In approval · editable',
723
+ approvalPendingTooltip: 'This record has a pending approval request; this step still allows editing',
565
724
  cancelApproval: 'Recall approval',
566
725
  cancelApprovalInFlight: 'Recalling…',
567
726
  cancelApprovalTooltip: 'Recall the pending approval request to unlock this record',
727
+ cancelApprovalTooltipUnlocked: 'Recall the pending approval request',
568
728
  cancelApprovalFailed: 'Failed to recall approval',
569
729
  cancelApprovalUnavailable: 'Recalling approvals is not supported on this data source',
570
730
  linkCopied: 'Link copied to clipboard',
@@ -651,6 +811,18 @@ const en = {
651
811
  attachmentCount: '{{count}} attachment',
652
812
  attachmentCountPlural: '{{count}} attachments',
653
813
  removeAttachment: 'Remove attachment',
814
+ // Record Attachments panel (enable.files, objectstack#4358)
815
+ attachments: 'Attachments',
816
+ uploadAttachment: 'Upload',
817
+ loadingAttachments: 'Loading attachments…',
818
+ noAttachments: 'No attachments yet. Upload a file to get started.',
819
+ downloadAttachment: 'Download',
820
+ deleteAttachment: 'Delete attachment',
821
+ attachmentDeleteDenied: 'Only the uploader or someone who can edit this record may delete this attachment.',
822
+ attachmentParentAccessDenied: "You don't have access to attach files to this record.",
823
+ attachmentDownloadDenied: "You don't have access to download this attachment.",
824
+ attachmentAuthRequired: 'Please sign in to download this attachment.',
825
+ attachmentPermissionDenied: "You don't have permission to do that.",
654
826
  // Diff
655
827
  unifiedDiff: 'Unified diff',
656
828
  sideBySideDiff: 'Side-by-side diff',
@@ -1074,6 +1246,7 @@ const en = {
1074
1246
  navTypeGroup: 'Group',
1075
1247
  navTypeSeparator: 'Separator',
1076
1248
  navTypeAction: 'Action',
1249
+ navTypeComponent: 'Component',
1077
1250
  navEditIcon: 'Edit icon',
1078
1251
  navToggleVisible: 'Toggle visibility',
1079
1252
  navHidden: 'Hidden',
@@ -1190,6 +1363,24 @@ const en = {
1190
1363
  dragToReorder: 'Drag to reorder',
1191
1364
  favorites: 'Favorites',
1192
1365
  },
1366
+ settingsHub: {
1367
+ title: 'Settings',
1368
+ subtitle: 'Configure your workspace, integrations, and feature flags.',
1369
+ loadError: 'Failed to load settings',
1370
+ empty: 'No settings registered. Plugins can register settings manifests via the SettingsService.',
1371
+ settingsCount: '{{n}} settings',
1372
+ beta: 'Beta',
1373
+ // Section headers, keyed by the manifest `category` value. Unknown
1374
+ // (plugin-authored) categories fall back to the literal category string.
1375
+ categories: {
1376
+ Workspace: 'Workspace',
1377
+ Communication: 'Communication',
1378
+ Security: 'Security',
1379
+ Infrastructure: 'Infrastructure',
1380
+ Beta: 'Beta',
1381
+ Other: 'Other',
1382
+ },
1383
+ },
1193
1384
  loadingSteps: {
1194
1385
  connecting: 'Connecting to data source',
1195
1386
  loadingConfig: 'Loading configuration',
@@ -1348,6 +1539,26 @@ const en = {
1348
1539
  planApproveMessage: 'Looks good — build it as proposed.',
1349
1540
  planApproveDefaultsMessage: 'Build it with your best assumptions; use sensible defaults for the open questions.',
1350
1541
  planAnswerMessage: 'For "{{question}}", go with: {{option}}.',
1542
+ changesTitle: 'Confirm changes',
1543
+ changesConfirmed: 'Confirmed',
1544
+ changesConfirm: 'Confirm',
1545
+ changesConfirmHint: 'Reply to confirm or adjust this change.',
1546
+ // Wording is load-bearing: this is SENT to the agent and must satisfy the
1547
+ // cloud confirm gate's English clause `apply (this|the) change`
1548
+ // (service-ai-studio confirm-gate.ts APPROVAL_RE). "apply what you just
1549
+ // proposed" did NOT match, so the button was inert. Singular "the change"
1550
+ // so it still matches if the gate ever adds a word boundary.
1551
+ changesConfirmMessage: 'Confirm — apply the change you just proposed.',
1552
+ changeVerb: {
1553
+ createObject: 'Create object',
1554
+ addField: 'Add field',
1555
+ modifyField: 'Modify field',
1556
+ deleteField: 'Delete field',
1557
+ createMetadata: 'Create',
1558
+ updateMetadata: 'Modify',
1559
+ createSeed: 'Generate sample data',
1560
+ createPackage: 'Create app package',
1561
+ },
1351
1562
  justNow: 'just now',
1352
1563
  minutesAgo: '{{count}}m ago',
1353
1564
  hoursAgo: '{{count}}h ago',
@@ -1786,6 +1997,59 @@ const en = {
1786
1997
  shell: {
1787
1998
  tenantHostHint: 'You are signing in to this workspace',
1788
1999
  },
2000
+ // These were previously supplied only as inline `defaultValue:` args at the
2001
+ // SetPasswordPage call sites, so `zh` was the only pack that could carry a
2002
+ // translation. Owning them here makes the page translatable everywhere.
2003
+ setPassword: {
2004
+ title: 'Set a recovery password',
2005
+ description: 'You signed in via single sign-on. Set a local password so you can still sign in to this environment directly if SSO ever becomes unavailable.',
2006
+ email: 'Email',
2007
+ newPassword: 'New password',
2008
+ confirmPassword: 'Confirm password',
2009
+ submit: 'Set password',
2010
+ submitting: 'Saving…',
2011
+ success: 'Local password set',
2012
+ failed: 'Could not set password',
2013
+ passwordsMismatch: 'Passwords do not match',
2014
+ noSession: 'Your session has expired.',
2015
+ backToSignIn: 'Sign in again',
2016
+ },
2017
+ layout: {
2018
+ headline: 'Build powerful business applications, faster.',
2019
+ subhead: 'The universal platform for enterprise data management, workflows, and analytics.',
2020
+ },
2021
+ // ADR-0069 full-screen remediation gate. A user hitting this cannot reach
2022
+ // the rest of the app until they finish, so it must read in their language.
2023
+ remediation: {
2024
+ signOut: 'Sign out instead',
2025
+ password: {
2026
+ title: 'Your password has expired',
2027
+ fallbackMessage: 'Please set a new password to continue.',
2028
+ current: 'Current password',
2029
+ next: 'New password',
2030
+ confirm: 'Confirm new password',
2031
+ submit: 'Change password & continue',
2032
+ submitting: 'Updating…',
2033
+ mismatch: 'New passwords do not match.',
2034
+ failed: 'Could not change password.',
2035
+ },
2036
+ mfa: {
2037
+ title: 'Set up two-factor authentication',
2038
+ fallbackMessage: 'Your organization requires an authenticator app to continue.',
2039
+ confirmPassword: 'Confirm your password',
2040
+ continue: 'Continue',
2041
+ preparing: 'Preparing…',
2042
+ enrollFailed: 'Could not start enrollment.',
2043
+ scanTitle: 'Scan with your authenticator',
2044
+ scanBody: 'Scan this QR code with Google Authenticator, 1Password, Authy, etc., then enter the 6-digit code.',
2045
+ backupTitle: 'Save your backup codes',
2046
+ backupBody: 'Store these somewhere safe — each can be used once if you lose your device.',
2047
+ codeLabel: '6-digit code',
2048
+ verify: 'Verify & continue',
2049
+ verifying: 'Verifying…',
2050
+ invalidCode: 'Invalid code. Try again.',
2051
+ },
2052
+ },
1789
2053
  },
1790
2054
  profile: {
1791
2055
  title: 'Profile',
@@ -1881,6 +2145,7 @@ const en = {
1881
2145
  offline: 'Offline',
1882
2146
  usersOnline: 'Users currently online',
1883
2147
  switchView: 'Switch view',
2148
+ switchObject: 'Switch Object',
1884
2149
  connection: {
1885
2150
  connected: 'Connected',
1886
2151
  connecting: 'Connecting...',
@@ -1900,6 +2165,14 @@ const en = {
1900
2165
  subtitle: 'Your workspace dashboard',
1901
2166
  nav: 'Home',
1902
2167
  allApps: 'All Applications',
2168
+ yourApps: 'Your apps',
2169
+ showMoreApps: 'More',
2170
+ showLess: 'Show less',
2171
+ continueEmpty: 'Items you open will show up here.',
2172
+ actionCenter: {
2173
+ title: 'Needs your attention',
2174
+ empty: "You're all caught up",
2175
+ },
1903
2176
  greetingMorning: 'Good morning',
1904
2177
  greetingAfternoon: 'Good afternoon',
1905
2178
  greetingEvening: 'Good evening',
@@ -2119,8 +2392,8 @@ const en = {
2119
2392
  description: 'Please provide the required information to continue.',
2120
2393
  selectPlaceholder: 'Select {{label}}',
2121
2394
  requiredError: '{{label}} is required',
2122
- lookupPlaceholder: 'Paste the {{label}} record id (UUID)',
2123
- lookupHelpText: 'Enter the record id of the referenced object. A picker is coming soon.',
2395
+ lookupPlaceholder: 'Record id for {{label}}',
2396
+ 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.',
2124
2397
  cancel: 'Cancel',
2125
2398
  confirm: 'Confirm',
2126
2399
  uploading: 'Uploading…',
@@ -2208,6 +2481,10 @@ const en = {
2208
2481
  filterAll: 'All',
2209
2482
  markAllRead: 'Mark all read',
2210
2483
  viewAll: 'View all notifications',
2484
+ groupCount: '{{count}} notifications',
2485
+ groupUnread: '{{count}} unread',
2486
+ groupMarkRead: 'Mark read',
2487
+ groupMarkReadTitle: 'Mark all of this type read',
2211
2488
  approvalsPending: '{{count}} pending approvals',
2212
2489
  viewApprovals: 'View approvals',
2213
2490
  noPendingApprovals: 'No pending approvals',
@@ -2320,6 +2597,93 @@ const en = {
2320
2597
  done: 'Done — hide it',
2321
2598
  },
2322
2599
  },
2600
+ excelImport: {
2601
+ noImportableFields: 'That object has no importable fields.',
2602
+ schemaReadFailed: 'Could not read the object schema.',
2603
+ imported: 'Imported {{count}} row(s) into {{object}}.',
2604
+ importFrom: 'Import the real rows from',
2605
+ into: 'into',
2606
+ opening: 'Opening…',
2607
+ importAction: 'Import',
2608
+ dismiss: 'Dismiss',
2609
+ },
2610
+ cloudOnboarding: {
2611
+ hintCreate: 'Spin up your first environment — a private workspace with its own URL, database, and plan. Building happens inside it.',
2612
+ hintReady: 'Your production environment is ready. Open it to build and run your apps — that all happens inside the environment.',
2613
+ createEnvironment: 'Create your environment',
2614
+ openProduction: 'Open Production',
2615
+ manageEnvironments: 'Manage environments',
2616
+ },
2617
+ aiModelStatus: {
2618
+ summary: 'Build / Ask uses {{conversational}} ({{conversationalSource}}); structured uses {{structured}} ({{structuredSource}}).',
2619
+ summaryRouting: 'Routing policy: free plans → {{free}}, paid plans → {{paid}}.',
2620
+ modelUnknown: 'unknown',
2621
+ sourceUnknown: 'not reported by the adapter',
2622
+ rowConversational: 'Build / Ask model',
2623
+ rowStructured: 'Structured (blueprint / seed)',
2624
+ rowReasoning: 'Reasoning effort',
2625
+ readFailed: 'Couldn\'t read the effective AI model. This environment may not run an AI service, or you may lack the ai:read permission.',
2626
+ readFailedWithStatus: 'Couldn\'t read the effective AI model (HTTP {{status}}). This environment may not run an AI service, or you may lack the ai:read permission.',
2627
+ overridesInEffect: 'Overrides in effect: ',
2628
+ noOverrides: 'none — running the deployed code defaults.',
2629
+ adapter: 'Adapter: ',
2630
+ sourceCodeDefault: 'code default (no env override)',
2631
+ sourceInherits: 'same as build/ask',
2632
+ sourcePinned: 'pinned by {{source}}',
2633
+ },
2634
+ chatbotError: {
2635
+ title: 'Response failed',
2636
+ fallbackDetail: 'Something went wrong. Please try again.',
2637
+ details: 'Details',
2638
+ hide: 'Hide',
2639
+ retry: 'Retry',
2640
+ },
2641
+ chatbotQuota: {
2642
+ title: 'Upgrade needed',
2643
+ fallbackMessage: 'You have reached your AI quota.',
2644
+ buyCredits: 'Buy a credit pack',
2645
+ upgradePlan: 'Upgrade plan',
2646
+ },
2647
+ environment: {
2648
+ addEnvironment: 'Add environment',
2649
+ setUpProduction: 'Set up your production environment',
2650
+ addDevelopment: 'Add development environment',
2651
+ },
2652
+ cloudConnection: {
2653
+ checking: 'Checking connection…',
2654
+ retry: 'Try again',
2655
+ errors: {
2656
+ expired: 'The request expired before it was approved. Start again.',
2657
+ bindFailed: 'Binding failed.',
2658
+ deviceCodeFailed: 'Device code request failed.',
2659
+ },
2660
+ waiting: {
2661
+ popupOpened: 'Approve the connection in the window that just opened — this page updates by itself.',
2662
+ polling: 'Waiting for approval in the cloud console…',
2663
+ openApproval: 'Open the approval page',
2664
+ copy: 'Copy',
2665
+ copied: 'Copied',
2666
+ codePrefilled: 'The code is pre-filled on the approval page.',
2667
+ openItHere: 'Window did not appear? Open it here',
2668
+ cancel: 'Cancel',
2669
+ },
2670
+ bound: {
2671
+ title: 'Connected to ObjectStack Cloud',
2672
+ runtime: 'Runtime',
2673
+ organization: 'Organization',
2674
+ approvedBy: 'Approved by',
2675
+ runtimeId: 'Runtime ID',
2676
+ environment: 'Environment',
2677
+ since: 'Since',
2678
+ privatePackages: 'Your organization\'s private packages now appear in the Marketplace under “Your organization”.',
2679
+ disconnect: 'Disconnect',
2680
+ },
2681
+ unbound: {
2682
+ title: 'Not connected',
2683
+ body: 'Connect this runtime to an ObjectStack control plane to browse your organization\'s private packages and install them here. Approval is a single click in your cloud account — no ids or credentials are typed into this page.',
2684
+ connect: 'Connect',
2685
+ },
2686
+ },
2323
2687
  marketplace: {
2324
2688
  title: 'App Marketplace',
2325
2689
  subtitle: 'Browse approved apps published to the ObjectStack catalog. Click an app to view details and install it into one of your environments.',
@@ -2455,6 +2819,14 @@ const en = {
2455
2819
  yearsAgo: '{{count}}y ago',
2456
2820
  },
2457
2821
  },
2822
+ approvals: {
2823
+ approve: 'Approve',
2824
+ reject: 'Reject',
2825
+ comment: 'Comment (optional)',
2826
+ approveSuccess: 'Approved',
2827
+ rejectSuccess: 'Rejected',
2828
+ rejectConfirm: 'Reject this approval request?',
2829
+ },
2458
2830
  approvalsInbox: {
2459
2831
  loadMore: 'Load more',
2460
2832
  loadingMore: 'Loading…',
@@ -2479,13 +2851,28 @@ const en = {
2479
2851
  slaRemaining: 'SLA {{dur}} left',
2480
2852
  slaOverdue: 'SLA overdue {{dur}}',
2481
2853
  actReassign: 'Reassigned',
2854
+ reassignFromTo: 'from {{from}} to {{to}}',
2482
2855
  actRemind: 'Reminder sent',
2483
2856
  actRequestInfo: 'Requested more info',
2484
2857
  actComment: 'Commented',
2485
2858
  stepProgress: 'Approval steps',
2486
2859
  prevRequest: 'Previous',
2487
2860
  nextRequest: 'Next',
2488
- positionOf: '{{index}} of {{total}}',
2861
+ positionOf: 'Request {{index}} of {{total}}',
2862
+ progressApprovals: 'Approvals — {{got}} of {{need}}',
2863
+ progressGroups: 'Sign-off progress — {{got}} of {{need}} groups',
2864
+ progressEligible: '{{count}} eligible approver(s)',
2865
+ progressBar: 'Decision progress',
2866
+ declaredActions: 'Actions',
2867
+ attachmentChip: 'Attachment',
2868
+ attachmentOpenFailed: 'Could not open the attachment — please try again',
2869
+ approveOneTitle: 'Approve "{{title}}"?',
2870
+ approveOneBody: 'This approves the request with your identity. To add a comment or attachment, open the request instead.',
2871
+ flowOrigin: 'Flow-initiated',
2872
+ sortBy: 'Sort',
2873
+ sortRecent: 'Newest first',
2874
+ sortOldest: 'Oldest first',
2875
+ sortAmount: 'Amount (high→low)',
2489
2876
  quickPhrase1: 'Approved — meets requirements.',
2490
2877
  quickPhrase2: 'Approved with conditions — please monitor execution.',
2491
2878
  quickPhrase3: 'Please add supporting material and resubmit.',