Repository navigation
feat(ui): lazy studio i18n namespace; designer.* and perm.* strings move into it (#25922 slice 1) - #26593
Merged
Conversation
…lice 1) Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
…h case Claude-Session: https://claude.ai/code/session_01ADHkmRuDqEXC3CybUtz5d1 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
席位核对 · ACCEPT · seat
|
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Steve · project thread
Part of #25922
Clause-②: no
Metadata-protocol: none
维护者速读
@object-ui/i18n新增懒加载的studio命名空间(en 常驻、zh 按需拉取、其他语言回落 en),并把 Studio 设计器表里的designer.*/perm.*共 349 个键(两种语言)迁入;app-shell 的t()先查原表、再查命名空间,调用点不变。ui/packages/i18n/src/namespaces/studio/index.ts,再看 app-shellviews/metadata-admin/i18n.ts的lookupString与useMetadataLocale。cd ui && pnpm run check:i18n-designer-parity && pnpm exec vitest run packages/i18n/src/__tests__/studio-namespace.test.ts packages/i18n/src/__tests__/studio-namespace-lazy.test.tsx。What changes
@object-ui/i18n/namespaces/studio(ui/packages/i18n/src/namespaces/studio/{index,en,zh}.ts,package.jsonexport). Same residency shape aslocales/registry.ts:enis a static import (the fallback for every key and language),zhis one literal() => import('./zh.js'). API:studioString(key, lang)(synchronous; while the serving catalogue is in flight it starts the fetch and answers fromen, never the raw key),loadStudioCatalogue(lang)(memoised, a rejected load is not memoised),isStudioCatalogueLoaded,resolveStudioLanguage(exact tag, then base language, elseen), theuseStudioCatalogue(lang)hook (useSyncExternalStore, re-renders its caller when a catalogue lands),STUDIO_NAMESPACE,STUDIO_FALLBACK_LANGUAGE,STUDIO_LANGUAGE_CODES,StudioCatalogue.designer.*andperm.*row (349 keys per side; one contiguous run on each side ofENGINE_STRINGS_EN/ENGINE_STRINGS_ZH) moves out ofui/packages/app-shell/src/views/metadata-admin/i18n.tsinto the namespace, text unchanged.pickTable(locale).strings[key]reads go throughlookupString(key, locale)= table first, namespace second, sot/tFormat/tOptional/translateNodeLabel/translateNodeHint/translateEnumOptionand every call site stay as they are. The 54 zh-only producer keys are untouched and keep theirtOptionalread.useMetadataLocale()now also callsuseStudioCatalogue(locale), so every designer component re-renders oncezhlands.all-locales-key-parity, by construction.locales/en.tsgains no key; the namespace's files live outsidelocales/and are not members ofbuiltInLocales, which is what that suite iterates. Theindex.tsdocblock and the README say so; the namespace's own parity isstudio-namespace.test.ts.ui/apps/console/vite.config.ts): two priority-84advancedChunksgroups,i18n-ns-studio-enandi18n-ns-studio-zh, so the namespace is not swept into the eageri18n-runtimegroup (whose test matches all ofpackages/i18n).ui/scripts/check-i18n-dead-keys.mjscollectDesignerKeys, used bycheck-i18n-designer-table-parity.mjsandcheck-i18n-en-drift.mjs): when the table module imports@object-ui/i18n/namespaces/studio(the same edge the runtime follows), the homes'STUDIO_EN/STUDIO_ZHliterals are merged intoENGINE_STRINGS_EN/_ZHby AST. A home that cannot be read throws; a key in both homes throws ("exactly one home"); the dead-keys sweep does not count a home literal as a reader. en-drift reads the homes at the same ref, so the move itself is not drift.studionamespace)", citing rulings 6431032267 and 6431234244; two comments that cited the old heading name follow it..changeset/25922-studio-i18n-namespace.md,@object-ui/i18npatch.ui/.github/**, rootci.yml(itscheck:i18n-designer-paritystep stays), existing keys of the eager locale packs,ObjectGrid.tsx.Tests
New:
ui/packages/i18n/src/__tests__/studio-namespace.test.ts(unit): scoped parity (en ⊆ zh, same{placeholders}, zh-only keys only in documented families, non-empty values), no namespace key defined bylocales/en.ts(with a lit control), language resolution table, resident zh answers zh whilede/en-USanswer en, unknown key isundefined.ui/packages/i18n/src/__tests__/studio-namespace-lazy.test.tsx(dom, isolated): before the fetch a zh lookup renders en; the same component re-renders in zh once the chunk lands;derenders en and fetches nothing.ui/packages/app-shell/src/views/studio-design/AddFieldPopover.studioNamespace-25922.test.tsx: a real Studio screen (Data pillar "Add field" popover, which mixes both homes) throughuseMetadataLocale()— zh first paint is English (never the key), then the same mount is Chinese; table keys read Chinese throughout;derenders English from both homes.ui/scripts/__tests__/check-i18n-dead-keys.test.ts: sixcollectDesignerKeys()home cases (merge, no import → no homes, unreadable home throws, duplicate key throws,source+readHome, sweep ignores home literals).ui/scripts/__tests__/check-eager-closure-budget.test.ts: the two namespace modules route toi18n-ns-studio-zh/i18n-ns-studio-en.Forced test edits (the zh rows these suites assert synchronously now arrive in a lazily fetched chunk, so each makes zh resident before its first case with a top-level
await loadStudioCatalogue('zh'); no assertion changed):metadata-admin/zh-base-term.i18n-13131.test.ts— the zh census also reads the namespace's zh rows (otherwise it would silently stop covering 349 keys).metadata-admin/CelTestRunDialog.i18n-10862.test.tsx,metadata-admin/PermissionMatrixEditor.cloneToCustomize.test.tsx,inspectors/FieldTypePicker.search-12516.test.tsx,inspectors/ObjectDefaultInspector.test.tsx,inspectors/ObjectFieldInspector.draft-locale.test.tsx,inspectors/ObjectFieldInspector.labelTranslation-11782.test.tsx,inspectors/ObjectFieldInspector.typePicker-11793.test.tsx,inspectors/ObjectFieldInspector.valueDomain-7597.test.tsx,inspectors/inspectorStrings.hookAction.i18n-10586.test.tsx,inspectors/inspectorStrings.i18n-10586.test.tsx,inspectors/inspectorStrings.i18n-10696.test.tsx,inspectors/inspectorStrings.i18n-10748.test.tsx,previews/PermissionPreview.rlsPolicies-11027.test.tsx,previews/dataPreviews.i18n-10862-s3.test.tsx,previews/field-types.studioSurfaces-11909.test.tsx,previews/flowFieldChrome.i18n-10862-s4.test.tsx,studio-design/BuilderLanding.environmentOverlayCopy-12171.test.ts(all underui/packages/app-shell/src/views/).metadata-admin/ResourceEditPage.referencesErrorState.test.tsx(cites the README section's new name).Acceptance notes
Console eager bundle does not grow. Same tree, console
vite build, BEFORE = the basei18n.ts+vite.config.tsrestored in place, AFTER = this branch:i18nchunk (app-shell table), gzipi18n-runtime, gzipi18n-ns-studio-en(new, eager), gzipi18n-ns-studio-zh(new, lazy)i18n-locale-en(the eager en catalogue)locales/en.tsis 270,655 B before and after.check-eager-locale-cataloguesandcheck-eager-closure-budgetexit 0 on the AFTER dist (aggregate 1948.5 KB of 2431.6 KB).Ablations (
scripts/ablation-replace.mjs, mutation landed and restored,git diff HEADempty after each):studioString's en fallback →return undefined;: 2 red —studio-namespace-lazy"answers from en before the zh catalogue lands",AddFieldPopover"zh: English while the catalogue is in flight".resolveStudioLanguage's?? STUDIO_FALLBACK_LANGUAGE→?? (lang ?? ""): 8 red, including both third-locale (de) screen cases.Gates:
check:i18n-designer-paritygreen (ENGINE_STRINGS 3121 en / 3175 zh, the union unchanged),check:i18n-driftgreen with 0 keys added or removed,check:i18n-dead-keysandcheck:i18n-keysgreen.Open questions (implementation choices, not blockers):
{token}syntax, which i18next would interpolate as literal text. A later slice could convert, but that is a text change to every row.useMetadataLocale()still collapses toen-US/zh-CN, so azh-TWviewer readszh(as before this PR).Clause-②: nois copied from the claim; the PR adds one subpath export, which is additive.Remaining slices (proposal)
Remaining app-shell table ≈ 6,430 lines across both locales (engine.inspector 1,644; engine.studio 1,586; engine.packages/form/edit 802; other engine.* 2,398). Changed lines per slice ≈ 2× table lines, each ≤ ~3,000 and each keeping
check:i18n-designer-paritygreen; each slice adds the zh preload to the zh suites it touches.engine.inspector.{pageBlock, action, dataset, flowNode, appNav, widget}engine.inspector+engine.packages/form/edit(incl. the zh-onlypackages.form.helpkeys, still read bytOptional)engine.studio.{access, if, data, rules, auto, settings}+ ~450 of otherengine.*engine.studio+ ~650 of otherengine.*engine.*TYPE_LABELS/DOMAIN_LABELSand the zh side tables (FLOW_FIELD_ZH…); delete the app-shell table; retirecheck:i18n-designer-parityand its ci.yml stepVerification
PermissionMatrixEditor.cloneToCustomize.test.tsx.pnpm --filter @object-ui/i18n type-check,pnpm --filter @object-ui/app-shell type-check: both exit 0 (afterpnpm --filter @object-ui/i18n build).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 46 derived commands run, all exit 0;--ranreconciliation: 46 derived, 46 run, 0 NOT-MEASURED (derived zero). Also run: uicheck:eager-closure,check:eager-locale-catalogues,check:i18n-dead-keys,check:i18n-designer-parity,check:i18n-drift,check:i18n-keys, all exit 0 on the AFTER console dist. Heade355404ca8; 36 files, +1,792 / −961 (2,753 changed lines, under the 3,000 threshold).Generated by Claude Code