feat: add English/Chinese language toggle for the manager UI#1264
Open
thynomex wants to merge 3 commits into
Open
feat: add English/Chinese language toggle for the manager UI#1264thynomex wants to merge 3 commits into
thynomex wants to merge 3 commits into
Conversation
The manager app (codex-plus-manager) was Chinese-only. This adds a source-text-keyed i18n layer so every user-facing string can render in English, with a topbar toggle to switch languages. - src/i18n.ts: t()/tf() helpers keyed by the original Chinese text; Chinese stays the zero-overhead default. Language is persisted to localStorage and the webview reloads on switch so module-level literals (route tables, preset labels) re-evaluate under the new lang. - src/i18n-en.ts: English dictionary (539 plain + 39 interpolated keys). - App.tsx / ProviderPresetSelector.tsx: every Chinese literal wrapped via an AST codemod (tools/i18n-codemod.mjs) — position-based edits that preserve formatting; comments and object keys left untouched. - tools/i18n-verify.mjs: scans real t()/tf() call sites and fails if the dictionary has any missing or stale key. - Added a Languages toggle button beside the theme toggle in the topbar. Verified: tsc --noEmit clean, vite build succeeds, existing unit tests pass, dictionary matches every call site.
…tions showNotice now wraps the message body with t() so Rust backend messages are translated at the display layer. Adds EN_BACKEND (exact-match) and EN_BACKEND_PATTERNS (regex) dictionaries covering all commands.rs strings.
…is active Add update_tray_labels Tauri command that rebuilds the tray context menu with translated labels and updates the window title. The frontend invokes it on startup when the language is set to English.
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.
Summary
Adds an English / Chinese language toggle to the Codex++ manager UI. The app is authored Chinese-first; this PR makes the entire manager frontend translatable without changing any behaviour, and adds a one-click toggle in the top bar (next to the theme toggle).
Chinese remains the default. Nothing changes for existing users unless they flip the toggle.
How it works
A lightweight, source-text-keyed i18n layer (no key renaming, minimal diff noise):
src/i18n.ts— runtime.t("中文")returns the English translation when the active language is English, otherwise the original Chinese (zero-overhead default).tf("前缀 {0}", [expr])handles interpolated strings, preserving argument order.src/i18n-en.ts— the English dictionary (537 plain strings + 39 interpolated templates), keyed by the original Chinese source text.App.tsxandProviderPresetSelector.tsxis wrapped witht()/tf().Why a reload on toggle: many Chinese literals live in module-level constants (route tables, preset/category labels, status maps) that evaluate once at import. Switching language persists the choice to
localStorageand reloads the webview, so every literal — module-level and render-level — re-evaluates under the new language. For a local Tauri window this is instant.Tooling (for maintainability)
To keep the translation layer honest as the UI evolves, two scripts are included under
tools/:i18n-codemod.mjs— AST-based (uses the repo's own TypeScript). Wraps every CJK string/template/JSX-text precisely via position-based edits, so formatting is untouched. Re-runnable and idempotent (won't double-wrap).i18n-verify.mjs— scans actualt()/tf()call sites and fails if the dictionary has any missing or stale key. Run it in CI or before a release to guarantee no string is left untranslated or orphaned.Scope
Frontend UI strings only. Backend (
commands.rs) result messages are out of scope for this PR and can follow in a second pass if desired.Verification
npm run check(tsc) — cleannpm run vite:build— succeeds (1607 modules)node --test(model-windows unit tests) — 9/9 passnode tools/i18n-verify.mjs— dictionary matches call sites exactlyNotes for reviewers
model-windows.tsis intentionally not wrapped: its only Chinese string is a test-only error message, andmodel-windows.test.tsimports the module in isolation undernode --testwhere an@/i18nimport wouldn't resolve.