#613

feat(i18n): complete bilingual UI support (en/zh-CN) — closes #567

Openwalieanwants to merge intofrom

Summary

Completes bilingual (en/zh-CN) UI support for #567. This PR is the third phase of the i18n work (previous phases landed in #584-era commits; full phase 1+2 content is in the first commit of this branch).

Phase 1+2 (checkpoint 1654d66)

  • 21 i18n namespaces, en + zh-CN locale files
  • React Intl integration (i18next + react-i18next), automatic language detection
  • Language switching in Settings → Display & Sound (persisted)

Phase 3 (this PR, d218bb0)

  1. Explicit Intl locales — Intl.RelativeTimeFormat/NumberFormat/DateTimeFormat calls in src/utils/time.ts and src/features/home/homeFormatters.ts now pass i18n.language instead of relying on the system locale. This fixes 6 pre-existing test failures on machines where Node's default locale is zh-CN (e.g. Chinese Windows), without touching assertions.
  2. Rust-side verification — src-tauri/src/i18n.rs gains 6 unit tests asserting the tray menu labels (File/View/Settings) render correctly in both en and zh-CN.
  3. Remaining string scan cleanup — threadStatus.ts now returns i18n keys (workspaces:statusRunning / statusReviewing / statusIdle), rendered via t() in WorkspaceHomeHistory.tsx; platformPaths.ts translates its own file-manager action strings (files:revealInFileManager / showInFileManager / openInFileManager with {{fileManager}} interpolation; "Finder" / "File Explorer" stay literal by design).
  4. i18next-parser integration — i18next-parser@^9.0.2 + i18next-parser.config.cjs + npm run extract:i18n script. Locale files normalized: BOM stripped, \uXXXX escapes inlined, 16 plural base keys backfilled from _one values (i18next v24/v4 plural rules). Extraction is idempotent.
  5. Docs — docs/i18n-phase3-plan.md (extraction workflow, known false positives to clean, leftovers, PR handoff) + README Localization section.

Verification

  • Full suite: 1032/1032 passed (baseline had 6 failures, all fixed by item 1)
  • i18n parity tests: 31/31 passed
  • npm run typecheck: clean
  • vite build: ok (pre-existing chunk-size warning only)

Known limitations

  • Rust side: cargo check/cargo test is currently blocked upstream by #599 (whisper-rs build failure on Windows); the new Rust tests were reviewed manually and will be runnable once #599 is resolved. Runtime language switching for the native tray menu stays as designed (menu text is fixed at startup; restart to apply a language change).
  • i18next-parser is deprecated upstream in favor of i18next-cli (v9.0.2 still works); flagged for a future upgrade.
  • optionKeyLabel / metaKeyLabel are false-positive keys the parser regenerates from local variable names in useSettingsViewOrchestration.ts; they must be deleted after each extract:i18n run (documented).

Activity

30
chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d218bb0ed5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

waliean2mo ago

Addressed in 9bb3302: settingsViewConstants.ts no longer evaluates i18n.t() at module load. DICTATION_MODELS now stores labelKey/noteKey, composer presets and section labels store key strings only; each consumer (SettingsDictationSection, SettingsComposerSection, SettingsView) renders through t() from useTranslation, so these labels now update immediately when the Display language is switched. Verified: 1032/1032 tests pass, typecheck clean.

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9bb3302af1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

waliean2mo ago

Both review points addressed in 9682f3d:

1. v4 plural forms — added _one/_other variants for all 11 {{count}} keys missing them (files: countMatches/countModified/countFiles, git: openCount, home: windowHours/windowMinutes/statRunsInLast7Days/statAcrossRuns/statActiveDaysInLast7, prompts: metaHasPrompts, workspaces: moreErrors) in both en and zh-CN, and removed the 5 legacy v3 _plural keys. A full-suite scan confirms zero remaining v3 _plural keys and zero {{count}} base keys without _other in either locale. English plural forms are distinct where the language requires (e.g. "{{count}} matches"); zh-CN uses identical _one/_other values as Chinese does not inflect.

2. Live docs — replaced the three historical phase notes (i18n-phase1/2/3-plan.md) with a single live-state guide at docs/localization.md covering the current architecture (21 namespaces, en/zh-CN), v4 plural rules, the extract:i18n workflow including the optionKeyLabel/metaKeyLabel false-positive cleanup step, file format conventions (BOM warning), the module-scope i18n.t() ban, and current limitations. No dangling references (verified: only the phase docs referenced each other).

