Complete client UI i18n migration#1282
Conversation
|
| Filename | Overview |
|---|---|
| packages/app/src/i18n/i18next.ts | New i18n singleton — initializes with hardcoded lng: "en" and drops the init promise without a .catch(), both of which were flagged in previous threads. |
| packages/app/src/i18n/locales.ts | Locale types and resolution logic; startsWith("zh-") mapping to zh-CN was flagged in a previous thread but otherwise clean. |
| packages/app/src/i18n/provider.tsx | React I18n provider; first-render flash issue was flagged in a previous thread; otherwise minimal and correct. |
| packages/app/src/i18n/resources/en.ts | 1338-line English resource file; contains two dead duplicate keys (common.back and common.states.loading) that are never referenced in code. |
| packages/app/src/i18n/resources/zh-CN.ts | Simplified Chinese translations with full parity to en.ts; includes the same dead keys mirroring en.ts. |
| packages/app/src/hooks/use-settings/storage.ts | Adds language: AppLanguage field to AppSettings with correct validation via parseAppLanguage; unknown values fall back to "system". |
| packages/app/e2e/settings-i18n.spec.ts | E2E smoke test for language switching; language-selection interactions are raw Playwright calls inline in the test body rather than helper-wrapped domain actions. |
| packages/app/src/git/worktree-archive-warning.ts | Correctly converts hardcoded strings to a WorktreeArchiveWarningLabels parameter with an English-default constant; both callers pass translated labels. |
| packages/app/src/components/agent-list.tsx | Refactors date-section bucketing to use stable DateSectionKey enum values; translates status labels, badges, and archive sheet via useTranslation(). |
| packages/app/src/composer/agent-controls/utils.ts | Converts getAgentControlHint to getAgentControlHintKey (returns translation key strings); adds optional fallbackLabels to resolveAgentModelSelection with English defaults. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[App boot] --> B[RootProviders]
B --> C[QueryProvider]
C --> D[I18nProvider]
D --> E{settings.language}
E -->|system| F[getSystemLocales]
F --> G[resolveSupportedLocale]
G -->|zh-* match| H[zh-CN]
G -->|no match| I[en fallback]
E -->|en| I
E -->|zh-CN| H
H --> J[i18n.changeLanguage]
I --> J
J --> K[I18nextProvider]
K --> L[App children - useTranslation hooks]
M[AppSettings storage] -->|language field| E
N[AsyncStorage] <-->|persist / load| M
Reviews (13): Last reviewed commit: "feat: translate sessions and agent list ..." | Re-trigger Greptile
| for (const locale of systemLocales) { | ||
| const normalized = locale.toLowerCase(); | ||
| if (normalized === "zh" || normalized.startsWith("zh-")) { | ||
| return "zh-CN"; | ||
| } | ||
| } |
There was a problem hiding this comment.
Traditional Chinese locales mapped to Simplified Chinese
startsWith("zh-") matches zh-TW, zh-Hant, zh-HK, and other Traditional Chinese BCP-47 tags, silently promoting them all to zh-CN (Simplified Chinese). Traditional Chinese speakers whose system locale is zh-TW would receive Simplified Chinese UI instead of falling back to English — which they may actually prefer. If this mapping is intentional, a comment explaining the decision would help; otherwise, restricting the match to Simplified-Chinese tags (zh-CN, zh-Hans) avoids surprising Traditional Chinese users.
There was a problem hiding this comment.
Fixed in abc61a4. resolveSupportedLocale now maps only generic zh, zh-CN, and zh-Hans* tags to zh-CN; Traditional Chinese tags such as zh-TW, zh-Hant, and zh-HK now fall back to English. Added locale resolver test coverage for those tags.
|
|
||
| const i18n = createInstance(); | ||
|
|
||
| void i18n.use(initReactI18next).init({ |
There was a problem hiding this comment.
Init errors silently discarded
void i18n.use(initReactI18next).init(...) drops the returned promise without .catch(). If initialization fails for any reason (e.g., a plugin conflict or a misconfigured option), the i18n instance will be left in an uninitialized state and all t() calls will silently return the raw translation keys. Attaching an error handler (even a console.error) would make failures detectable in development.
There was a problem hiding this comment.
Fixed in abc61a4. i18next initialization is now wrapped with observeI18nInit(...), which attaches a catch handler and reports initialization failures. Added init.test.ts coverage for reporting rejected init promises.
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
# Conflicts: # packages/app/src/composer/agent-controls/index.tsx # packages/app/src/composer/index.tsx






Linked issue
Fixes #273.
Fixes #1069.
Fixes #1162.
This PR covers the staged client i18n framework and the current client-owned UI migration through Batch 4Z. The remaining untranslated text is intentionally outside client-owned UI copy: agent/daemon/protocol output, terminal/log/code/user content, provider/catalog metadata, shortcut key names, runtime enum values, file paths, branch/PR names, URLs, and raw server/runtime errors.
Design and implementation plan are included in:
docs/superpowers/specs/2026-06-01-client-i18n-design.mddocs/superpowers/plans/2026-06-01-client-i18n.mddocs/superpowers/specs/2026-06-02-full-client-ui-i18n-design.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-1.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-2.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-3a.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-3b.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-4a.mddocs/superpowers/plans/2026-06-02-full-client-ui-i18n-batch-4b.mdType of change
What does this PR do
Adds client i18n infrastructure and migrates the current client-owned UI copy:
useTranslation()/t(...); pure helpers, module-level utilities, stores, policies, and non-React fallbacks use directi18n.t(...)where a hook cannot be used.docs/i18n.md.Provider/model names, provider catalog metadata, provider-defined labels/descriptions, project/host/workspace/user labels, script names and commands, diagnostic output, pairing URLs, endpoint values, protocol parser errors, daemon connection details, file paths, URLs, branch names, PR titles/bodies, check names, workflow names, diff contents, commands, logs, terminal output, shortcut key names, shortcut combos, binding IDs, action IDs, agent output, raw runtime/server error details, caller-provided override labels, and protocol/server diagnostics remain untranslated by design.
How did you verify it
Local verification run on
feat/client-i18n:ar/es/fr/rulocales, missing resource files, and fallback-heavy generated resources.node node_modules/vitest/vitest.mjs run packages/app/src/i18n/locales.test.ts packages/app/src/i18n/sync-language.test.ts packages/app/src/i18n/init.test.ts packages/app/src/i18n/resources.test.ts packages/app/src/composer/actions.test.ts packages/app/src/composer/submit.test.ts packages/app/src/client-slash-commands/index.test.ts packages/app/src/git/policy.test.ts packages/app/src/panels/agent-panel-descriptor.test.tsx packages/app/src/composer/agent-controls/utils.test.ts --bail=1passed: 10 test files, 133 tests.node node_modules/@typescript/native-preview/bin/tsgo.js --noEmit -p packages/app/tsconfig.json --pretty falsepassed.node_modules/oxlint/bin/oxlintpassed with 0 warnings and 0 errors.node_modules/oxfmt/bin/oxfmt --check docs/i18n.md packages/app/src/i18npassed.git diff --checkpassed./tmp/paseo-i18n-screenshots/:settings-general-english.pngsettings-language-menu-un-official.pngsettings-general-spanish.pngsettings-general-french.pngsettings-general-russian.pngsettings-general-arabic.pngadb,emulator, andxcrunare absent).Current local npm wrapper scripts could not resolve their binaries in this install:
npm run test --workspace=@getpaseo/app -- <targeted files>failed before running tests withsh: 1: vitest: not found.npm run typecheck --workspace=@getpaseo/appfailed before typecheck withsh: 1: tsgo: not found.npm run lint -- packages/app/src/i18n/resources/en.tsfailed before lint withsh: 1: oxlint: not found.npm run format:check:files -- docs/i18n.md packages/app/src/i18n/resources/en.tsfailed before format check withsh: 1: oxfmt: not found.Checklist
npm run typecheckpasses or an equivalent direct typecheck command passednpm run lintpasses or an equivalent direct lint command passednpm run formatran (or equivalent direct formatter check passed)