feat(i18n): add English and Simplified Chinese localization - #181
Open
squarepots wants to merge 121 commits into
Open
squarepots wants to merge 121 commits into
squarepots wants to merge 121 commits into
Conversation
squarepots
force-pushed
the
feat/i18n-foundation
branch
from
September 23, 2026 09:57
2a46320 to
9af558c
Compare
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.
中文
实现状态
本 PR 完成 Codex Switcher 的双语本地化基础,并基于最终依赖栈 #180、#182、#185、#184、#186 和 #183 完成整合。
AppSettings.ui_language_preference作为唯一持久化 authority,支持System default、English、简体中文;解析后的en-US/zh-CN同步到主窗口、托盘 webview、原生应用菜单和原生托盘菜单。Browser default、English、简体中文。当前 JS session 的 in-memory preference 是唯一 semantic authority;localStorage 只做尽力持久化。显式选择先更新内存,即使 storage 不可用,React、设置 picker 和 web-secret prompt 也保持一致;Browser default才按navigator.languages的第一个受支持语言解析,且不会写入桌面设置。initialize_app_settings()决定:新安装持久化 System,已有 pre-localization 安装及缺少语言字段的 legacy settings 持久化 English,显式偏好和 legacylanguage字段保持不变。普通 runtime read 只读取AppSettings;缺失 settings 时固定使用 English safe fallback,绝不再依据accounts.json重新推断语言。设置写入继续复用 locked/atomic persistence。zh-CN、zh_CN、zh-Hans、zh-Hans-*、zh-SG,并让zh-TW、zh-HK、zh-MO、zh-Hant*、裸zh回退到 English。DisplaySettings,先尽力投影 native menu/tray,再通过现有app-settings-changed机制通知 webview;投影失败不会伪报持久化失败。document.documentElement.lang仅是已解析语言的 projection,不是 browser authority。597b970)、fix(storage): make state writes atomic and single-writer #182(2fadfc7)、fix(auth): align OAuth refresh policy with Codex #185(7aa083b)、fix(auth): make activation a single transaction #184(5a606f6)、feat(warmup): persist host-owned scheduling policy #186(c66cc5e)和 feat(backup): add user-passphrase encryption #183(d52e172)验证,保留 web boundary、passphrase backup、auth transaction、OAuth refresh 和 Rust-owned warm-up scheduler 的既有行为。验证
pnpm test:i18n:8 项通过pnpm test:desktop-reopen:7 项通过pnpm test:browser-runtime:2 项通过pnpm test:close-preference:3 项通过pnpm test:reset-credits:3 项通过pnpm test:warmup-policy:1 项通过pnpm test:web-boundary:1 项通过pnpm test:backup-passphrase:3 项通过pnpm build:通过cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check:通过cargo check --locked --manifest-path src-tauri/Cargo.toml:通过cargo test --locked --manifest-path src-tauri/Cargo.toml:101 项通过git diff --check:通过Closes #157
English
Implementation status
This PR completes the bilingual localization foundation for Codex Switcher on the final dependency stack: #180, #182, #185, #184, #186, and #183.
AppSettings.ui_language_preference, withSystem default,English, and简体中文. The resolveden-US/zh-CNlanguage is projected to the main window, tray webview, native application menu, and native tray menu.Browser default,English, and简体中文. The current JS session in-memory preference is the single semantic authority; localStorage is best-effort persistence only. Explicit choices update memory first, so React, the settings picker, and the web-secret prompt stay aligned even when storage is unavailable. OnlyBrowser defaultresolves the first supported entry fromnavigator.languages, and it never writes desktop settings.initialize_app_settings(): new installs persist System; existing pre-localization installs and legacy settings without language persist English; explicit preferences and the legacylanguagefield survive. Ordinary runtime reads only readAppSettings; a missing settings file always uses the English safe fallback and never re-infers language fromaccounts.json. Settings writes reuse locked/atomic persistence.zh-CN,zh_CN,zh-Hans,zh-Hans-*, andzh-SG;zh-TW,zh-HK,zh-MO,zh-Hant*, and barezhfall back to English.DisplaySettings, attempt native menu/tray projection before notifying webviews through the existingapp-settings-changedmechanism, and do not report persistence failure when a projection fails.document.documentElement.langis only a projection of the resolved language, never browser authority.597b970), fix(storage): make state writes atomic and single-writer #182 (2fadfc7), fix(auth): align OAuth refresh policy with Codex #185 (7aa083b), fix(auth): make activation a single transaction #184 (5a606f6), feat(warmup): persist host-owned scheduling policy #186 (c66cc5e), and feat(backup): add user-passphrase encryption #183 (d52e172), preserving the existing web boundary, passphrase backup, auth transaction, OAuth refresh, and Rust-owned warm-up scheduler behavior.Validation
pnpm test:i18n: 8 passedpnpm test:desktop-reopen: 7 passedpnpm test:browser-runtime: 2 passedpnpm test:close-preference: 3 passedpnpm test:reset-credits: 3 passedpnpm test:warmup-policy: 1 passedpnpm test:web-boundary: 1 passedpnpm test:backup-passphrase: 3 passedpnpm build: passedcargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check: passedcargo check --locked --manifest-path src-tauri/Cargo.toml: passedcargo test --locked --manifest-path src-tauri/Cargo.toml: 101 passedgit diff --check: passedCloses #157
Restores #168 after the source fork was accidentally deleted.
Maintenance triage — 2026-09-30
Prerequisite PRs: #178, #180, #182, #185, #184, #186, #183.