Skip to content

Commit 4b59358

Browse files
feat(ui): the remaining Studio inspector strings and the package, form and editor strings move into the studio i18n namespace (#25922 slice S3) (#26815)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8PeP4DzppH3b1kDPCjihHVx)_ Part of #25922 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:Studio 设计器表里剩余的 `engine.inspector.*`(223 键)以及全部 `engine.packages.*`、`engine.form.*`、`engine.edit.*` 从 app-shell 私有表搬进 `@object-ui/i18n` 的 `studio` 命名空间,共 en 551 键、zh 560 键(多出的 9 个 `engine.packages.form.help.*` 按原样保持仅 zh),文案一字未改,调用点不动。 - 为什么改:执行 #25922 裁决 6431032267(Q2 = A,6431234244 维持),这是 (M) 的第 3 片(S3),派单 6447417545。 - 风险与回滚:与前两片相同,zh 用户首次打开这些编辑器时标签先显示英文、zh 分片到达后同一挂载重渲染为中文;回滚即 revert 本 PR,行原样回到 app-shell。 - 先看:`ui/packages/i18n/src/namespaces/studio/zh.ts` 末尾新加的 S3 段(含仅 zh 行的说明),再看 `inspectors/inspectorStrings.studioNamespace-25922.test.ts` 的四个新家族下限与仅 zh 断言。 - 两分钟验证:`cd ui && pnpm run check:i18n-designer-parity && pnpm exec vitest run packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts`,应全绿。 - 需要你做的:无,席位落地。 ## What changes - **Slice S3 of the (M) item.** Every remaining `engine.inspector.*` row and every `engine.packages.*`, `engine.form.*` and `engine.edit.*` row leaves `ENGINE_STRINGS_EN` / `ENGINE_STRINGS_ZH` in `ui/packages/app-shell/src/views/metadata-admin/i18n.ts` and is appended to `STUDIO_EN` / `STUDIO_ZH` in `ui/packages/i18n/src/namespaces/studio/{en,zh}.ts`, text byte-for-byte unchanged: | family | `en` | `zh` | |---|---|---| | `engine.inspector.*` (the rest after S2) | 223 | 223 | | `engine.packages.*` | 133 | 142 | | `engine.form.*` | 98 | 98 | | `engine.edit.*` | 97 | 97 | | **total** | **551** | **560** | Same AST pass as S2 (each property with its leading comment block; a mixed group's comment moves only when the group's first row moves); a heading comment marks the S3 section in each catalogue. After this slice no `engine.inspector.*` row is left in the app-shell table. - **zh-only rows stay zh-only.** The nine `engine.packages.form.help.*` rows have no `en` entry, before and after: their English is the package schema's own `.describe()` sentence, read through `tOptional`. `check:i18n-designer-parity` already lists the family in `ZH_ONLY_FAMILIES`; the zh heading comment says why the rows have no `en` twin. - **No runtime change.** `lookupString` already asks the table first and the namespace second (slice 1), so `t` / `tFormat` / `tOptional` and every call site are untouched. No new file, so the console's `i18n-ns-studio-en` / `i18n-ns-studio-zh` chunk groups need no change. - **Readers.** Every reader of the moved keys is in app-shell. All but one are Studio surfaces (metadata-admin, inspectors, previews, studio-design). The exception is `views/RuntimeDraftBar.tsx` (`engine.edit.*`). It sits outside Studio, but it reads its locale through `useMetadataLocale()`, which re-renders when the `zh` catalogue lands, the same path the Studio surfaces take. So it needs no await. Dynamic keys (`engine.inspector.appNav.type.${…}`, `engine.packages.source.${…}`, `engine.inspector.view.type.${…}`) all go through `t()`. - **Changeset:** `.changeset/25922-studio-i18n-editor-chrome.md`, `@object-ui/i18n` patch. - ⛔ Untouched: `ui/packages/i18n/src/locales/*.ts`, `ui/.github/**`, root `ci.yml`, and every file PR #26800 owns (`inspectorStrings.i18n-10804`, the three `FlowNodeInspector` tests, `datasetPickers.authorText-11161`, `FlowPreview.removeNode-11772`, `flow-problems.removalRefusal-11838`, `previewStrings.i18n-10848`, `metadataError.heldWidget-11910`). None of them needed a preload for this slice. ## Why Ruling 6431032267 Q2 = A (upheld by 6431234244): the designer table becomes one lazy `@object-ui/i18n` namespace, moved in slices; S3 is the third row of #26593's slice table. ## Tests Widened: - `ui/packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts`: four new per-family floors (`engine.inspector.` 700, `engine.packages.` 120, `engine.form.` 90, `engine.edit.` 90, beside S2's six), so one family draining cannot hide behind another. Per family, the namespace carries every key in `en` and `zh`, and `t()` answers every key with the namespace's value in `en-US`, `zh-CN` and `de-DE`. New case: the `engine.packages.form.help.*` rows (at least 9) are absent from `en`, `tOptional(k, 'zh-CN')` returns the `zh` value, and `tOptional(k, 'en-US')` stays `undefined`. Forced edits: the zh rows these suites assert synchronously now arrive in the lazily fetched chunk. Each suite makes `zh` resident with a top-level `await loadStudioCatalogue('zh')`; no assertion changed. All files are under `ui/packages/app-shell/src/views/metadata-admin/`: - 19 dom suites: `AuditPanel.loadFailure`, `IconPickerWidget.unknownName-12531`, `PackageFormDialog` (+ `.helpTextI18n`, `.idDerive-11792`), `PackagesPage.installedApps-13356`, `ResourceEditPage.pickerLoadFailure` / `.referencesColumns-25916` / `.referencesErrorState`, `SchemaForm.deDeveloperize-8218`, `datasource/DatasourceResourcePage.selectPlaceholderLocale-11252`, `inspectors/DashboardDefaultInspector`, `inspectors/FlowReferenceField.flag.i18n-10448`, `inspectors/HookDefaultInspector.flag.i18n-10448`, `inspectors/ReportDefaultInspector` (+ `.i18nTitle`), `inspectors/unknownValueFlag.i18n-9652`, `previews/previewStrings.i18n-10835`, `selector-placeholder.i18n`. - 1 unit suite: `artifact-locked-banner.i18n.test.ts`. The `unit` project runs with `isolate: false`, so in the full run this suite passed only because an earlier file in the same worker had already loaded `zh`. Run alone, it failed. I found it by running each of the 34 unit-project tests that name a zh locale on its own; the other 33 pass alone. ## Acceptance notes - **Every moved key resolves identically before and after.** This was a one-off measurement and is not committed. I read the 551 + 560 values by AST from the base table at `f7c95cd1`. I then compared them with `t()` and `tOptional()` on this branch after `zh` is resident. The `en` value was checked in `en-US`, `en`, `de-DE` and `fr`. The `zh` value was checked in `zh-CN`, `zh` and `zh-TW`. Each lookup checked both `t()` and `tOptional()`. The nine zh-only rows were also checked in `en-US` and `de-DE`, where `t()` must echo the key and `tOptional()` must return `undefined`, as before. That is 3,902 lookups, 0 differing. - **Ablations** (`scripts/ablation-replace.mjs`, mutation landed by anchor count and blob, restored byte-identical to `HEAD`): - With the `?? studioString(key, locale)` arm removed from `lookupString`, 12 tests go red (11 in the pin across all ten families plus the zh-only case, and the equivalence check). The equivalence check reports 3,884 of 3,902 lookups differing. The 18 that hold are the zh-only rows in `en-US` and `de-DE`, whose expected answer is "not found" either way. - With one moved zh row altered (`engine.edit.publish`), the equivalence check reports exactly 3 differing lookups (`zh-CN`, `zh`, `zh-TW`). The pin stays green, as designed, because its oracle is the catalogue itself. - **Eager bundle: not re-measured locally.** The namespace's only non-test importer is app-shell's `i18n.ts`, which imports it statically. So the moved `en` rows sit behind the same import edge before and after, and the `zh` rows stay in the lazy `i18n-ns-studio-zh` chunk. CI's `Build & E2E UI` runs the eager-closure budget on the built console. ## Verification All at `61332921`. <details><summary>Affected tests</summary> - Before the forced edits, under `os-verify-lock`, I ran 341 test files: every app-shell test naming a zh locale, every file naming one of the four families, the i18n namespace tests and the ui i18n script tests. 322 passed and 19 failed, all of them the zh-synchronous suites above. - After the edits, I reran the 21 touched or new files: `Test Files 21 passed (21)`, `Tests 205 passed (205)`, VERDICT command-exit 0. - Unit-project isolation loop: each of the 34 unit tests that name a zh locale, run alone, exits 0 after the `artifact-locked-banner` preload. - `pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check`: VERDICT command-exit 0 (both tsconfigs in each package). </details> <details><summary>Gates</summary> - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 34 commands. Each exited 0, including `pnpm --dir ui exec vitest run scripts/` (`Test Files 178 passed | 2 skipped (180)`). `--ran`: 34 derived, 34 run, 0 NOT-MEASURED. - ui: `check:i18n-designer-parity`, `check:i18n-dead-keys`, `check:i18n-drift`, `check:i18n-keys` all exit 0, and `check:i18n-drift` reports 0 `en` values changed in the locale packs and in the designer table. `check:new-line-citations`: exit 0 (0 new citations). `node scripts/check-nul-bytes.mjs`: exit 0. - Changed lines: 2,770 (+1,454 / −1,316) over 25 files, under the 3,000 threshold. </details> ## Human Minimum - [x] 1. No `packages/spec` change. - [x] 2. No new names; the only new file is the changeset. - [x] 3. No formatter ran; `pnpm lint` is CI's. - [x] 4. One card slice, one branch off `main`, one pull request. - [x] 5. Patch changeset with both declaration lines. - [x] 6. n/a. - [x] 7. No hand edits to generated or release-owned files. - [x] 8. English. --- _Generated by [Claude Code](https://claude.ai/code/session_01JQwxbX9LnJhjTQPJEmoBYi)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4702c46 commit 4b59358

25 files changed

Lines changed: 1454 additions & 1316 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@object-ui/i18n': patch
3+
---
4+
5+
feat(i18n): the rest of the Studio inspectors and the package, form and editor strings move into the `studio` namespace
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Third slice of the move ruled on objectstack#25922** (6431032267, Q2 = A; kept by 6431234244). The remaining `engine.inspector.*` keys and every `engine.packages.*`, `engine.form.*` and `engine.edit.*` key (551 in `en`, 560 in `zh`) now live in `@object-ui/i18n/namespaces/studio` instead of `@object-ui/app-shell`'s private table, text unchanged. The nine `engine.packages.form.help.*` rows stay `zh`-only: their English is the producer's own help text, read through `tOptional`. Studio reads the same strings; a Chinese viewer sees these labels in English for the moment the `zh` catalogue takes to load, as with the earlier slices. No export changes.

‎ui/packages/app-shell/src/views/metadata-admin/AuditPanel.loadFailure.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ import userEvent from '@testing-library/user-event';
5050
import type { MetadataAuditEntry, MetadataClient } from '@object-ui/data-objectstack';
5151
import { AuditPanel } from './AuditPanel';
5252
import { t } from './i18n';
53+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
54+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
55+
// Resident before any case, so the zh rows below read synchronously.
56+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
57+
await loadStudioCatalogue('zh');
5358

5459
/** The positive claim this card exists to keep off a failed read. */
5560
const EMPTY_TITLE = t('engine.edit.auditEmptyTitle', 'en-US');

‎ui/packages/app-shell/src/views/metadata-admin/IconPickerWidget.unknownName-12531.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ import { WIDGETS } from './widgets';
4343
import { t, tFormat } from './i18n';
4444
import { getIcon } from '../../utils/getIcon';
4545
import { ActionDefaultInspector } from './inspectors/ActionDefaultInspector';
46+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
47+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
48+
// Resident before any case, so the zh rows below read synchronously.
49+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
50+
await loadStudioCatalogue('zh');
4651

4752
afterEach(cleanup);
4853

‎ui/packages/app-shell/src/views/metadata-admin/PackageFormDialog.helpTextI18n.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
1818
import { render, screen } from '@testing-library/react';
1919
import { ManifestSchema } from '@objectstack/spec/kernel';
2020
import { PackageFormDialog } from './PackageFormDialog';
21+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
22+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
23+
// Resident before any case, so the zh rows below read synchronously.
24+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
25+
await loadStudioCatalogue('zh');
2126

2227
let localeFixture: 'en-US' | 'zh-CN' = 'zh-CN';
2328
vi.mock('./i18n', async (importOriginal) => ({

‎ui/packages/app-shell/src/views/metadata-admin/PackageFormDialog.idDerive-11792.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/re
2222
import { ManifestSchema } from '@objectstack/spec/kernel';
2323
import { PackageFormDialog } from './PackageFormDialog';
2424
import { t } from './i18n';
25+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
26+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
27+
// Resident before any case, so the zh rows below read synchronously.
28+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
29+
await loadStudioCatalogue('zh');
2530

2631
let localeFixture: 'en-US' | 'zh-CN' = 'en-US';
2732
vi.mock('./i18n', async (importOriginal) => ({

‎ui/packages/app-shell/src/views/metadata-admin/PackageFormDialog.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
55
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
66
import { PackageFormDialog } from './PackageFormDialog';
77
import { t } from './i18n';
8+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
9+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
10+
// Resident before any case, so the zh rows below read synchronously.
11+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
12+
await loadStudioCatalogue('zh');
813

914
// Which console language the dialog renders in. Only `useMetadataLocale` is
1015
// replaced — the rest of `./i18n` (the `t` resolver and both string tables) is

‎ui/packages/app-shell/src/views/metadata-admin/PackagesPage.installedApps-13356.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ import { resolveHref } from '@object-ui/layout';
3232
import { PackagesPage, type InstalledPackageRow } from './PackagesPage';
3333
import { t } from './i18n';
3434
import { initRuntimeConfig, resetRuntimeConfigForTesting } from '../../runtime-config';
35+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
36+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
37+
// Resident before any case, so the zh rows below read synchronously.
38+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
39+
await loadStudioCatalogue('zh');
3540

3641
const CODE: InstalledPackageRow = {
3742
manifest: { id: 'com.acme.code', name: 'Code App', version: '1.0.0', scope: 'project' },

‎ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.pickerLoadFailure.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ vi.mock('./useMetadata', async (importOriginal) => {
141141
});
142142

143143
import { MetadataResourceEditPage, viewRefCatalog } from './ResourceEditPage';
144+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
145+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
146+
// Resident before any case, so the zh rows below read synchronously.
147+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
148+
await loadStudioCatalogue('zh');
144149

145150
function mountEditor() {
146151
render(

‎ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesColumns-25916.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ vi.mock('./useMetadata', async (importOriginal) => {
7272
});
7373

7474
import { MetadataResourceEditPage } from './ResourceEditPage';
75+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
76+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
77+
// Resident before any case, so the zh rows below read synchronously.
78+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
79+
await loadStudioCatalogue('zh');
7580

7681
const START_PATH = '/metadata/object/showcase_account';
7782

‎ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesErrorState.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ vi.mock('./useMetadata', async (importOriginal) => {
117117
});
118118

119119
import { MetadataResourceEditPage } from './ResourceEditPage';
120+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
121+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
122+
// Resident before any case, so the zh rows below read synchronously.
123+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
124+
await loadStudioCatalogue('zh');
120125

121126
const START_PATH = '/metadata/object/showcase_account';
122127

0 commit comments

Comments
 (0)