Skip to content

Commit f708cf2

Browse files
feat(ui): the flow designer and the rest of the Studio chrome move into the studio i18n namespace (#25922 slice S6) (#27023)
<!-- 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 ## 维护者速读 - 改了什么:app-shell 设计器私有表里除 `engine.translationPreview.*` 之外的全部剩余行(流程设计器各族、页面区块画布、文档与书预览、`engine.studio.inspector` 及其余 Studio 界面文案,共 44 族,en 538 键、zh 583 键),搬进 `@object-ui/i18n` 的 `studio` 命名空间,文案一字未改,调用点不动;`engine.flowNode.*`、`engine.enum.*` 两族照旧仅 zh。 - 为什么改:执行 #25922 裁决 6431032267(Q2 = A,6431234244 维持),这是 (M) 的第 6 片(S6),派单 6457069488;之后表里只剩 22 行 translationPreview,S7 再删表。 - 风险与回滚:与前几片相同,zh 用户首次打开这些页面时标签先显示英文、zh 分片到达后同一挂载重渲染为中文;回滚即 revert 本 PR。 - 先看:`ui/packages/i18n/src/namespaces/studio/zh.ts` 末尾的 S6 段(含仅 zh 两族的说明),再看钉测试新增的 44 个家族下限与三个仅 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 S6 of the (M) item.** Every row left in `ENGINE_STRINGS_EN` / `ENGINE_STRINGS_ZH` in `ui/packages/app-shell/src/views/metadata-admin/i18n.ts`, except `engine.translationPreview.*`, is appended to `STUDIO_EN` / `STUDIO_ZH` in `ui/packages/i18n/src/namespaces/studio/{en,zh}.ts`, text byte-for-byte unchanged. These are the 44 families, by keys per language: | group | families (`en` = `zh` unless noted) | `en` | `zh` | |---|---|---|---| | the flow designer | `flowSim` 64, `flowCanvas` 21, `flowRuns` 19, `flowPreview` 17, `flowScope` 17, `flowValidate` 16, `flowProblems` 9, `flowPalette` 8, `flowExpr` 6, `flowRef` 5, `flowRegion` 4, `flowNode` (zh-only, 41), `enum` (zh-only, 4) | 186 | 231 | | canvases and previews | `pageBlockCanvas` 59, `docPreview` 26, `bookPreview` 22, `layers` 16, `widgetPicker` 16 | 139 | 139 | | the Studio inspector | `studio.inspector` 35 | 35 | 35 | | the rest of the Studio chrome | `list` 36, `catalog` 25, `sharingRule` 16, `diagnostics` 16, `directory` 14, `draftConflict` 10, `validation` 10, `position` 9, `appNav` 8, `embedded` 7, `quickfind` 5, `badge` 3, `fieldsListEditor` 3, `typeAction` 2, `celTest` 2, `sourcePageEditor` 2, `condition` 2, and one key each: `celLint`, `package`, `breadcrumb`, `repeater`, `viewColumnPanes`, `home`, `engine.cancel`, `engine.close` | 178 | 178 | | **total** | | **538** | **583** | Every family is moved; none is left for S7. `engine.translationPreview.*` stays (22 rows in each language) because #26831 is still open. After this PR, those 22 rows are all the table holds. #26920 is still open too, so its two `engine.studio.notFound.*` rows are not in this PR. Whichever of #26920 and this PR lands second resolves the conflict. - **zh-only rows stay zh-only.** `engine.flowNode.*` (41) and `engine.enum.*` (4) have no `en` entry, before and after: - The flow node labels and hints fall back to the engine descriptor's own name for English. - `translateEnumOption` returns the raw value for any non-zh locale. `check:i18n-designer-parity` already lists both in `ZH_ONLY_FAMILIES`, and the zh heading comment says why. - **One anchor kept in place (forced edit).** `ZH_ONLY_FAMILIES` cites the anchor `resolved by translateNodeLabel/Hint` in `i18n.ts`. That text lived in the `engine.flowNode.*` rows' comment, which moved with the rows, so the gate's own test (`check-i18n-designer-table-parity.test.ts`, "every citation resolves") went red. The gate stays untouched, as the order requires. Instead, `translateNodeLabel`'s doc comment now says that the rows are resolved by translateNodeLabel/Hint through `lookupString` from the namespace. That makes the cited text occur once again in `i18n.ts`. - The S2–S5 AST pass, with a heading comment marking the S6 section in each catalogue. Two comment groups were mixed: their first row moved, so the comment moved, and the `engine.translationPreview.*` rows after it stayed. - **No runtime change.** `lookupString` already asks the table first and the namespace second, so `t` / `tFormat` / `tOptional`, `translateNodeLabel` / `translateNodeHint` / `translateEnumOption` and every call site are untouched. The table object, `t()` / `tOptional()`, `TYPE_LABELS` / `DOMAIN_LABELS`, `FLOW_FIELD_ZH` and `check:i18n-designer-parity` are left as they are for S7. - **Readers.** Every non-test reader of a moved family is under app-shell's `views/metadata-admin/` or `views/studio-design/`. None calls `t()` at module scope. The dynamic keys (`engine.flowNode.${type}.label|hint`, `engine.enum.${field}.${value}`) go through `lookupString`. Nothing to stop and report. - **Main merged twice** (`5fbed2b9`, `b94ef650`). The first merge picked up #26967, which added nine `engine.widgetPicker.type.*` rows to the namespace. That PR's comment said the family's other rows "still sit in the app-shell designer table (objectstack#25922 moves them)". This PR moves them, so the comment now points at the S6 section. Text and key set are otherwise unchanged. - Before the move, I read the patches of every open PR that touched either home (#26831, #26920, #26967, #26977, #26982, #26987). None touches a moved key. #26967, #26977 and #26987 have since merged and arrived through the main merges. - **Changeset:** `.changeset/25922-studio-i18n-flow-and-chrome.md`, `@object-ui/i18n` patch. - ⛔ Untouched: `ui/packages/i18n/src/locales/*.ts`, `ui/.github/**`, root `ci.yml`, `engine.translationPreview.*`, `ui/scripts/check-i18n-designer-table-parity.mjs`. ## Why Ruling 6431032267 Q2 = A (upheld by 6431234244): the designer table becomes one lazy `@object-ui/i18n` namespace, moved in slices. ## Tests - **Pin widened:** `inspectors/inspectorStrings.studioNamespace-25922.test.ts` gains a floor for each of the 44 S6 families (86 families in all). Every key in each family must resolve through `t()` to the namespace value in `en-US`, `zh-CN` and `de-DE`. The zh-only case now covers three families (`engine.packages.form.help.`, `engine.flowNode.`, `engine.enum.`). For each, the rows are absent from `en`, `tOptional` in `zh-CN` returns the `zh` value, and `tOptional` in `en-US` stays `undefined`. - **zh preloads (forced edits).** Each suite below reads a moved S6 zh row synchronously, so it now loads the `zh` catalogue first with a top-level `await loadStudioCatalogue('zh')`. No assertion changed. - 9 dom suites: - in `metadata-admin/`: `CelPredicateField.i18n-10862-s2` - in `metadata-admin/inspectors/`: `FlowNodeInspector.nodeTypeOptions-11778` - in `metadata-admin/previews/`: `AppNavCanvas.labelMaps-11128`, `AppNavCanvas.untitledCard-11862`, `DocPreview`, `FlowPreview.headerPills-11779`, `NodePalette`, `flowNodeLabels-13200` - in `studio-design/`: `ObjectListViewInspector.displayTitle-13151` - 3 unit suites: `metadata-admin/flowNodePaletteI18n.test.ts`, `previews/FlowRunsPanel.test.ts` and `previews/flow-problems.repeatedEdge-11772.test.ts`. All three are in the `unit` project (`isolate: false`). Each passed in the full run only because an earlier file had already loaded `zh`, and failed when run alone. ### The sweep I delayed the `zh` loader in `namespaces/studio/index.ts` by 4000 ms (`scripts/ablation-replace.mjs --hold`, restored byte-identical). Under that delay I ran every app-shell test that names zh or a moved key, plus the i18n namespace and script tests (458 files). Then I ran each of the 50 unit-project files alone. - **Before the fixes:** 11 files failed in the full run and 3 failed when run alone. - `i18n/src/__tests__/studio-namespace-lazy.test.tsx` fails by construction under the delay, because its `findByText` waits 1 s against a 4 s delay. - `scripts/__tests__/check-i18n-designer-table-parity.test.ts` failed because of the moved citation anchor described above, not because of the delay. - The other 12 are the suites listed above. - **All 12 come from S6 itself.** I checked out main's three homes and main's versions of the 12 test files and ran them under the same delay. All 12 pass on main, so this sweep found no leftover from S1–S5. - **After the fixes:** the 12 suites, the pin, the parity test and the equivalence check pass at normal speed (`Tests 305 passed (305)`). The dom suites and those three pass under the delay too (`Tests 271 passed (271)`). The three unit suites pass alone, both delayed and at normal speed. - **After the merge:** after each of the two main merges, I ran under the delay every test file those merges added or changed in ui (6 after the first merge, 21 after the second), together with the pin, the parity test, both `block-config-i18n` tests and the equivalence check. Last run: `Tests 501 passed (501)`. The equivalence check still reports 4,235 lookups, 0 differing. ## Acceptance notes - **With the table nearly empty, every lookup resolves as before.** This was a one-off measurement and is not committed. I read all 560 `en` and 605 `zh` rows of the base table at `49b50591` by AST, which includes the 22 + 22 `engine.translationPreview.*` rows that stay. I compared each with `t()` and `tOptional()` on this branch, with `zh` resident: - the base `en` value in `en-US`, `en`, `de-DE` and `fr`; - the base `zh` value in `zh-CN`, `zh` and `zh-TW`; - for the 45 zh-only rows, in `en-US` and `de-DE`, `t()` must echo the key and `tOptional()` must return `undefined`; - `translateNodeLabel` / `translateNodeHint` for every `engine.flowNode.*` row (the `zh` value in `zh-CN`, the caller's fallback in `en-US`), and `translateEnumOption` for every `engine.enum.*` row (the `zh` value in `zh-CN`, the raw value in `en-US`). Result: 4,235 lookups, 0 differing. - **Ablations** (mutation landed by anchor count and blob, restored byte-identical to `HEAD`): - Removing the `?? studioString(key, locale)` arm from `lookupString` turns 90 tests red: the pin's `t()` case for all 86 families, its three zh-only cases, and the equivalence check. The equivalence check reports 3,946 of 4,235 lookups differing. The 289 that hold are the 154 `engine.translationPreview.*` lookups the table still serves, plus the 135 `en`-side zh-only lookups, whose expected answer is "not found" or the fallback either way. - Altering one moved zh row (`engine.flowNode.start.label`) makes the equivalence check report exactly 4 differing lookups (`zh-CN`, `zh`, `zh-TW` and `translateNodeLabel` in `zh-CN`). The pin stays green, as designed. - **Eager bundle:** not re-measured locally, as in S2–S5. CI's `Build & E2E UI` measures it. ## Verification At `b94ef650` (the second main merge). <details><summary>Tests and gates</summary> - `pnpm --filter @object-ui/i18n --filter @object-ui/app-shell run type-check`: VERDICT command-exit 0. - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack`: 34 commands, each exit 0, including `pnpm --dir ui exec vitest run scripts/` (`Test Files 176 passed | 2 skipped (178)`). `--ran`: 34 derived, 34 run, 0 NOT-MEASURED. I also ran the same 34 after the first merge, all exit 0, and re-derived after the second merge: the same 34 commands. - ui `check:i18n-designer-parity`, `check:i18n-dead-keys`, `check:i18n-drift` (0 `en` values changed) and `check:i18n-keys` all exit 0, before and after each merge. `check:new-line-citations`: exit 0 (0 new citations). `node scripts/check-nul-bytes.mjs`: exit 0. - Changed lines: 2,816 (+1,473 / −1,343) over 17 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 3230bdb commit f708cf2

17 files changed

Lines changed: 1473 additions & 1343 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 flow designer and the rest of the Studio chrome move into the `studio` namespace
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Sixth slice of the move ruled on objectstack#25922** (6431032267, Q2 = A; kept by 6431234244). Every row still left in `@object-ui/app-shell`'s private designer table, except `engine.translationPreview.*`, now lives in `@object-ui/i18n/namespaces/studio`, text unchanged: the flow designer (`engine.flowSim.*`, `engine.flowCanvas.*`, `engine.flowRuns.*` and the other `engine.flow*` families), the page-block canvas, the doc and book previews, `engine.studio.inspector.*` and the remaining Studio chrome (538 keys in `en`, 583 in `zh`). The `engine.flowNode.*` and `engine.enum.*` rows stay zh-only, as before: their English is the flow node descriptor or the enum value itself. 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/CelPredicateField.i18n-10862-s2.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ import { fieldRuleRootIssue, validateRlsPredicateEnforceability } from '@objects
3636
import { t, tFormat } from './i18n';
3737
import { CelPredicateField } from './CelPredicateField';
3838
import { lintCelPredicate, type CelSchemaHint } from './celAuthoring';
39+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
40+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
41+
// Resident before any case, so the zh rows below read synchronously.
42+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
43+
await loadStudioCatalogue('zh');
3944

4045
afterEach(cleanup);
4146

‎ui/packages/app-shell/src/views/metadata-admin/flowNodePaletteI18n.test.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919

2020
import { describe, it, expect } from 'vitest';
2121
import { translateNodeLabel, translateNodeHint } from './i18n';
22+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
23+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
24+
// Resident before any case: this file runs in the `unit` project, whose shared
25+
// module graph would otherwise let it pass only when another file had loaded
26+
// `zh` first.
27+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
28+
await loadStudioCatalogue('zh');
2229

2330
/**
2431
* The framework's own strings for this node type, copied here ONLY as the

‎ui/packages/app-shell/src/views/metadata-admin/i18n.ts‎

Lines changed: 4 additions & 1327 deletions
Large diffs are not rendered by default.

‎ui/packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.nodeTypeOptions-11778.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ import { FlowNodeInspector } from './FlowNodeInspector';
2424
import { NODE_PALETTE } from '../previews/flow-canvas-parts';
2525
import { t, type SupportedLocale } from '../i18n';
2626
import type { MetadataSelection } from '../preview-registry';
27+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
28+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
29+
// Resident before any case, so the zh rows below read synchronously.
30+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
31+
await loadStudioCatalogue('zh');
2732

2833
const ACTIONS_ROUTE = '/api/v1/automation/actions';
2934
let engineActions: unknown[] | null = null;

‎ui/packages/app-shell/src/views/metadata-admin/inspectors/inspectorStrings.studioNamespace-25922.test.ts‎

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

33
/**
4-
* objectstack#25922 slices S2 to S5 — the designer rows that moved into
4+
* objectstack#25922 slices S2 to S6 — the designer rows that moved into
55
* `@object-ui/i18n`'s `studio` namespace (every `engine.inspector.*` row;
6-
* `engine.packages.*`, `engine.form.*`, `engine.edit.*`; `engine.studio.*` but
7-
* its inspector; the data source pages, the field types and the metadata
8-
* preview panes), and app-shell's `t()` / `tOptional()` still answer every one
9-
* of them the way they did when the rows sat in its own table.
6+
* `engine.packages.*`, `engine.form.*`, `engine.edit.*`; all of
7+
* `engine.studio.*`; the data source pages, the field types, the metadata
8+
* preview panes, the flow designer and the rest of the Studio chrome), and
9+
* app-shell's `t()` / `tOptional()` still answer every one of them the way they
10+
* did when the rows sat in its own table.
1011
*
1112
* What would break it:
1213
* - a row copied back into the app-shell table with a different value — the
@@ -78,15 +79,66 @@ const FAMILY_FLOOR: Readonly<Record<string, number>> = Object.freeze({
7879
'engine.viewPreview.': 4,
7980
'engine.objectPreview.': 1,
8081
'engine.previewShell.': 1,
82+
// S6 — the rest of the table (engine.translationPreview aside): the flow
83+
// designer, the page-block canvas, the doc and book previews, the Studio
84+
// inspector and the remaining chrome
85+
'engine.studio.inspector.': 30,
86+
'engine.flowSim.': 60,
87+
'engine.flowCanvas.': 20,
88+
'engine.flowRuns.': 18,
89+
'engine.flowPreview.': 15,
90+
'engine.flowScope.': 15,
91+
'engine.flowValidate.': 15,
92+
'engine.flowProblems.': 9,
93+
'engine.flowPalette.': 8,
94+
'engine.flowExpr.': 6,
95+
'engine.flowRef.': 5,
96+
'engine.flowRegion.': 4,
97+
'engine.pageBlockCanvas.': 55,
98+
'engine.list.': 30,
99+
'engine.docPreview.': 25,
100+
'engine.catalog.': 25,
101+
'engine.bookPreview.': 20,
102+
'engine.sharingRule.': 15,
103+
'engine.widgetPicker.': 15,
104+
'engine.layers.': 15,
105+
'engine.diagnostics.': 15,
106+
'engine.directory.': 14,
107+
'engine.draftConflict.': 10,
108+
'engine.validation.': 10,
109+
'engine.position.': 9,
110+
'engine.appNav.': 8,
111+
'engine.embedded.': 7,
112+
'engine.quickfind.': 5,
113+
'engine.badge.': 3,
114+
'engine.fieldsListEditor.': 3,
115+
'engine.typeAction.': 2,
116+
'engine.celTest.': 2,
117+
'engine.sourcePageEditor.': 2,
118+
'engine.condition.': 2,
119+
'engine.celLint.': 1,
120+
'engine.package.': 1,
121+
'engine.breadcrumb.': 1,
122+
'engine.repeater.': 1,
123+
'engine.viewColumnPanes.': 1,
124+
'engine.home.': 1,
125+
'engine.cancel': 1,
126+
'engine.close': 1,
81127
});
82128

83129
/**
84-
* The one zh-only family among the moved rows: the package form's help text,
85-
* whose English is the producer's own `.describe()` sentence and is read
86-
* through `tOptional` (`ZH_ONLY_FAMILIES` in
87-
* `ui/scripts/check-i18n-designer-table-parity.mjs` carries the reason).
130+
* The zh-only families among the moved rows, with the fewest keys each may
131+
* carry. The package form's help text reads its English from the producer's own
132+
* `.describe()` sentence; the flow node labels and hints and the flow enum
133+
* values read theirs from the engine descriptor or the value itself. Each is
134+
* read through `tOptional` or a `lookupString` fallback (`ZH_ONLY_FAMILIES` in
135+
* `ui/scripts/check-i18n-designer-table-parity.mjs` carries the reasons).
88136
*/
89-
const ZH_ONLY_PREFIX = 'engine.packages.form.help.';
137+
const ZH_ONLY_FLOOR: Readonly<Record<string, number>> = Object.freeze({
138+
'engine.packages.form.help.': 9,
139+
'engine.flowNode.': 40,
140+
'engine.enum.': 4,
141+
});
90142

91143
const familyKeys = (prefix: string): string[] => Object.keys(EN).filter((key) => key.startsWith(prefix));
92144

@@ -110,9 +162,9 @@ describe('moved designer rows answer from the studio namespace (objectstack#2592
110162
expect(wrong).toEqual([]);
111163
});
112164

