Repository navigation
feat(i18n): assign the locale paths outside UiCatalog<T> before ko integration #5075
Description
Problem
Per the updated maintainer decision on #3975, Korean will roll out progressively. Until each translation slice lands, an untranslated Korean surface may intentionally resolve to English. This audit checks that each locale path reaches the correct surface or the shared English fallback, and that it does not crash or silently render another language such as Simplified Chinese. It is a runtime-path and coverage audit, not a requirement that every string be translated before core enablement.
Those paths are not covered by the 126 UiCatalog<T> sites counted on #3975, and they split into two classes with different failure modes.
Class A — compiles clean, renders English
These pass typecheck with ko enabled and silently serve English, so nothing reports them.
| Path | Shape |
|---|---|
apps/desktop/src/main/e2e-fixture.ts (parseLocaleFlag) |
no ko branch — returns null |
apps/desktop/src/main/browser-message-box.ts |
locale ternary |
apps/desktop/src/renderer/workhub-surface.ts |
locale ternary / if-chain |
apps/desktop/src/renderer/settings/daily-review-settings-page.ts |
hardcoded union instead of UiLocale |
apps/desktop/e2e/fixtures.ts |
hardcoded union instead of UiLocale |
apps/desktop/.storybook/preview.ts and stories |
no ko in the locale global |
I catalogued these on #3975 against c0229b0 and re-verified the paths today. The line numbers in that comment have drifted, so they are omitted here deliberately — search for the shape, not the line.
One entry did not survive re-verification: a locale if-chain in renderer/features/connection-settings/subscription-result-message.ts. No such file exists under apps/desktop/src/renderer/features/connection-settings/ at current main, so it was renamed or moved rather than fixed. It should be re-located, not assumed gone.
parseLocaleFlag is the same class @Astro-Han caught for zh-TW in #3853, which is the argument for tracking this once rather than rediscovering it per locale.
Class B — hard failures, but uncounted
Plain as const locale maps indexed with a UiLocale. They are not declared as UiCatalog<T>, so they are absent from the census, and they only fail once ko is in the union. From run 34312890700 on 36a4377 (#5011) — all TS7053, all in maka-agent (packages/cli):
src/pi-tui-todo.ts:131,188,217src/pi-tui-transcript-viewer.ts:208src/pi-tui-runner.ts:4005src/__tests__/tui-copy-catalog.test.ts:59
Six is a floor, not a total. That run ends with tsc -p tsconfig.json failing in packages/cli with exit code 2, so any workspace built after it was never reached — whatever equivalents exist in @maka/ui and @maka/desktop are still unmeasured.
Desired outcome
Every path above has an owner and an explicit outcome before Korean enablement: translated Korean or a verified shared English fallback. No path may crash, mislabel another locale, or bypass the locale authority.
Proposed homes, for @me2seeks to confirm or overrule:
parseLocaleFlagandapps/desktop/e2e/fixtures.ts→ feat(i18n-ko): native surfaces and E2E fixtures #3980 (native surfaces and E2E fixtures)- the
packages/cliClass B sites → feat(i18n-ko): CLI — human help and TUI chrome #3979 / feat(cli): add Korean catalog for TUI #4349 - the renderer ternaries and hardcoded unions → feat(i18n-ko): desktop slice 1 — settings-preferences/onboarding/shell/permissions #3977 and the slice-2 work
apps/desktop/src/main/browser-message-box.ts→ closest to feat(i18n-ko): shared UI — packages/ui and core error copy #3978's main-process fallback bucket, though it is not listed there todayapps/desktop/.storybook/preview.tsand the stories → not owned by any slice today
Acceptance criteria:
- Every Class A path renders Korean or is verified to use the shared English fallback; paths that are intentionally English-only are recorded.
- Every Class B map has a typed Korean value or resolves through an explicit, tested English fallback; no unsafe
undefinedindex or implicitanyremains. - English remains complete, and completeness/placeholder checks for shipped
zh-CNandzh-TWremain enforced. - A full repo typecheck with
koenabled reports zero locale-related errors. - The Korean coverage inventory distinguishes translated copy from English fallback so the remaining work is visible.
- The
as constmaps in@maka/uiand@maka/desktopare enumerated once the CLI gap no longer blocks the build. - The relocated
subscription-result-messageif-chain is found and assigned, or recorded as no longer existing.
Refs #3975, #5011. Part of #3974.
Alternatives or workarounds
Leave them where they are without validating the fallback. ko could then crash, show the wrong locale, or leave untracked English paths in desktop main, WorkHub, daily-review settings, fixtures, and Storybook.
Assigning fixes opportunistically without one audit still risks missing non-catalog locale branches. Track the path and its outcome once; Korean fallback is acceptable during this rollout only when the route is explicit, tested, and included in the coverage inventory.
Activity
me2seeks commentedon Sep 9, 2026
Thanks for turning this into a concrete audit issue. The proposed split is confirmed, with these explicit owners:
parseLocaleFlag,apps/desktop/e2e/fixtures.ts,browser-message-box.ts, the shared Storybook locale global, and Korean screenshot/E2E coverage. These are native, fixture, and integration-verification paths.as constlocale maps and their tests, including the TUI transcript, todo panel, runner, and the feat(cli): add Korean catalog for TUI #4349-related copy.@maka/ui, and should refresh against fix(i18n): emit settings expected-result codes from producers #4551's final producer-code/catalog contract.@maka/desktopshould be assigned by surface: feat(i18n-ko): desktop slice 1 — settings-preferences/onboarding/shell/permissions #3977 for preferences/onboarding/shell/permission surfaces, feat(i18n-ko): desktop slice 2 — remaining settings/conversation/artifact/browser/mcp/plan-mode #3976 for the remaining renderer surfaces, and feat(i18n-ko): native surfaces and E2E fixtures #3980 for main-process/native/E2E/Storybook paths.#5075 remains the cross-slice audit and release gate, not a catch-all implementation PR. Before the integration branch is cut, update this issue with the complete scan result and confirm that every Class A path renders Korean or is explicitly recorded as English-only, and every Class B map is typed or has a
koentry.@heeoneie, thank you for locating and separating these paths. The assigned slice owners, not this tracking issue, now carry the implementation work.
heeoneie commentedon Sep 16, 2026
Correction: the central claim below is wrong —
SHELL_COPY_BY_LOCALEistype-constrained after all. See this comment.
While scoping slice 1 (#3977) I ran into a locale map that doesn't fit either class cleanly, and I think it points at a gap in how the audit plans to find them.
apps/desktop/src/renderer/locales/shell-copy.tsdeclares its catalog with no type at all:Every other catalog in slice 1 is constrained —
satisfies UiCatalog<SettingsPreferencesCopy>,: UiCatalog<OnboardingCatalog> =,satisfies UiCatalog<ShellRemainingCopy>,satisfies UiCatalog<PermissionCenterCopy>. This one is not.That gives it a split character:
koentry can be added while any key left out of it silently serves English, becausegetShellCopy()returnsSHELL_COPY_BY_LOCALE[locale]and nothing narrows that toUiCatalog<ShellCopy>.kojoins the union, because there is no type to violate.That combination is the problem for the acceptance criteria as written. The plan is to surface Class B by typechecking each workspace once
kois in. This file passes that sweep and ships English anyway.Concretely, two module-level constants live outside the
enblock and are referenced from it:EN_STATIC_COMMANDS(70 strings) andEN_SETTINGS_SECTIONS(16 strings).koneeds its own of both and nothing forces it — 86 strings that a typecheck-driven audit would not ask for.Suggested addition to the audit: alongside the typecheck sweep, scan for locale-keyed catalog objects that carry no
UiCatalog<T>annotation and nosatisfiesclause. Those are invisible to typecheck by construction, so the sweep cannot find them no matter how thorough it is.I'm covering
shell-copy.tsas part of slice 1. Flagging it here so the other slice owners can check their own files for the same shape before the integration branch is cut.Measured on
stack/i18n-ko-coreata193ad8d1.heeoneie commentedon Sep 16, 2026
Correction to my comment above — I got the central claim wrong.
SHELL_COPY_BY_LOCALEis constrained. The opening line at L757 carries noannotation, but the object closes with
} satisfies UiCatalog<ShellCopy>;atL2313 — 1,556 lines later — and
ShellCopydeclares bothcommands(L414)and
settingsSections(L415). I read the opening line and not the closingone.
Checked by running it this time rather than by reading: with
koinUI_LOCALESand the catalog untouched,tscreportsshell-copy.ts(2280,3): error TS2741: Property 'ko' is missing. All fiveslice-1 catalogs are constrained the same way. So the typecheck sweep in the
acceptance criteria does find this file, and the hole I described is not
there. Sorry for the noise.
What survives is narrower, and I think still worth having. The type
enforces that the keys exist, not that the values were translated. This
compiles clean:
— 86 English strings shipped to Korean users with a green typecheck.
That is not hypothetical.
zh-CNandzh-TWcurrently share oneZH_*pairfor exactly these two constants, which is why Traditional users see
Simplified text in the command palette and the settings section names
(#5377). The same shape would let a
koentry point atEN_*and pass.So the gap isn't "untyped catalogs the sweep misses" — it's "locale-keyed
constants whose values the type system cannot check." A cheap mechanical
check covers it: for each catalog, flag any two locales that reference the
same module-level constant. That catches the
zhcase that exists today anda
ko-pointing-at-EN_*case tomorrow. It's a much smaller addition thanwhat I proposed above, and it's the only part of that comment I'd still
stand behind.
Astro-Han commentedon Sep 17, 2026
Closing this as an issue for now: the direction has not been confirmed by a maintainer, and the tracker only keeps proposals that already have an agreed scope. Please continue it in GitHub Discussions (https://github.com/apache/maka/discussions); once the shape and acceptance criteria are settled there, open an issue with that scope and it will be picked up.
heeoneie commentedon Sep 18, 2026
Two more entries for this issue, found while trying to take the
koscreenshots #3977 asks for. Both are on
stack/i18n-ko-coreata193ad8d1,and the line numbers are from there.
Class A — the Storybook locale global (
apps/desktop/.storybook/preview.tsx)This is the entry the issue already lists as "no
koin the locale global",now with the exact shape. Two places, and only the second one is visible:
preview.tsx:41— the decorator maps the global to aUiLocalewith aternary chain that ends in a default:
kois not a branch, so it falls through to'zh-CN'. Nothing fails; thestory renders Simplified Chinese while the toolbar claims something else.
preview.tsx:103— the toolbaritemsarray lists three locales, sokocannot be picked from the UI at all.
Whoever takes #3980 needs both. Adding the branch without the toolbar entry
leaves
kounreachable, and adding the toolbar entry without the branchsilently shows
zh-CNunder a Korean label — the second failure is the onethis issue is about.
The crash behind it (
packages/ui/src/astryx-i18n.tsx:68)Adding both locally does not give a Korean story. The global decorator mounts
AstryxLocaleProvider, which throws forko:The line is:
astryxMessageOverrides(line 104) already takes the locale and returnsOVERRIDES_BY_LOCALE[locale], and the call site indexes that result by thelocale a second time. The double indexing is why the failure reads as
undefined[...]rather than as a missing catalog entry: the outer lookupreturns
undefinedforko, and the inner one then throws.It is worth listing here because it handles a locale outside the
UiCatalog<T>contract that the 126 sites on #3975 were counted against. Ittypechecks today only because
OVERRIDES_BY_LOCALEis declared withsatisfies UiCatalog<Overrides>and the index happens on the function'sreturn type, so the census does not see it.
Why this blocks the desktop app too, not just Storybook
Same line, same cause. On a machine whose system locale is
ko_KRthe appresolves
kowithout anyone touching the language setting, and the renderercrashes in
AstryxLocaleProviderbefore the first surface paints. Guardingthat one call locally moves the crash to the next catalog the tree reaches
(
session-collaboration-copy.ts, then a main-process catalog), becausecatalog accessors index without a fallback:
return CATALOG[locale];.That is the right default — it fails loudly instead of shipping the silent
English this issue is about — but it does mean a partially translated stack
cannot be run at all, and therefore that no
koscreenshot can be takenuntil the sibling slices land. I recorded the same chain on #5451.
me2seeks commentedon Sep 29, 2026
Maintainer decision update: progressive Korean rollout is now accepted; see the updated policy on #3975 and the implementation direction on #5100. I have reopened this audit because its direction is now confirmed.
During rollout, an untranslated path may use the shared English fallback. The audit should verify that every path either renders Korean or reaches that fallback safely, and that no path crashes or silently renders Simplified Chinese under a Korean locale. Keep the coverage inventory explicit so users and maintainers can see which surfaces are still English. Preserve complete English and the existing Simplified/Traditional Chinese coverage checks. This issue does not require full Korean coverage before the core locale can land.
The per-slice owners remain responsible for their assigned paths; maintainers will coordinate the full-workspace check, integration branch, screenshots, and E2E. The final Korean coverage state remains part of the #3974 completion record.
简体中文
维护者更新决定:现已接受韩语渐进式上线,详见 #3975 的交付政策和 #5100 的实施方向。方向已经确认,因此重新开启本审计。
渐进上线期间,未翻译路径可以使用共享的英文回退。本审计要确认每条路径都能显示韩语或安全回退英文,不能崩溃,也不能在韩语界面错误显示简体中文。覆盖清单需要明确列出仍显示英文的界面。英文保持完整,简体和繁体中文的既有完整性检查继续保留。本 issue 不要求核心合入前先完成所有韩语翻译。
各分片负责人仍处理各自路径;完整工作区检查、集成分支、截图和 E2E 由维护者协调。最终韩语覆盖情况记录在 #3974。
github-actions commentedon Sep 29, 2026
feat(i18n-ko): core — add ko to UiLocale model