Repository navigation
fix(i18n): Studio edits the Traditional Chinese entry in a Traditional session and never overwrites the other script - #31089
objectstack-fleet[bot] wants to merge 4 commits into
Conversation
…ntry
The shared write limb no longer owns the other script's entry: a zh-Hant
edit over { en, zh } adds zh-Hant and keeps the Simplified text, and a
clear there removes nothing. Reading is unchanged.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9qibxSGAjHBvjATmenUGp
useMetadataLocale resolves the session language through the console's own resolveBuiltInLanguage, so the nav designer reads and edits the entry the sidebar shows. Chrome falls back to the Simplified catalogue; three strict zh-CN chrome comparisons move to isZhLocale. navItemLabel's rename and clear go through the shared write limb. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxSGAjHBvjATmenUGp
…s as a gap Empty entries are judged after the shared resolver picks, so a blank zh-TW beside zh-CN is a gap for a zh-Hant reader rather than covered by zh-CN. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxSGAjHBvjATmenUGp
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxSGAjHBvjATmenUGp
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 35 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 07ab3eeda48f4c6fba0fd6da2c456dd100ba38ca && git checkout 07ab3eeda48f4c6fba0fd6da2c456dd100ba38ca
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 719a502b260616c5ffe62db3c3089f3f27e78622 410d25d60cf8e96d2c3c4c5e8808d6447ac9f5f4 && git checkout -B drift-repro 719a502b260616c5ffe62db3c3089f3f27e78622 && git merge --no-ff 410d25d60cf8e96d2c3c4c5e8808d6447ac9f5f4
node scripts/docs-audit/affected-docs.mjs --json 719a502b260616c5ffe62db3c3089f3f27e78622 |
|
domain:ui#2 · os-tesla · session_01L9qibw7DekEe3wx5f3zphf 席位核对 · ACCEPT · 2026-11-07T05:43Z · head
|
Requested by Tesla · project thread
Fixes #31074
Clause-②: no
Metadata-protocol: none
Clause-② is
no:SupportedLocalegains'zh-Hant', but it lives in@object-ui/app-shell, which is private and exports only its root, which does not carry that type.@object-ui/i18nand@objectstack/clichange behaviour, not their exports. Metadata-protocol isnone: what an author can write is unchanged.维护者速读
os i18n check也把“繁体条目留空”算作缺翻译。ui/packages/app-shell/src/views/metadata-admin/i18n.ts的designerLocaleOf;ui/packages/i18n/src/pickLocalized.ts的localeWriteKey(共用写入分支的脚本检查);packages/cli/src/utils/i18n-coverage.ts的inlineLocaleText。pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/useMetadataLocale.sessionScript-31074.test.tsx packages/i18n/src/__tests__/setLocalized.test.ts,预期全绿。410d25d6的 diff 复核:15 个文件、+304 / −60,无受治理路径,不碰packages/spec/src,不欠契约复审。Studio 设计器语言改为跟随会话书写:繁体会话(zh-Hant / zh-TW / zh-HK)按zh-Hant读写标签条目,界面文字仍用简体目录;写入侧遇到只有另一种书写的标签时新增本书写条目、不覆盖原文;CLI 覆盖率把渲染器实际显示的空条目算作缺口。现场三项读数与三组消融见正文。CI 全绿,同意落地。What changes
useMetadataLocale(metadata-admin/i18n.ts) no longer collapses everyzh*to'zh-CN'. A new puredesignerLocaleOf(language)resolves the session language through the console's ownresolveBuiltInLanguage. A session the console serves inzh-Hant(zh-Hant,zh-TW,zh-HK, …) designs as'zh-Hant', every other Chinese session designs as'zh-CN', and anything else as'en-US'.SupportedLocalegains'zh-Hant'.localeWriteKeyinpickLocalized.ts, behindsetLocalized/clearLocalized) stops owning an entry of the other script. Azh-Hantedit over{ en, zh }or{ en, 'zh-CN' }addszh-Hant, and a clear there removes nothing. The same holds the other way round. Where the table does not name a script subtag (zh-Hant-US), the limb does not assume it is the editor's own. The read side is unchanged.navItemLabel'srenamedLabel/clearedLabelnow go throughsetLocalized/clearLocalizedinstead of askingresolveI18nLabelfor the owned key, so they inherit the rule. Their own "sibling-only map ⇒ add the exact tag" rule (objectui#11196) is kept inownsAnEntry.inlineLocaleTextjudges an empty entry after the shared resolver picks, not before. A blank entry the renderer shows is a gap:{ 'zh-CN': '成员', 'zh-TW': '' }atzh-Hant, and{ zh: '成员', 'zh-CN': '' }atzh-CN. Server seat: no objection (pm:mailbox — domain:server#2 · os-tesla #30985, 6702009928).Studio surfaces that read the designer locale
useMetadataLocale, and the components that take its value as a prop, almost all use it for chrome only (t()/tFormat()/tOptional()→studioString). Thestudionamespace ships one Chinese catalogue (zh), andresolveStudioLanguage('zh-Hant')serves it, so a Traditional designer reads Simplified chrome and never English. No Traditional strings were invented. Three chrome sites compared=== 'zh-CN'and would have dropped to English, so they now useisZhLocale:PositionHoldersSection.tsx:110,AssignedUsersSection.tsx:132andResourceEditPage.tsx:3059.pickLocalized,resolveI18nLabel,navItemLabelTextorrenamedLabel/clearedLabel:StudioNavItemInspector,AppNavInspector,AppNavCanvas,InterfacesNavRail,SourcePageProperties,StudioDesignSurface,ObjectActionsPanel,ObjectListViewInspector/ObjectListViewTitle,ListViewBulkActionsSection,AutomationsFlowRail,metadataError,packageSurfaces,useDatasetCatalog,AppPreview,DashboardPreview,ViewPreview,DashboardDefaultInspector,DashboardWidgetInspectorandReportDefaultInspector.translationTable.tsanddoc-draft.tskey by the translation or doc language the author picks, so they are untouched.Re-pinned #31068 controls
These pinned the cross-script overwrite as "unchanged" and now pin the added entry:
setLocalized.test.tsUNCHANGED:{ en, 'zh-CN' }@zh-Hant→zh-CN;{ en, zh }@zh-TW→zh;{ en, 'zh-HK' }@zh-Hans→zh-HK. All three moved to the Studio designs a Traditional Chinese session in Simplified, so its label edits land on the Simplified entry #31074 block, where they now add their own tag.navItemLabel.inherit-11196.test.tsUNCHANGED:{ en, zh }renamed inzh-Hant→{ en, zh: 'RENAMED' }. Moved to the Studio designs a Traditional Chinese session in Simplified, so its label edits land on the Simplified entry #31074 block, where it now addszh-Hant.i18n-inline-locale-map-coverage.test.ts:{ 'zh-CN': '成员', 'zh-TW': '' }@zh-Hantwas'成员'(covered) and is now a gap.BuilderLanding.environmentOverlayCopy-12171.test.tsDECLARED_LOCALESlists'zh-Hant'. Itssatisfies Record<SupportedLocale, true>exists to fail the type-check until a new locale is listed.The spec twin is untouched. The
packages/spectest's verbatim copy ofpickLocalizedcoverssplitScriptTagOf,localizedEntryKeyandpickLocalized, and none of them changed: onlylocaleWriteKeydid. Its provenance pin still names the revision the copy matches.Tests
Head
410d25d60c.Live readings (console from this tree, showcase backend)
Setup:
examples/app-showcasewith two top-level nav labels set locally,nav_capability_map={ en: 'Proj EN', zh: '简体项目', 'zh-TW': '繁體專案' }andnav_start_here={ en: 'Tasks EN', zh: '简体任务' }. Theirapps.showcase_app.navigation.<id>.labelbundle rows were dropped, because a bundle row wins over the map. These edits were local only and are reverted. Console:ui/apps/consolevite withobjectui-locale = zh-Hant, logged in as admin, Studio → Interfaces.mainit listed 简体项目 (measured on PR fix(i18n): a Traditional Chinese session reads and edits the Traditional entry of an inline label map #31068's head, Studio designs a Traditional Chinese session in Simplified, so its label edits land on the Simplified entry #31074 body).PUT /api/v1/meta/app/showcase_app?mode=draft&package=com.example.showcase.customwithlabel: { en: 'Proj EN', zh: '简体项目', 'zh-TW': '改名繁體' }, sozh-TWwas updated andzhleft untouched.label: { en: 'Tasks EN', zh: '简体任务', 'zh-Hant': '新增繁體' }:zh-Hantwas added and the Simplified text kept. The inspector's Label field then read 新增繁體.Studio chrome in that session is Simplified (界面 / 权限 / 属性), which is the namespace fallback described above.
Suites
pnpm --dir ui exec vitest run packages/i18n/src/__tests__ packages/app-shell/src/views/metadata-admin/previews packages/app-shell/src/views/metadata-admin/useMetadataLocale.sessionScript-31074.test.tsx: all pass.pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/BuilderLanding.environmentOverlayCopy-12171.test.ts: 4 pass.packages/cli:vitest run test/i18n-inline-locale-map-coverage.test.ts17 pass.@object-ui/app-shell type-check,@object-ui/i18n type-checkand@objectstack/cli typecheck(withNODE_OPTIONS=--max-old-space-size=6144, because the 4096 run OOMed incheck:test-typecheck) all exit 0.eslinton every changed ui file: 0 errors.Ablations (committed first, mutated, restored)
designerLocaleOf→ always'zh-CN'for Chinese): 5 red inuseMetadataLocale.sessionScript-31074.test.tsx, all of them the zh-Hant / zh-TW / zh-HK rows and both rename rows. 0 controls red.localeWriteKey→return key, which is the fix(i18n): a Traditional Chinese session reads and edits the Traditional entry of an inline label map #31068 behaviour): 16 red acrosssetLocalized,clearLocalized,navItemLabeland the designer pin, all of them new Studio designs a Traditional Chinese session in Simplified, so its label edits land on the Simplified entry #31074 pins. 0 controls red.i18n-coverage.tsatmain): 2 red, the new empty-entry case and the parity sweep over the two new maps.Derived gates
node scripts/pm/dispatch-gates.mjs --commandson410d25d60cderives 66 families, and all 66 exit 0.--ranreconciles them as 66 accounted and 0 NOT-MEASURED. One family needed a rerun:pnpm --dir ui exec vitest run scripts/first exited 1 on a 15 s timeout indollar-dialect-alias-census.test.tswhile the live console was running on the same box. A container restart then cut the sweep short. The resumed sweep reran every family that had not yet recorded exit 0, and that one passed.node scripts/check-sdui-manifest.mjsis in the derived set and exits 0.Acceptance notes
studionamespace has one Chinese catalogue, and inventing Traditional strings is out of scope. Only the label entries an author reads and edits follow the script.zh-Hantreader of{ en, zh }still sees thezhtext until a Traditional entry exists, and the first edit adds one.navItemLabel's "sibling-only map ⇒ add the exact tag" rule (objectui#11196) is unchanged. For example,{ en, 'zh-TW' }renamed inzh-Hantaddszh-Hant, as before.