113-
it('the zh-only package help rows stay optional lookups: zh answers, en finds nothing', () => {
114-
const keys = Object.keys(ZH).filter((key) => key.startsWith(ZH_ONLY_PREFIX));
115-
expect(keys.length).toBeGreaterThanOrEqual(9);
165+
it.each(Object.entries(ZH_ONLY_FLOOR))('%s: the zh-only rows stay optional lookups: zh answers, en finds nothing', (prefix, floor) => {
166+
const keys = Object.keys(ZH).filter((key) => key.startsWith(prefix));
167+
expect(keys.length).toBeGreaterThanOrEqual(floor);
116168
expect(keys.filter((key) => key in EN)).toEqual([]);
117169
expect(keys.filter((key) => tOptional(key, 'zh-CN') !== ZH[key])).toEqual([]);
118170
expect(keys.filter((key) => tOptional(key, 'en-US') !== undefined)).toEqual([]);

‎ui/packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.labelMaps-11128.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ import { render, screen, cleanup, fireEvent } from '@testing-library/react';
3232
import { I18nProvider } from '@object-ui/i18n';
3333
import { tFormat } from '../i18n';
3434
import { AppPreview } from './AppPreview';
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
afterEach(cleanup);
3742

‎ui/packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.untitledCard-11862.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ import { I18nProvider } from '@object-ui/i18n';
3030
import { MetadataCtx } from '@object-ui/react';
3131

3232
import { AppNavCanvas } from './AppNavCanvas';
33+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
34+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
35+
// Resident before any case, so the zh rows below read synchronously.
36+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
37+
await loadStudioCatalogue('zh');
3338

3439
afterEach(cleanup);
3540

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

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

4040
import { DocPreview } from './DocPreview';
4141
import { localeRefusal, patchAddLocale, patchRemoveLocale, resolvePlacements, toBookOptions } from './doc-draft';
42+
// The designer rows this suite reads in zh live in `@object-ui/i18n`'s `studio`
43+
// namespace, whose `zh` catalogue is fetched on demand (objectstack#25922).
44+
// Resident before any case, so the zh rows below read synchronously.
45+
import { loadStudioCatalogue } from '@object-ui/i18n/namespaces/studio';
46+
await loadStudioCatalogue('zh');
4247

4348
const STUB_NS = 'doc-preview-test';
4449

‎ui/packages/app-shell/src/views/metadata-admin/previews/FlowPreview.headerPills-11779.test.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ vi.stubGlobal(
3232

3333
import { FlowPreview } from './FlowPreview';
3434
import { t } from '../i18n';
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
afterEach(cleanup);
3742

0 commit comments

Comments
 (0)