@object-ui/app-shell 11.3.0 → 11.5.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 +700 -0
- package/README.md +32 -0
- package/dist/chrome/KeyboardShortcutsDialog.js +2 -1
- package/dist/console/AppContent.js +145 -26
- package/dist/console/ConsoleShell.js +25 -3
- package/dist/console/home/CloudOnboardingNext.d.ts +9 -0
- package/dist/console/home/CloudOnboardingNext.js +14 -4
- package/dist/console/home/HomePage.js +34 -7
- package/dist/console/organizations/CreateWorkspaceDialog.js +33 -3
- package/dist/console/organizations/OrganizationsPage.js +16 -7
- package/dist/context/CommandPaletteProvider.js +2 -1
- package/dist/hooks/useConsoleActionRuntime.js +32 -3
- package/dist/hooks/useObjectActions.js +16 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/layout/AppHeader.js +13 -5
- package/dist/layout/AppSidebar.js +10 -4
- package/dist/observability/sentry.d.ts +5 -0
- package/dist/observability/sentry.js +6 -1
- package/dist/preview/DraftChangesPanel.d.ts +31 -1
- package/dist/preview/DraftChangesPanel.js +146 -18
- package/dist/urlParams.d.ts +68 -0
- package/dist/urlParams.js +76 -0
- package/dist/utils/appRoute.d.ts +15 -0
- package/dist/utils/appRoute.js +22 -0
- package/dist/utils/deriveRelatedLists.d.ts +20 -5
- package/dist/utils/deriveRelatedLists.js +31 -13
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/pageTabsUrlSync.d.ts +32 -0
- package/dist/utils/pageTabsUrlSync.js +43 -0
- package/dist/utils/recordFormNavigation.d.ts +40 -0
- package/dist/utils/recordFormNavigation.js +30 -0
- package/dist/utils/resolveViewId.d.ts +23 -0
- package/dist/utils/resolveViewId.js +37 -0
- package/dist/utils/warnSuppressedListNav.d.ts +10 -0
- package/dist/utils/warnSuppressedListNav.js +40 -0
- package/dist/views/InterfaceListPage.d.ts +1 -0
- package/dist/views/InterfaceListPage.js +7 -5
- package/dist/views/ObjectDataPage.d.ts +29 -0
- package/dist/views/ObjectDataPage.js +227 -0
- package/dist/views/ObjectView.js +65 -13
- package/dist/views/RecordDetailView.js +191 -123
- package/dist/views/RecordFormPage.js +7 -1
- package/dist/views/RelatedRecordActionsBridge.d.ts +33 -0
- package/dist/views/RelatedRecordActionsBridge.js +147 -0
- package/dist/views/metadata-admin/PackagesPage.js +18 -7
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +18 -1
- package/dist/views/metadata-admin/PermissionMatrixEditor.js +73 -14
- package/dist/views/metadata-admin/ResourceEditPage.js +39 -0
- package/dist/views/metadata-admin/i18n.d.ts +12 -21
- package/dist/views/metadata-admin/i18n.js +557 -6
- package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +11 -4
- package/dist/views/metadata-admin/inspectors/AppNavInspector.js +141 -7
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +14 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +76 -5
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +60 -30
- package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +8 -1
- package/dist/views/metadata-admin/inspectors/flow-node-config.js +3 -2
- package/dist/views/metadata-admin/inspectors/nav-target.d.ts +52 -0
- package/dist/views/metadata-admin/inspectors/nav-target.js +149 -0
- package/dist/views/metadata-admin/nav-selection.d.ts +20 -0
- package/dist/views/metadata-admin/nav-selection.js +81 -0
- package/dist/views/metadata-admin/permission-slice.d.ts +66 -0
- package/dist/views/metadata-admin/permission-slice.js +70 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +19 -7
- package/dist/views/metadata-admin/previews/AppPreview.js +4 -2
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +16 -7
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +18 -2
- package/dist/views/studio-design/BuilderLanding.d.ts +15 -0
- package/dist/views/studio-design/BuilderLanding.js +126 -0
- package/dist/views/studio-design/ObjectFormDesigner.d.ts +33 -0
- package/dist/views/studio-design/ObjectFormDesigner.js +231 -0
- package/dist/views/studio-design/ObjectSettingsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectSettingsPanel.js +46 -0
- package/dist/views/studio-design/ObjectValidationsPanel.d.ts +30 -0
- package/dist/views/studio-design/ObjectValidationsPanel.js +80 -0
- package/dist/views/studio-design/PackageIdInput.d.ts +31 -0
- package/dist/views/studio-design/PackageIdInput.js +40 -0
- package/dist/views/studio-design/StudioDesignSurface.d.ts +13 -0
- package/dist/views/studio-design/StudioDesignSurface.js +962 -145
- package/dist/views/studio-design/metadataError.d.ts +23 -0
- package/dist/views/studio-design/metadataError.js +44 -0
- package/dist/views/studio-design/packageSurfaces.d.ts +49 -0
- package/dist/views/studio-design/packageSurfaces.js +34 -0
- package/dist/views/studio-design/packages-io.d.ts +38 -0
- package/dist/views/studio-design/packages-io.js +73 -0
- package/dist/views/studio-design/skeletons.d.ts +16 -0
- package/dist/views/studio-design/skeletons.js +51 -0
- package/package.json +42 -39
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Metadata admin i18n bundle (Phase 3f).
|
|
4
|
+
*
|
|
5
|
+
* Lightweight static label table for the 27 built-in metadata types,
|
|
6
|
+
* plus a tiny `t()` helper for engine UI strings.
|
|
7
|
+
*
|
|
8
|
+
* Why not i18next? The engine already consumes `label` from the
|
|
9
|
+
* server's `/meta/types` response (which is sourced from
|
|
10
|
+
* `DEFAULT_METADATA_TYPE_REGISTRY`). This bundle exists as a fallback
|
|
11
|
+
* for environments without translation bundles configured, and as the
|
|
12
|
+
* single source of truth for Chinese labels until the platform's
|
|
13
|
+
* `setup.translation.ts` ships zh-CN coverage.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* import { translateMetadataType, t } from './i18n';
|
|
17
|
+
* translateMetadataType('view', 'zh-CN') // → '视图'
|
|
18
|
+
* t('engine.directory.title', 'zh-CN') // → '元数据'
|
|
19
|
+
*
|
|
20
|
+
* The DirectoryPage / PageShell call these to localise headings when
|
|
21
|
+
* the consumer hasn't wired the global i18n provider.
|
|
22
|
+
*/
|
|
23
|
+
import { useObjectTranslation } from '@object-ui/i18n';
|
|
2
24
|
const TYPE_LABELS_EN = {
|
|
3
25
|
// Data
|
|
4
26
|
object: 'Object',
|
|
@@ -345,10 +367,38 @@ const ENGINE_STRINGS_EN = {
|
|
|
345
367
|
'engine.inspector.appNav.kind': 'Nav Item',
|
|
346
368
|
'engine.inspector.appNav.close': 'Close nav item',
|
|
347
369
|
'engine.inspector.appNav.label': 'Label',
|
|
348
|
-
'engine.inspector.appNav.path': 'Path / Route',
|
|
349
370
|
'engine.inspector.appNav.icon': 'Icon',
|
|
350
|
-
'engine.inspector.appNav.kindField': 'Kind',
|
|
351
371
|
'engine.inspector.appNav.remove': 'Remove nav item',
|
|
372
|
+
'engine.inspector.appNav.typeField': 'Type',
|
|
373
|
+
'engine.inspector.appNav.type.object': 'Object',
|
|
374
|
+
'engine.inspector.appNav.type.page': 'Page',
|
|
375
|
+
'engine.inspector.appNav.type.dashboard': 'Dashboard',
|
|
376
|
+
'engine.inspector.appNav.type.report': 'Report',
|
|
377
|
+
'engine.inspector.appNav.type.url': 'Link (URL)',
|
|
378
|
+
'engine.inspector.appNav.type.group': 'Group',
|
|
379
|
+
'engine.inspector.appNav.object': 'Object',
|
|
380
|
+
'engine.inspector.appNav.targetMode': 'Landing',
|
|
381
|
+
'engine.inspector.appNav.mode.default': 'Default view (workspace)',
|
|
382
|
+
'engine.inspector.appNav.mode.view': 'Named view',
|
|
383
|
+
'engine.inspector.appNav.mode.record': 'Record deep-link',
|
|
384
|
+
'engine.inspector.appNav.mode.filters': 'Filtered slice (/data)',
|
|
385
|
+
'engine.inspector.appNav.view': 'View',
|
|
386
|
+
'engine.inspector.appNav.recordId': 'Record ID',
|
|
387
|
+
'engine.inspector.appNav.recordIdHint': 'Supports {current_user_id} and {current_org_id} template variables.',
|
|
388
|
+
'engine.inspector.appNav.recordMode': 'Open mode',
|
|
389
|
+
'engine.inspector.appNav.recordModeView': 'View',
|
|
390
|
+
'engine.inspector.appNav.recordModeEdit': 'Edit',
|
|
391
|
+
'engine.inspector.appNav.filters': 'URL filters',
|
|
392
|
+
'engine.inspector.appNav.filtersField': 'Field',
|
|
393
|
+
'engine.inspector.appNav.filtersValue': 'Value',
|
|
394
|
+
'engine.inspector.appNav.filtersAdd': 'Add condition',
|
|
395
|
+
'engine.inspector.appNav.filtersRemove': 'Remove condition',
|
|
396
|
+
'engine.inspector.appNav.filtersHint': 'One-off slice carried in the URL — promote it to a named view when it becomes curated and reused.',
|
|
397
|
+
'engine.inspector.appNav.url': 'URL',
|
|
398
|
+
'engine.inspector.appNav.urlTarget': 'Open in',
|
|
399
|
+
'engine.inspector.appNav.urlTargetSelf': 'Same tab',
|
|
400
|
+
'engine.inspector.appNav.urlTargetBlank': 'New tab',
|
|
401
|
+
'engine.inspector.appNav.preview': 'Resolved link',
|
|
352
402
|
// View column inspector
|
|
353
403
|
'engine.inspector.viewColumn.kind': 'Column',
|
|
354
404
|
'engine.inspector.viewColumn.close': 'Close column',
|
|
@@ -547,9 +597,10 @@ const ENGINE_STRINGS_EN = {
|
|
|
547
597
|
'engine.packages.col.version': 'Version',
|
|
548
598
|
'engine.packages.col.scope': 'Scope',
|
|
549
599
|
'engine.packages.col.status': 'Status',
|
|
550
|
-
'engine.packages.scope.project': '
|
|
600
|
+
'engine.packages.scope.project': 'Read-only · code',
|
|
551
601
|
'engine.packages.scope.system': 'System',
|
|
552
602
|
'engine.packages.scope.cloud': 'Cloud',
|
|
603
|
+
'engine.packages.scope.writable': 'Writable',
|
|
553
604
|
'engine.packages.status.enabled': 'Enabled',
|
|
554
605
|
'engine.packages.status.disabled': 'Disabled',
|
|
555
606
|
'engine.packages.import.invalidJson': 'Selected file is not valid JSON.',
|
|
@@ -805,6 +856,234 @@ const ENGINE_STRINGS_EN = {
|
|
|
805
856
|
// AI assistant entry points
|
|
806
857
|
'designer.canvas.askAi': 'Ask AI',
|
|
807
858
|
'designer.canvas.askAiGenerate': 'Generate fields with AI',
|
|
859
|
+
// ── StudioDesignSurface (ADR-0080 WYSIWYG design surface) ──────────────
|
|
860
|
+
// Shared chrome
|
|
861
|
+
'engine.studio.cancel': 'Cancel',
|
|
862
|
+
'engine.studio.create': 'Create',
|
|
863
|
+
'engine.studio.createDraft': 'Create (save as draft)',
|
|
864
|
+
'engine.studio.saveDraft': 'Save draft',
|
|
865
|
+
'engine.studio.data.savedDraft': 'Object “{label}” saved as draft',
|
|
866
|
+
'engine.studio.data.lastSaved': 'Saved {time}',
|
|
867
|
+
'engine.studio.publish': 'Publish',
|
|
868
|
+
'engine.studio.loading': 'Loading…',
|
|
869
|
+
'engine.studio.loadFailed': 'Failed to load',
|
|
870
|
+
'engine.studio.unpublishedDraft': 'Unpublished draft',
|
|
871
|
+
'engine.studio.unpublished': 'Unpublished',
|
|
872
|
+
'engine.studio.new': 'New',
|
|
873
|
+
'engine.studio.edit': 'Edit',
|
|
874
|
+
'engine.studio.done': 'Done',
|
|
875
|
+
'engine.studio.close': 'Close',
|
|
876
|
+
'engine.studio.deselect': 'Clear selection',
|
|
877
|
+
'engine.studio.home': 'Back to home',
|
|
878
|
+
// Pillar tab labels
|
|
879
|
+
'engine.studio.pillar.data': 'Data',
|
|
880
|
+
'engine.studio.pillar.automations': 'Automations',
|
|
881
|
+
'engine.studio.pillar.interfaces': 'Interfaces',
|
|
882
|
+
'engine.studio.pillar.access': 'Access',
|
|
883
|
+
// Header · package-level publish + app bridge
|
|
884
|
+
'engine.studio.changes': 'Changes',
|
|
885
|
+
'engine.studio.publishTitle': 'Confirm and publish all pending drafts at once (whole package · one atomic release)',
|
|
886
|
+
'engine.studio.publishNoneTitle': 'No drafts pending publish',
|
|
887
|
+
'engine.studio.publishedAll': 'Published all drafts in this package (one atomic release)',
|
|
888
|
+
'engine.studio.app.open': 'Open app',
|
|
889
|
+
'engine.studio.app.openTitle': 'Open app “{label}” (the published front-end)',
|
|
890
|
+
'engine.studio.app.create': 'Create app',
|
|
891
|
+
'engine.studio.app.noneTitle': 'This package has no app (front-end) yet — create one',
|
|
892
|
+
'engine.studio.app.willOpenAfterPublish': 'After publishing, this becomes “Open app”',
|
|
893
|
+
'engine.studio.app.pending': 'App “{label}” pending publish',
|
|
894
|
+
'engine.studio.app.namePlaceholder': 'App name (e.g. Order Center)',
|
|
895
|
+
'engine.studio.app.idPlaceholder': 'Identifier (e.g. orders_app)',
|
|
896
|
+
'engine.studio.app.savedDraft': 'App “{label}” saved as draft — open it after publishing',
|
|
897
|
+
// Package switcher
|
|
898
|
+
'engine.studio.pkg.switchTitle': 'Switch / create package',
|
|
899
|
+
'engine.studio.pkg.readonly': 'Read-only',
|
|
900
|
+
'engine.studio.pkg.readonlyHint': 'Read-only package — switch to or create a writable package to edit.',
|
|
901
|
+
'engine.studio.app.scaffoldNav': "Add this package's objects as menu items",
|
|
902
|
+
'engine.studio.landing.title': 'App Builder',
|
|
903
|
+
'engine.studio.landing.description': 'Design objects, forms, automations and interfaces inside a writable package; edits save as drafts and the whole package publishes in one release. Code-loaded packages are read-only (browse only).',
|
|
904
|
+
'engine.studio.landing.mineHeading': 'My packages (writable)',
|
|
905
|
+
'engine.studio.landing.noneWritable': 'No writable packages yet — create one to start.',
|
|
906
|
+
'engine.studio.landing.dup': 'Duplicate',
|
|
907
|
+
'engine.studio.landing.dupTitle': 'Duplicate this package into a new writable copy (like “duplicate base”)',
|
|
908
|
+
'engine.studio.landing.dupDefaultName': '{name} copy',
|
|
909
|
+
'engine.studio.landing.dupNamePlaceholder': 'Copy name',
|
|
910
|
+
'engine.studio.landing.dupIdPlaceholder': 'Copy package ID',
|
|
911
|
+
'engine.studio.landing.dupGo': 'Duplicate and open the builder',
|
|
912
|
+
'engine.studio.landing.dupCreated': 'Duplicated into writable package “{name}”',
|
|
913
|
+
'engine.studio.landing.createGo': 'Create and start building',
|
|
914
|
+
'engine.studio.landing.installedHeading': 'Installed (read-only · browsable)',
|
|
915
|
+
'engine.studio.designer.search': 'Search…',
|
|
916
|
+
'engine.studio.designer.select': 'Select…',
|
|
917
|
+
'engine.studio.designer.pickDate': 'Pick a date…',
|
|
918
|
+
'engine.studio.designer.fieldAria': '{label} — click to edit properties, drag to reorder',
|
|
919
|
+
'engine.studio.designer.groupUp': 'Move group up',
|
|
920
|
+
'engine.studio.designer.groupDown': 'Move group down',
|
|
921
|
+
'engine.studio.designer.groupDelete': 'Delete group',
|
|
922
|
+
'engine.studio.designer.groupDeleteTitle': 'Delete group (its fields move to Ungrouped)',
|
|
923
|
+
'engine.studio.designer.dropHere': 'Drag fields here',
|
|
924
|
+
'engine.studio.designer.ungrouped': 'Ungrouped',
|
|
925
|
+
'engine.studio.designer.newGroup': 'New group',
|
|
926
|
+
'engine.studio.designer.hint': 'Drag to reorder / move across groups · click a field to edit its properties',
|
|
927
|
+
'engine.studio.designer.addGroup': 'Add group',
|
|
928
|
+
'engine.studio.rules.title': 'Validation rules',
|
|
929
|
+
'engine.studio.rules.none': 'No validation rules yet.',
|
|
930
|
+
'engine.studio.rules.explain': 'Rules run when a record is saved: when the condition is true, the save is rejected with the message.',
|
|
931
|
+
'engine.studio.rules.noMessage': '(no message)',
|
|
932
|
+
'engine.studio.rules.pick': 'Select a rule on the left, or click “New” to create one.',
|
|
933
|
+
'engine.studio.rules.structured': '“{type}” rules carry structured configuration (state-machine transitions / format constraints etc.) and cannot be edited here yet — maintain them in the code package. Message: {message}',
|
|
934
|
+
'engine.studio.rules.none2': '(none)',
|
|
935
|
+
'engine.studio.rules.deleteRule': 'Delete rule',
|
|
936
|
+
'engine.studio.rules.nameLabel': 'Rule name (snake_case, unique)',
|
|
937
|
+
'engine.studio.rules.messageLabel': 'Error message (shown to the user when validation fails)',
|
|
938
|
+
'engine.studio.rules.messagePlaceholder': 'e.g. Completion date is required when status is Done',
|
|
939
|
+
'engine.studio.rules.celPre': 'Fail condition (CEL) — when the condition is ',
|
|
940
|
+
'engine.studio.rules.celTrue': 'true',
|
|
941
|
+
'engine.studio.rules.celMid': ', the save is rejected with the message above; new rules default to ',
|
|
942
|
+
'engine.studio.rules.celPost': ' (never fires) — replace it with a real condition.',
|
|
943
|
+
'engine.studio.rules.severity': 'Severity',
|
|
944
|
+
'engine.studio.rules.severityError': 'error (rejects the save)',
|
|
945
|
+
'engine.studio.rules.enabled': 'Enabled',
|
|
946
|
+
'engine.studio.rules.delete': 'Delete',
|
|
947
|
+
'engine.studio.settings.basics': 'Basics',
|
|
948
|
+
'engine.studio.settings.noInspector': 'No default object inspector registered.',
|
|
949
|
+
'engine.studio.settings.semanticRoles': 'Semantic roles',
|
|
950
|
+
'engine.studio.settings.semanticHint': 'Applied consistently across forms, lists and detail pages (ADR-0085)',
|
|
951
|
+
'engine.studio.settings.nameField': 'Record name field (nameField) — shown in titles, links and references',
|
|
952
|
+
'engine.studio.settings.autoDerive': '(auto-derived)',
|
|
953
|
+
'engine.studio.settings.stageField': 'Lifecycle field (stageField) — the detail page progress bar renders its options',
|
|
954
|
+
'engine.studio.settings.autoDetect': '(auto-detect status/stage-like field names)',
|
|
955
|
+
'engine.studio.settings.stageNone': 'None — this object has no linear flow; hide the progress bar',
|
|
956
|
+
'engine.studio.settings.highlightFields': 'Highlight fields (highlightFields) — default list columns, cards and detail header take the first 4; order is display order',
|
|
957
|
+
'engine.studio.settings.removeField': 'Remove {field}',
|
|
958
|
+
'engine.studio.settings.addFieldOption': '+ Add field…',
|
|
959
|
+
'engine.studio.settings.undeclared': '(not declared — surfaces pick heuristically)',
|
|
960
|
+
'engine.studio.pkg.writable': 'Writable',
|
|
961
|
+
'engine.studio.pkg.heading': 'Packages (apps)',
|
|
962
|
+
'engine.studio.pkg.none': 'No app packages yet',
|
|
963
|
+
'engine.studio.pkg.namePlaceholder': 'Name (e.g. Repair Center)',
|
|
964
|
+
'engine.studio.pkg.idPlaceholder': 'Package ID (e.g. com.example.repairs)',
|
|
965
|
+
'engine.studio.pkg.idStrippedNotice': 'Unsupported characters were removed — allowed: lowercase letters, digits, dots, hyphens, underscores',
|
|
966
|
+
'engine.studio.pkg.idFormatHint': 'Use a reverse-domain identifier with at least one dot, e.g. com.example.myapp',
|
|
967
|
+
'engine.studio.pkg.idFromNameUnavailable': 'No identifier could be suggested from this name — type one below (e.g. com.example.myapp)',
|
|
968
|
+
'engine.studio.pkg.createWritable': 'Create writable package',
|
|
969
|
+
'engine.studio.pkg.new': 'New package (writable base)',
|
|
970
|
+
'engine.studio.pkg.created': 'Package {name} created (writable)',
|
|
971
|
+
// Nav item inspector (Interfaces pillar)
|
|
972
|
+
'engine.studio.nav.selectItem': 'Select a menu item on the left.',
|
|
973
|
+
'engine.studio.nav.label': 'Label',
|
|
974
|
+
'engine.studio.nav.labelPlaceholder': 'e.g. Positions',
|
|
975
|
+
'engine.studio.nav.linkObject': 'Link to object',
|
|
976
|
+
'engine.studio.nav.chooseObject': '— Choose object —',
|
|
977
|
+
'engine.studio.nav.boundHint': 'This menu item opens that object’s record list.',
|
|
978
|
+
'engine.studio.nav.unboundHint': 'Choose an object; the menu item will open its record list.',
|
|
979
|
+
'engine.studio.nav.noObjects': 'This package has no objects yet — create one in the Data pillar first.',
|
|
980
|
+
// Interfaces pillar
|
|
981
|
+
'engine.studio.if.pickLeft': 'Select a menu item on the left',
|
|
982
|
+
'engine.studio.if.navHeading': '{app} · Navigation',
|
|
983
|
+
'engine.studio.if.editNavTitle': 'Edit navigation (drag to reorder / rename / add-remove)',
|
|
984
|
+
'engine.studio.if.doneEditTitle': 'Done editing',
|
|
985
|
+
'engine.studio.if.noApp': 'This package has no app yet.',
|
|
986
|
+
'engine.studio.if.noNavItems': 'No nav items yet — (click “Edit” above to add)',
|
|
987
|
+
'engine.studio.if.previewIsRuntime': 'Preview = runtime · same renderer',
|
|
988
|
+
'engine.studio.if.noAppTitle': 'This package has no app yet',
|
|
989
|
+
'engine.studio.if.noAppHint': 'Create an app to design its navigation and interfaces.',
|
|
990
|
+
'engine.studio.if.readonlyPreview': '{type} shows a read-only preview for now; design support is in progress.',
|
|
991
|
+
'engine.studio.if.editHint': 'Click a block → edit on the right · then “Save draft” → “Publish”',
|
|
992
|
+
'engine.studio.if.objectHintPre': 'Runtime list preview · edit fields / structure in the ',
|
|
993
|
+
'engine.studio.if.objectHintPost': ' pillar',
|
|
994
|
+
'engine.studio.inspector.props': 'Properties',
|
|
995
|
+
'engine.studio.inspector.emptyLine1': 'Click a block on the canvas,',
|
|
996
|
+
'engine.studio.inspector.emptyLine2': 'and edit its properties right here.',
|
|
997
|
+
// Data pillar
|
|
998
|
+
'engine.studio.data.newFieldLabel': 'New field',
|
|
999
|
+
'engine.studio.data.nameFieldLabel': 'Name',
|
|
1000
|
+
'engine.studio.data.idExists': 'Identifier “{name}” already exists',
|
|
1001
|
+
'engine.studio.data.fieldCount': '{count} fields',
|
|
1002
|
+
'engine.studio.data.pickObject': 'Select an object',
|
|
1003
|
+
'engine.studio.data.objects': 'Objects',
|
|
1004
|
+
'engine.studio.data.searchObjects': 'Search objects…',
|
|
1005
|
+
'engine.studio.data.noObjects': 'No objects yet — create one below to start',
|
|
1006
|
+
'engine.studio.data.labelPlaceholder': 'Display name (e.g. Repair Ticket)',
|
|
1007
|
+
'engine.studio.data.idPlaceholder': 'Identifier (e.g. repair_ticket)',
|
|
1008
|
+
'engine.studio.data.newObject': 'New object',
|
|
1009
|
+
'engine.studio.data.readOnlyPackage': 'This package is read-only — switch to or create a writable package to add objects',
|
|
1010
|
+
'engine.studio.data.firstObjectTitle': 'Start with your first object',
|
|
1011
|
+
'engine.studio.data.firstObjectHint': 'Objects are your app’s data foundation (e.g. “Orders”, “Customers”). Enter a display name and identifier at the bottom-left to create one; then design its fields, forms, and automations, and publish once at the end.',
|
|
1012
|
+
'engine.studio.data.tab.records': 'Records',
|
|
1013
|
+
'engine.studio.data.tab.form': 'Form',
|
|
1014
|
+
'engine.studio.data.tab.rules': 'Validations',
|
|
1015
|
+
'engine.studio.data.tab.settings': 'Settings',
|
|
1016
|
+
'engine.studio.data.badge.grid': 'Runtime list · same renderer',
|
|
1017
|
+
'engine.studio.data.badge.rules': 'Validation rules · draft',
|
|
1018
|
+
'engine.studio.data.badge.settings': 'Object settings · draft',
|
|
1019
|
+
'engine.studio.data.badge.formLayout': 'Form design · draft',
|
|
1020
|
+
'engine.studio.data.badge.formPreview': 'Runtime form · published definition',
|
|
1021
|
+
'engine.studio.data.addFieldTitle': 'Add a field (then set its type and properties on the right)',
|
|
1022
|
+
'engine.studio.data.addField': 'Add field',
|
|
1023
|
+
'engine.studio.data.editFieldProps': 'Edit field properties',
|
|
1024
|
+
'engine.studio.data.draftObjectTitle': 'Unpublished new object',
|
|
1025
|
+
'engine.studio.data.draftObjectHint': 'The Records grid queries real data, but this object has no table until it’s published. Design fields and groups in “Form · Layout” first, then click “Publish” in the top bar — after publishing, this becomes its live data grid.',
|
|
1026
|
+
'engine.studio.data.goDesignFields': 'Go to “Form · Layout” to design fields',
|
|
1027
|
+
'engine.studio.data.gridHint': 'Column “+” adds a field · pencil edits properties · drag a header to reorder · then “Save draft” → “Publish”',
|
|
1028
|
+
'engine.studio.data.form.layout': 'Layout',
|
|
1029
|
+
'engine.studio.data.form.preview': 'Preview',
|
|
1030
|
+
'engine.studio.data.form.layoutBadge': 'Layout designer · draft (includes unpublished changes)',
|
|
1031
|
+
'engine.studio.data.form.previewBadge': 'Runtime form · published definition',
|
|
1032
|
+
'engine.studio.data.form.previewWarn': 'You have unpublished changes — this preview shows the pre-publish (published) state; confirm the draft in “Layout”, and to see the post-publish result, click “Publish” in the top bar first.',
|
|
1033
|
+
'engine.studio.data.form.noPublishedTitle': 'No published definition yet',
|
|
1034
|
+
'engine.studio.data.form.noPublishedHint': '“Preview” renders the published runtime form, but this object isn’t published yet. Confirm the draft in “Layout”, then click “Publish” in the top bar to preview.',
|
|
1035
|
+
'engine.studio.data.formHint': 'Click any field → edit properties on the right · “Add field” adds a field · then “Save draft” → “Publish”',
|
|
1036
|
+
'engine.studio.data.fieldProps': 'Field properties',
|
|
1037
|
+
// Automations pillar
|
|
1038
|
+
'engine.studio.auto.nodeStart': 'Start',
|
|
1039
|
+
'engine.studio.auto.nodeEnd': 'End',
|
|
1040
|
+
'engine.studio.auto.savedDraft': 'Automation “{label}” saved as draft',
|
|
1041
|
+
'engine.studio.auto.defaultOff': 'Off by default · review before enabling',
|
|
1042
|
+
'engine.studio.auto.heading': 'Automations · flow',
|
|
1043
|
+
'engine.studio.auto.on': 'On',
|
|
1044
|
+
'engine.studio.auto.off': 'Off',
|
|
1045
|
+
'engine.studio.auto.offTitle': 'Disabled — will not run',
|
|
1046
|
+
'engine.studio.auto.onBound': 'Enabled · bound to its trigger',
|
|
1047
|
+
'engine.studio.auto.onUnbound': 'Enabled · no trigger (run manually)',
|
|
1048
|
+
'engine.studio.auto.enabled': 'Enabled',
|
|
1049
|
+
'engine.studio.auto.disabled': 'Disabled',
|
|
1050
|
+
'engine.studio.auto.enableTitle': 'Enable this automation (publish to apply)',
|
|
1051
|
+
'engine.studio.auto.disableTitle': 'Disable this automation (publish to apply)',
|
|
1052
|
+
'engine.studio.auto.enabledToast': 'Enabled — publish to apply',
|
|
1053
|
+
'engine.studio.auto.disabledToast': 'Disabled — publish to apply',
|
|
1054
|
+
'engine.studio.auto.newTitle': 'New automation',
|
|
1055
|
+
'engine.studio.auto.none': 'No automations yet — click “New” to start',
|
|
1056
|
+
'engine.studio.auto.namePlaceholder': 'Name (e.g. Offer Notice)',
|
|
1057
|
+
'engine.studio.auto.idPlaceholder': 'Identifier (e.g. offer_notice)',
|
|
1058
|
+
'engine.studio.auto.canvasHint': 'Visual orchestration · click a node to configure',
|
|
1059
|
+
'engine.studio.auto.pick': 'Select an automation',
|
|
1060
|
+
'engine.studio.auto.editHint': 'Click a node → configure on the right · then “Save draft” → “Publish”',
|
|
1061
|
+
'engine.studio.auto.config': 'Configuration',
|
|
1062
|
+
'engine.studio.auto.emptyLine1': 'Click a node on the canvas,',
|
|
1063
|
+
'engine.studio.auto.emptyLine2': 'and its configuration appears here.',
|
|
1064
|
+
// Access pillar
|
|
1065
|
+
'engine.studio.access.created': 'Permission set “{label}” created',
|
|
1066
|
+
'engine.studio.access.title': 'Permission matrix',
|
|
1067
|
+
'engine.studio.access.subtitle': 'Objects × CRUD · field-level R/W',
|
|
1068
|
+
'engine.studio.access.bannerTitle': 'This matrix lists only the objects this package declares, and “Save” merges just that slice — grants contributed by other packages are preserved. Edits are saved as package drafts and go live when you Publish the package (top bar), exactly like Data and Interfaces.',
|
|
1069
|
+
'engine.studio.access.banner': 'This package’s objects · saved as draft',
|
|
1070
|
+
'engine.studio.access.heading': 'Permission sets / Profiles',
|
|
1071
|
+
'engine.studio.access.search': 'Search permissions…',
|
|
1072
|
+
'engine.studio.access.none': 'No permission sets yet — create one below',
|
|
1073
|
+
'engine.studio.access.labelPlaceholder': 'Display name (e.g. Sales permissions)',
|
|
1074
|
+
'engine.studio.access.idPlaceholder': 'Identifier (e.g. sales_perms)',
|
|
1075
|
+
'engine.studio.access.new': 'New permission set',
|
|
1076
|
+
'engine.studio.access.emptyMain': 'Create a permission set to start configuring',
|
|
1077
|
+
'engine.studio.access.pick': 'Select a permission set',
|
|
1078
|
+
// ── AppNavCanvas (nav-tree editor, used by Studio + AppPreview) ─────────
|
|
1079
|
+
'engine.appNav.heading': 'Navigation',
|
|
1080
|
+
'engine.appNav.addItem': 'Add nav item',
|
|
1081
|
+
'engine.appNav.removeItem': 'Remove nav item',
|
|
1082
|
+
'engine.appNav.empty': 'Empty — click “Add nav item” to start',
|
|
1083
|
+
'engine.appNav.emptyReadonly': 'No top-level nav items yet',
|
|
1084
|
+
'engine.appNav.newItem': 'New item',
|
|
1085
|
+
'engine.appNav.itemOne': 'item',
|
|
1086
|
+
'engine.appNav.itemOther': 'items',
|
|
808
1087
|
};
|
|
809
1088
|
const ENGINE_STRINGS_ZH = {
|
|
810
1089
|
'engine.package.writableRequired': '请先选择或新建一个可写的基座(package)——只读的代码包中无法新建该项。',
|
|
@@ -1040,10 +1319,38 @@ const ENGINE_STRINGS_ZH = {
|
|
|
1040
1319
|
'engine.inspector.appNav.kind': '导航项',
|
|
1041
1320
|
'engine.inspector.appNav.close': '关闭导航项',
|
|
1042
1321
|
'engine.inspector.appNav.label': '名称',
|
|
1043
|
-
'engine.inspector.appNav.path': '路径 / 路由',
|
|
1044
1322
|
'engine.inspector.appNav.icon': '图标',
|
|
1045
|
-
'engine.inspector.appNav.kindField': '类型',
|
|
1046
1323
|
'engine.inspector.appNav.remove': '删除导航项',
|
|
1324
|
+
'engine.inspector.appNav.typeField': '类型',
|
|
1325
|
+
'engine.inspector.appNav.type.object': '对象',
|
|
1326
|
+
'engine.inspector.appNav.type.page': '页面',
|
|
1327
|
+
'engine.inspector.appNav.type.dashboard': '仪表盘',
|
|
1328
|
+
'engine.inspector.appNav.type.report': '报表',
|
|
1329
|
+
'engine.inspector.appNav.type.url': '链接(URL)',
|
|
1330
|
+
'engine.inspector.appNav.type.group': '分组',
|
|
1331
|
+
'engine.inspector.appNav.object': '对象',
|
|
1332
|
+
'engine.inspector.appNav.targetMode': '落点',
|
|
1333
|
+
'engine.inspector.appNav.mode.default': '默认视图(工作台)',
|
|
1334
|
+
'engine.inspector.appNav.mode.view': '具名视图',
|
|
1335
|
+
'engine.inspector.appNav.mode.record': '记录深链',
|
|
1336
|
+
'engine.inspector.appNav.mode.filters': '参数化切面(/data)',
|
|
1337
|
+
'engine.inspector.appNav.view': '视图',
|
|
1338
|
+
'engine.inspector.appNav.recordId': '记录 ID',
|
|
1339
|
+
'engine.inspector.appNav.recordIdHint': '支持 {current_user_id} 与 {current_org_id} 模板变量。',
|
|
1340
|
+
'engine.inspector.appNav.recordMode': '打开方式',
|
|
1341
|
+
'engine.inspector.appNav.recordModeView': '查看',
|
|
1342
|
+
'engine.inspector.appNav.recordModeEdit': '编辑',
|
|
1343
|
+
'engine.inspector.appNav.filters': 'URL 过滤条件',
|
|
1344
|
+
'engine.inspector.appNav.filtersField': '字段',
|
|
1345
|
+
'engine.inspector.appNav.filtersValue': '值',
|
|
1346
|
+
'engine.inspector.appNav.filtersAdd': '添加条件',
|
|
1347
|
+
'engine.inspector.appNav.filtersRemove': '移除条件',
|
|
1348
|
+
'engine.inspector.appNav.filtersHint': '一次性切面由 URL 承载——当它值得沉淀复用时,请改建具名视图。',
|
|
1349
|
+
'engine.inspector.appNav.url': '链接地址',
|
|
1350
|
+
'engine.inspector.appNav.urlTarget': '打开位置',
|
|
1351
|
+
'engine.inspector.appNav.urlTargetSelf': '当前标签页',
|
|
1352
|
+
'engine.inspector.appNav.urlTargetBlank': '新标签页',
|
|
1353
|
+
'engine.inspector.appNav.preview': '运行期落点',
|
|
1047
1354
|
// View column inspector
|
|
1048
1355
|
'engine.inspector.viewColumn.kind': '列',
|
|
1049
1356
|
'engine.inspector.viewColumn.close': '关闭列',
|
|
@@ -1241,9 +1548,10 @@ const ENGINE_STRINGS_ZH = {
|
|
|
1241
1548
|
'engine.packages.col.version': '版本',
|
|
1242
1549
|
'engine.packages.col.scope': '范围',
|
|
1243
1550
|
'engine.packages.col.status': '状态',
|
|
1244
|
-
'engine.packages.scope.project': '
|
|
1551
|
+
'engine.packages.scope.project': '只读 · 代码包',
|
|
1245
1552
|
'engine.packages.scope.system': '系统',
|
|
1246
1553
|
'engine.packages.scope.cloud': '云端',
|
|
1554
|
+
'engine.packages.scope.writable': '可写',
|
|
1247
1555
|
'engine.packages.status.enabled': '已启用',
|
|
1248
1556
|
'engine.packages.status.disabled': '已禁用',
|
|
1249
1557
|
'engine.packages.import.invalidJson': '所选文件不是有效 JSON。',
|
|
@@ -1498,6 +1806,234 @@ const ENGINE_STRINGS_ZH = {
|
|
|
1498
1806
|
// AI assistant entry points
|
|
1499
1807
|
'designer.canvas.askAi': '问 AI',
|
|
1500
1808
|
'designer.canvas.askAiGenerate': '用 AI 生成字段',
|
|
1809
|
+
// ── StudioDesignSurface (ADR-0080 WYSIWYG design surface) ──────────────
|
|
1810
|
+
// Shared chrome
|
|
1811
|
+
'engine.studio.cancel': '取消',
|
|
1812
|
+
'engine.studio.create': '创建',
|
|
1813
|
+
'engine.studio.createDraft': '创建(存为草稿)',
|
|
1814
|
+
'engine.studio.saveDraft': '保存草稿',
|
|
1815
|
+
'engine.studio.data.savedDraft': '对象「{label}」已存为草稿',
|
|
1816
|
+
'engine.studio.data.lastSaved': '已于 {time} 保存',
|
|
1817
|
+
'engine.studio.publish': '发布',
|
|
1818
|
+
'engine.studio.loading': '加载中…',
|
|
1819
|
+
'engine.studio.loadFailed': '加载失败',
|
|
1820
|
+
'engine.studio.unpublishedDraft': '未发布草稿',
|
|
1821
|
+
'engine.studio.unpublished': '未发布',
|
|
1822
|
+
'engine.studio.new': '新建',
|
|
1823
|
+
'engine.studio.edit': '编辑',
|
|
1824
|
+
'engine.studio.done': '完成',
|
|
1825
|
+
'engine.studio.close': '关闭',
|
|
1826
|
+
'engine.studio.deselect': '取消选择',
|
|
1827
|
+
'engine.studio.home': '返回主页',
|
|
1828
|
+
// Pillar tab labels
|
|
1829
|
+
'engine.studio.pillar.data': '数据',
|
|
1830
|
+
'engine.studio.pillar.automations': '自动化',
|
|
1831
|
+
'engine.studio.pillar.interfaces': '界面',
|
|
1832
|
+
'engine.studio.pillar.access': '权限',
|
|
1833
|
+
// Header · package-level publish + app bridge
|
|
1834
|
+
'engine.studio.changes': '变更',
|
|
1835
|
+
'engine.studio.publishTitle': '一次性确认并发布全部待发布草稿(整包 · 一次原子发布)',
|
|
1836
|
+
'engine.studio.publishNoneTitle': '没有待发布的草稿',
|
|
1837
|
+
'engine.studio.publishedAll': '已发布本软件包的全部草稿(一次原子发布)',
|
|
1838
|
+
'engine.studio.app.open': '打开应用',
|
|
1839
|
+
'engine.studio.app.openTitle': '打开应用「{label}」(发布后的前端界面)',
|
|
1840
|
+
'engine.studio.app.create': '创建应用',
|
|
1841
|
+
'engine.studio.app.noneTitle': '这个软件包还没有应用(前端界面)— 创建一个',
|
|
1842
|
+
'engine.studio.app.willOpenAfterPublish': '发布后这里会变成「打开应用」',
|
|
1843
|
+
'engine.studio.app.pending': '应用「{label}」待发布',
|
|
1844
|
+
'engine.studio.app.namePlaceholder': '应用名称(如:订单中心)',
|
|
1845
|
+
'engine.studio.app.idPlaceholder': '标识符(如:orders_app)',
|
|
1846
|
+
'engine.studio.app.savedDraft': '应用「{label}」已存为草稿 — 发布后即可打开',
|
|
1847
|
+
// Package switcher
|
|
1848
|
+
'engine.studio.pkg.switchTitle': '切换 / 新建软件包',
|
|
1849
|
+
'engine.studio.pkg.readonly': '只读',
|
|
1850
|
+
'engine.studio.pkg.readonlyHint': '只读软件包 — 请切换或新建可写软件包后再编辑。',
|
|
1851
|
+
'engine.studio.app.scaffoldNav': '将本包的对象添加为菜单项',
|
|
1852
|
+
'engine.studio.landing.title': '应用构建',
|
|
1853
|
+
'engine.studio.landing.description': '在一个可写软件包里设计对象、表单、自动化与界面;编辑存为草稿,整包一次发布。源码加载的软件包为只读(仅可浏览)。',
|
|
1854
|
+
'engine.studio.landing.mineHeading': '我的软件包(可写)',
|
|
1855
|
+
'engine.studio.landing.noneWritable': '还没有可写软件包 — 新建一个开始。',
|
|
1856
|
+
'engine.studio.landing.dup': '复制',
|
|
1857
|
+
'engine.studio.landing.dupTitle': '复制这个软件包为新的可写副本(类似 duplicate base)',
|
|
1858
|
+
'engine.studio.landing.dupDefaultName': '{name} 副本',
|
|
1859
|
+
'engine.studio.landing.dupNamePlaceholder': '副本名称',
|
|
1860
|
+
'engine.studio.landing.dupIdPlaceholder': '副本包 ID',
|
|
1861
|
+
'engine.studio.landing.dupGo': '复制并进入构建器',
|
|
1862
|
+
'engine.studio.landing.dupCreated': '已复制为可写软件包「{name}」',
|
|
1863
|
+
'engine.studio.landing.createGo': '创建并开始构建',
|
|
1864
|
+
'engine.studio.landing.installedHeading': '已安装(只读 · 可浏览)',
|
|
1865
|
+
'engine.studio.designer.search': '搜索…',
|
|
1866
|
+
'engine.studio.designer.select': '请选择…',
|
|
1867
|
+
'engine.studio.designer.pickDate': '选择日期…',
|
|
1868
|
+
'engine.studio.designer.fieldAria': '{label} — 点选改属性,拖动排序',
|
|
1869
|
+
'engine.studio.designer.groupUp': '上移分组',
|
|
1870
|
+
'engine.studio.designer.groupDown': '下移分组',
|
|
1871
|
+
'engine.studio.designer.groupDelete': '删除分组',
|
|
1872
|
+
'engine.studio.designer.groupDeleteTitle': '删除分组(字段归为未分组)',
|
|
1873
|
+
'engine.studio.designer.dropHere': '拖字段到这里',
|
|
1874
|
+
'engine.studio.designer.ungrouped': '未分组',
|
|
1875
|
+
'engine.studio.designer.newGroup': '新分组',
|
|
1876
|
+
'engine.studio.designer.hint': '拖动字段排序 / 拖到其它分组 · 点选字段改属性',
|
|
1877
|
+
'engine.studio.designer.addGroup': '添加分组',
|
|
1878
|
+
'engine.studio.rules.title': '验证规则',
|
|
1879
|
+
'engine.studio.rules.none': '还没有验证规则。',
|
|
1880
|
+
'engine.studio.rules.explain': '规则在保存记录时执行:条件为真 ⇒ 拒绝保存并提示消息。',
|
|
1881
|
+
'engine.studio.rules.noMessage': '(无消息)',
|
|
1882
|
+
'engine.studio.rules.pick': '选择左侧的规则进行编辑,或点「新增」创建一条。',
|
|
1883
|
+
'engine.studio.rules.structured': '「{type}」类型的规则带有结构化配置(状态机转移表 / 格式约束等),暂不支持在此编辑 —— 请在代码包中维护。消息:{message}',
|
|
1884
|
+
'engine.studio.rules.none2': '(无)',
|
|
1885
|
+
'engine.studio.rules.deleteRule': '删除规则',
|
|
1886
|
+
'engine.studio.rules.nameLabel': '规则名(snake_case,唯一)',
|
|
1887
|
+
'engine.studio.rules.messageLabel': '错误消息(校验失败时展示给用户)',
|
|
1888
|
+
'engine.studio.rules.messagePlaceholder': '例如:完成日期在状态为已完成时必填',
|
|
1889
|
+
'engine.studio.rules.celPre': '失败条件(CEL)—— 条件为 ',
|
|
1890
|
+
'engine.studio.rules.celTrue': '真',
|
|
1891
|
+
'engine.studio.rules.celMid': ' 时,拒绝保存并显示上面的消息;新规则默认 ',
|
|
1892
|
+
'engine.studio.rules.celPost': ' (永不触发),请改为真实条件。',
|
|
1893
|
+
'engine.studio.rules.severity': '严重度',
|
|
1894
|
+
'engine.studio.rules.severityError': 'error(拒绝保存)',
|
|
1895
|
+
'engine.studio.rules.enabled': '启用',
|
|
1896
|
+
'engine.studio.rules.delete': '删除',
|
|
1897
|
+
'engine.studio.settings.basics': '基础信息',
|
|
1898
|
+
'engine.studio.settings.noInspector': '未注册对象默认检查器。',
|
|
1899
|
+
'engine.studio.settings.semanticRoles': '语义角色',
|
|
1900
|
+
'engine.studio.settings.semanticHint': '跨表单 / 列表 / 详情统一生效(ADR-0085)',
|
|
1901
|
+
'engine.studio.settings.nameField': '记录名称字段(nameField)—— 标题、链接、引用处显示的字段',
|
|
1902
|
+
'engine.studio.settings.autoDerive': '(自动推导)',
|
|
1903
|
+
'engine.studio.settings.stageField': '生命周期字段(stageField)—— 详情页顶部进度条按它的选项渲染',
|
|
1904
|
+
'engine.studio.settings.autoDetect': '(自动探测 status/stage 等字段名)',
|
|
1905
|
+
'engine.studio.settings.stageNone': '无 —— 这个对象没有线性流程,不显示进度条',
|
|
1906
|
+
'engine.studio.settings.highlightFields': '重点字段(highlightFields)—— 默认列表列、卡片、详情顶栏取前 4;顺序即展示顺序',
|
|
1907
|
+
'engine.studio.settings.removeField': '移除 {field}',
|
|
1908
|
+
'engine.studio.settings.addFieldOption': '+ 添加字段…',
|
|
1909
|
+
'engine.studio.settings.undeclared': '(未声明 —— 各处按启发式自动挑选)',
|
|
1910
|
+
'engine.studio.pkg.writable': '可写',
|
|
1911
|
+
'engine.studio.pkg.heading': '软件包(应用)',
|
|
1912
|
+
'engine.studio.pkg.none': '暂无应用软件包',
|
|
1913
|
+
'engine.studio.pkg.namePlaceholder': '名称(如:维修中心)',
|
|
1914
|
+
'engine.studio.pkg.idPlaceholder': '包 ID(如:com.example.repairs)',
|
|
1915
|
+
'engine.studio.pkg.idStrippedNotice': '已移除不支持的字符——仅允许小写字母、数字、点、连字符和下划线',
|
|
1916
|
+
'engine.studio.pkg.idFormatHint': '请使用带至少一个点的反向域名标识,如 com.example.myapp',
|
|
1917
|
+
'engine.studio.pkg.idFromNameUnavailable': '无法从该名称生成标识,请在下方手动输入(如 com.example.myapp)',
|
|
1918
|
+
'engine.studio.pkg.createWritable': '创建可写软件包',
|
|
1919
|
+
'engine.studio.pkg.new': '新建软件包(可写 base)',
|
|
1920
|
+
'engine.studio.pkg.created': '软件包 {name} 已创建(可写)',
|
|
1921
|
+
// Nav item inspector (Interfaces pillar)
|
|
1922
|
+
'engine.studio.nav.selectItem': '在左侧选择一个菜单项。',
|
|
1923
|
+
'engine.studio.nav.label': '标签',
|
|
1924
|
+
'engine.studio.nav.labelPlaceholder': '如:职位',
|
|
1925
|
+
'engine.studio.nav.linkObject': '链接到对象',
|
|
1926
|
+
'engine.studio.nav.chooseObject': '— 选择对象 —',
|
|
1927
|
+
'engine.studio.nav.boundHint': '这个菜单项会打开该对象的记录列表。',
|
|
1928
|
+
'engine.studio.nav.unboundHint': '选择一个对象,菜单项将打开它的记录列表。',
|
|
1929
|
+
'engine.studio.nav.noObjects': '这个软件包还没有对象 — 先到 Data 支柱创建。',
|
|
1930
|
+
// Interfaces pillar
|
|
1931
|
+
'engine.studio.if.pickLeft': '从左侧选择一个菜单项',
|
|
1932
|
+
'engine.studio.if.navHeading': '{app} · 导航',
|
|
1933
|
+
'engine.studio.if.editNavTitle': '编辑导航(拖拽排序 / 重命名 / 增删)',
|
|
1934
|
+
'engine.studio.if.doneEditTitle': '完成编辑',
|
|
1935
|
+
'engine.studio.if.noApp': '这个软件包还没有应用。',
|
|
1936
|
+
'engine.studio.if.noNavItems': '还没有导航项 —(点上方「编辑」添加)',
|
|
1937
|
+
'engine.studio.if.previewIsRuntime': '预览即运行 · 同一渲染器',
|
|
1938
|
+
'engine.studio.if.noAppTitle': '这个软件包还没有应用',
|
|
1939
|
+
'engine.studio.if.noAppHint': '创建一个应用来设计它的导航与界面。',
|
|
1940
|
+
'engine.studio.if.readonlyPreview': '{type} 暂用只读预览,设计能力建设中。',
|
|
1941
|
+
'engine.studio.if.editHint': '点选积木 → 右侧直接改 · 改完「保存草稿」→「发布」',
|
|
1942
|
+
'engine.studio.if.objectHintPre': '运行态列表预览 · 改字段 / 结构请到 ',
|
|
1943
|
+
'engine.studio.if.objectHintPost': ' 支柱',
|
|
1944
|
+
'engine.studio.inspector.props': '属性',
|
|
1945
|
+
'engine.studio.inspector.emptyLine1': '在画布里点选一个积木,',
|
|
1946
|
+
'engine.studio.inspector.emptyLine2': '它的属性会在这里直接编辑。',
|
|
1947
|
+
// Data pillar
|
|
1948
|
+
'engine.studio.data.newFieldLabel': '新字段',
|
|
1949
|
+
'engine.studio.data.nameFieldLabel': '名称',
|
|
1950
|
+
'engine.studio.data.idExists': '标识符 "{name}" 已存在',
|
|
1951
|
+
'engine.studio.data.fieldCount': '{count} 字段',
|
|
1952
|
+
'engine.studio.data.pickObject': '选择一个对象',
|
|
1953
|
+
'engine.studio.data.objects': '对象',
|
|
1954
|
+
'engine.studio.data.searchObjects': '搜索对象…',
|
|
1955
|
+
'engine.studio.data.noObjects': '还没有对象 — 在下方新建一个开始',
|
|
1956
|
+
'engine.studio.data.labelPlaceholder': '显示名(如:报修工单)',
|
|
1957
|
+
'engine.studio.data.idPlaceholder': '标识符(如:repair_ticket)',
|
|
1958
|
+
'engine.studio.data.newObject': '新建对象',
|
|
1959
|
+
'engine.studio.data.readOnlyPackage': '此包为只读——请切换到或新建一个可写的包后再添加对象',
|
|
1960
|
+
'engine.studio.data.firstObjectTitle': '从第一个对象开始',
|
|
1961
|
+
'engine.studio.data.firstObjectHint': '对象是应用的数据基座(如「订单」「客户」)。在左下角输入显示名与标识符即可创建;之后为它设计字段、表单与自动化,最后一次发布。',
|
|
1962
|
+
'engine.studio.data.tab.records': '记录',
|
|
1963
|
+
'engine.studio.data.tab.form': '表单',
|
|
1964
|
+
'engine.studio.data.tab.rules': '验证',
|
|
1965
|
+
'engine.studio.data.tab.settings': '设置',
|
|
1966
|
+
'engine.studio.data.badge.grid': '运行态列表 · 同一渲染器',
|
|
1967
|
+
'engine.studio.data.badge.rules': '验证规则 · 草稿',
|
|
1968
|
+
'engine.studio.data.badge.settings': '对象设置 · 草稿',
|
|
1969
|
+
'engine.studio.data.badge.formLayout': '表单设计 · 草稿',
|
|
1970
|
+
'engine.studio.data.badge.formPreview': '运行态表单 · 已发布定义',
|
|
1971
|
+
'engine.studio.data.addFieldTitle': '添加一个字段(随后在右侧设置类型与属性)',
|
|
1972
|
+
'engine.studio.data.addField': '添加字段',
|
|
1973
|
+
'engine.studio.data.editFieldProps': '编辑字段属性',
|
|
1974
|
+
'engine.studio.data.draftObjectTitle': '未发布的新对象',
|
|
1975
|
+
'engine.studio.data.draftObjectHint': '「记录」网格查询真实数据,而这个对象发布前还没有数据表。请先在「表单 · 布局」里设计字段与分组,然后点顶栏「发布」— 发布后这里就是它的实时数据网格。',
|
|
1976
|
+
'engine.studio.data.goDesignFields': '去「表单 · 布局」设计字段',
|
|
1977
|
+
'engine.studio.data.gridHint': '列头「+」加字段 · 笔形改属性 · 拖列头重排 · 改完「保存草稿」→「发布」',
|
|
1978
|
+
'engine.studio.data.form.layout': '布局',
|
|
1979
|
+
'engine.studio.data.form.preview': '预览',
|
|
1980
|
+
'engine.studio.data.form.layoutBadge': '布局设计器 · 草稿(含未发布改动)',
|
|
1981
|
+
'engine.studio.data.form.previewBadge': '运行态表单 · 已发布定义',
|
|
1982
|
+
'engine.studio.data.form.previewWarn': '有未发布改动 — 此预览为发布前(已发布)的效果;草稿确认用「布局」,看发布后效果请先点顶栏「发布」',
|
|
1983
|
+
'engine.studio.data.form.noPublishedTitle': '尚无已发布定义',
|
|
1984
|
+
'engine.studio.data.form.noPublishedHint': '「预览」渲染已发布的运行态表单,而这个对象还未发布。在「布局」里确认草稿,点顶栏「发布」后即可预览。',
|
|
1985
|
+
'engine.studio.data.formHint': '点选任意字段 → 右侧改属性 · 「添加字段」加字段 · 改完「保存草稿」→「发布」',
|
|
1986
|
+
'engine.studio.data.fieldProps': '字段属性',
|
|
1987
|
+
// Automations pillar
|
|
1988
|
+
'engine.studio.auto.nodeStart': '开始',
|
|
1989
|
+
'engine.studio.auto.nodeEnd': '结束',
|
|
1990
|
+
'engine.studio.auto.savedDraft': '自动化「{label}」已存为草稿',
|
|
1991
|
+
'engine.studio.auto.defaultOff': '默认 OFF · 审阅后再启用',
|
|
1992
|
+
'engine.studio.auto.heading': '自动化 · flow',
|
|
1993
|
+
'engine.studio.auto.on': '已启用',
|
|
1994
|
+
'engine.studio.auto.off': '已停用',
|
|
1995
|
+
'engine.studio.auto.offTitle': '已停用 — 不会运行',
|
|
1996
|
+
'engine.studio.auto.onBound': '已启用 · 已绑定触发器',
|
|
1997
|
+
'engine.studio.auto.onUnbound': '已启用 · 无触发器(手动运行)',
|
|
1998
|
+
'engine.studio.auto.enabled': '已启用',
|
|
1999
|
+
'engine.studio.auto.disabled': '已停用',
|
|
2000
|
+
'engine.studio.auto.enableTitle': '启用此自动化(发布后生效)',
|
|
2001
|
+
'engine.studio.auto.disableTitle': '停用此自动化(发布后生效)',
|
|
2002
|
+
'engine.studio.auto.enabledToast': '已设为启用 — 发布后生效',
|
|
2003
|
+
'engine.studio.auto.disabledToast': '已设为停用 — 发布后生效',
|
|
2004
|
+
'engine.studio.auto.newTitle': '新建自动化',
|
|
2005
|
+
'engine.studio.auto.none': '还没有自动化 — 点「新建」开始',
|
|
2006
|
+
'engine.studio.auto.namePlaceholder': '名称(如:录用通知)',
|
|
2007
|
+
'engine.studio.auto.idPlaceholder': '标识符(如:offer_notice)',
|
|
2008
|
+
'engine.studio.auto.canvasHint': '可视化编排 · 点选节点配置',
|
|
2009
|
+
'engine.studio.auto.pick': '选择一个自动化',
|
|
2010
|
+
'engine.studio.auto.editHint': '点选节点 → 右侧配置 · 改完「保存草稿」→「发布」',
|
|
2011
|
+
'engine.studio.auto.config': '配置',
|
|
2012
|
+
'engine.studio.auto.emptyLine1': '在画布里点选一个节点,',
|
|
2013
|
+
'engine.studio.auto.emptyLine2': '它的配置会在这里显示。',
|
|
2014
|
+
// Access pillar
|
|
2015
|
+
'engine.studio.access.created': '权限集「{label}」已创建',
|
|
2016
|
+
'engine.studio.access.title': '权限矩阵',
|
|
2017
|
+
'engine.studio.access.subtitle': '对象 × CRUD · 字段级读写',
|
|
2018
|
+
'engine.studio.access.bannerTitle': '此矩阵仅列出本包声明的对象,「Save」只合并本包切片 —— 其他包贡献的授权原样保留。编辑保存为软件包草稿,点击顶栏「发布」后随整个包一起生效(与数据、界面一致)。',
|
|
2019
|
+
'engine.studio.access.banner': '仅本包对象 · 保存为草稿',
|
|
2020
|
+
'engine.studio.access.heading': '权限集 / Profile',
|
|
2021
|
+
'engine.studio.access.search': '搜索权限…',
|
|
2022
|
+
'engine.studio.access.none': '还没有权限集 — 在下方新建一个',
|
|
2023
|
+
'engine.studio.access.labelPlaceholder': '显示名(如:销售权限)',
|
|
2024
|
+
'engine.studio.access.idPlaceholder': '标识符(如:sales_perms)',
|
|
2025
|
+
'engine.studio.access.new': '新建权限集',
|
|
2026
|
+
'engine.studio.access.emptyMain': '新建一个权限集开始配置',
|
|
2027
|
+
'engine.studio.access.pick': '选择一个权限集',
|
|
2028
|
+
// ── AppNavCanvas (nav-tree editor, used by Studio + AppPreview) ─────────
|
|
2029
|
+
'engine.appNav.heading': '导航',
|
|
2030
|
+
'engine.appNav.addItem': '添加导航项',
|
|
2031
|
+
'engine.appNav.removeItem': '删除导航项',
|
|
2032
|
+
'engine.appNav.empty': '还没有导航项 — 点「添加导航项」开始',
|
|
2033
|
+
'engine.appNav.emptyReadonly': '还没有顶层导航项',
|
|
2034
|
+
'engine.appNav.newItem': '新菜单项',
|
|
2035
|
+
'engine.appNav.itemOne': '项',
|
|
2036
|
+
'engine.appNav.itemOther': '项',
|
|
1501
2037
|
};
|
|
1502
2038
|
function pickTable(locale) {
|
|
1503
2039
|
const lower = (locale ?? '').toLowerCase();
|
|
@@ -1569,3 +2105,18 @@ export function detectLocale() {
|
|
|
1569
2105
|
return 'zh-CN';
|
|
1570
2106
|
return 'en-US';
|
|
1571
2107
|
}
|
|
2108
|
+
/**
|
|
2109
|
+
* React hook — the Studio/metadata-admin locale derived from the app's ACTIVE
|
|
2110
|
+
* i18n language, collapsed to one of the two locales this catalog ships.
|
|
2111
|
+
*
|
|
2112
|
+
* Prefer this over {@link detectLocale} in components: `detectLocale()` reads
|
|
2113
|
+
* `navigator.language`, which never changes when the user switches languages
|
|
2114
|
+
* in-app via the LocaleSwitcher (that only moves the i18next instance). This
|
|
2115
|
+
* follows the live `useObjectTranslation().language`, so the Studio pillars
|
|
2116
|
+
* re-render in lock-step with the console locale — the same source the rest of
|
|
2117
|
+
* the app (Home, forms, list views) renders from.
|
|
2118
|
+
*/
|
|
2119
|
+
export function useMetadataLocale() {
|
|
2120
|
+
const { language } = useObjectTranslation();
|
|
2121
|
+
return /^zh/i.test(language) ? 'zh-CN' : 'en-US';
|
|
2122
|
+
}
|