Verification: 1032/1032 tests pass, i18n parity 31/31.

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9682f3df02

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd687d75d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

waliean2mo ago

All three addressed in 1d24232:

  1. Native menu/tray (src-tauri/src/lib.rs + i18n.rs): the menu and the macOS tray now resolve the persisted language through the new i18n::resolve_ui_language, which uses the saved preference when present and otherwise falls back to the host locale via the sys-locale crate (zh* -> zh-CN, else en). This matches the frontend detectInitialLanguage semantics, so on first launch on a zh-CN host the native menu/tray are Chinese instead of English. A saved preference still wins afterwards.

  2. Composer follow-up hint (Composer.tsx + composer.json): behavior now interpolates the translated composer:steer/composer:queue labels, and action uses two new localized phrases composer:followUpActionSteer ("steer" / "引导") and followUpActionQueue ("queue" / "排队"). The zh-CN followUpDefault template drops the awkward "以" so it reads naturally with Chinese verbs. No mixed-language hint anymore.

  3. Rust test assertion (src-tauri/src/types.rs): app_settings_defaults_from_empty_json now expects "" for the no-preference default, consistent with the new semantics.

Verified: 1032/1032 tests pass, typecheck clean. Rust changes parse cleanly via cargo fmt; cargo check remains blocked by the pre-existing upstream whisper-rs build failure (#599). sys-locale 0.3 is a pure-Rust, dependency-free crate (Windows uses GetUserDefaultUILanguage, macOS CoreFoundation, Unix env vars), consistent with the host-locale detection approach.

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d24232294

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

waliean2mo ago

All four addressed in 31db2d4:

  1. P1 i18n.t binding (4 files): const { t } = i18n module-level destructuring in usageLabels.ts, homeFormatters.ts, homeUsageViewModel.ts and ComposerAttachments.tsx dropped the i18next instance's this, so the first t(...) call at render threw. All four now use i18n.t.bind(i18n); since they're plain functions evaluated per call (no memoized results), language switching still applies immediately. (Test suite didn't catch it because these modules aren't exercised through their real render paths.) While in this file I also localized the home usage card's hardcoded Updated prefix via the new home:updatedLabel key.

  2. Tray rebuild paths (src-tauri/src/tray.rs): both macOS rebuild entry points — recent-threads update (set_tray_recent_threads) and session usage update (set_tray_session_usage) — now run the saved language through i18n::resolve_ui_language before update_tray_menu, so an empty saved value no longer snaps the tray back to English after the initial Chinese tray was built at startup. The about-window title path in menu.rs::handle_menu_event got the same treatment (including the lock-failure fallback).

  3. Trans placeholder (SettingsGitSection.tsx): settings:git_commit_message_prompt_help contains {{diff}}, so <Trans> treated it as a missing interpolation and dropped it. It now passes values={{ diff: "{diff}" }}, rendering the literal {diff} placeholder again in both locales.

  4. docs/i18n-glossary.md: decision #5 rewritten to describe the current state — Rust menu/tray/about-title are localized via t_rs/t_rs_fmt with host-locale fallback through resolve_ui_language — instead of the stale "not in Phase 1 scope" note.

Verified: 1032/1032 tests pass, typecheck clean, cargo fmt --check clean on the touched Rust files. cargo check remains blocked by the pre-existing upstream whisper-rs failure (#599).

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31db2d4502

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

waliean2mo ago

All three addressed in 4c57a49:

  1. Cargo.lock: committed with the sys-locale v0.3.2 entry (its only dependency, libc, is already in the lock), so locked/reproducible Rust builds are consistent again. Note: sys-locale 0.3.2 itself compiles cleanly — the remaining cargo check errors are all the pre-existing upstream whisper-rs breakage (#599).

  2. zh-CN server_remote_use: now keeps the {{name}} interpolation — "使用 {{name}}" — matching the en resource, so inactive remote buttons and their aria-labels retain the remote-specific context instead of all reading the bare "使用" label.

  3. GitDiffPanel: the pushSyncConflictMessage memo now includes t in its dependency array, so the localized conflict text refreshes on language change even when the push error payload is unchanged.

Verified: 1032/1032 tests pass, typecheck clean.

chatgpt-codex-connector[bot]reviewed2mo ago
chatgpt-codex-connector[bot]2mo ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c57a49db6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".