Skip to content

feat(i18n): system-locale detection + 11 languages with Arabic RTL - #7

Merged
Wangnov merged 6 commits into
mainfrom
claude/compassionate-wilbur-cb6c63
Jun 7, 2026
Merged

Wangnov merged 6 commits into
mainfrom
claude/compassionate-wilbur-cb6c63

Conversation

@Wangnov

@Wangnov Wangnov commented Jun 7, 2026

Copy link
Copy Markdown
Owner

概述

为应用增加多语言支持:首次启动自动检测系统语言(按系统区域选择,fallback 英语),并在原有简体中文 / 英语基础上新增 9 种语言,共 11 种。

语言(11 种)

English(fallback) · 简体中文 · 繁體中文 · 日本語 · 한국어 · Français · Deutsch · Español · Português · Русский · العربية

"印度语"按需求用英语覆盖(印度软件圈通用英语),故未单列印地语;"迪拜用的语言"= 阿拉伯语,已做完整 RTL。

主要改动

  • 系统语言检测 (detectLang / matchTag):遍历 navigator.languages 做 BCP-47 最近匹配,中文按地区/字形分简繁(zh-TW/HK/MO/Hant → 繁中),未命中回退英语;用户在设置里的选择存 localStorage,优先于自动检测。
  • 阿拉伯语完整 RTL:I18nProvider 切语言时同步 document.documentElement.dir,布局主要靠 flexbox + 逻辑属性(text-align: start/end、padding-inline)自动镜像,少数物理元素(toggle 滑块、返回箭头、chevron)用 [dir="rtl"] 翻转;版本号 / URL / 百分比强制 direction: ltr 不被卷入。
  • 设置 UI:语言选择从放不下 11 项的分段控件改为数据驱动的 2 列网格(LANGS 元数据驱动),每项以母语名显示。
  • 翻译:每种语言 119 条文案,key 完整性由 Record<Key, string> 类型强制——漏译会直接编译失败。t() 增加英语兜底链。

验证

  • npm run build(tsc --noEmit + vite build)通过
  • 语言检测 31/31 用例通过(含 zh-Hant-HK→繁中、pt-PT→pt-BR、ar-AE→ar、hi-IN→en 兜底、多语言偏好取首个支持项)
  • 实机预览:11 项语言网格渲染正确、切阿拉伯语后整页 RTL 镜像、localStorage 持久化均正常

备注

翻译由 AI 生成,占位符 {version} 等、Codex/OpenAI/MSIX 等专名、key 完整性均已校验;ar/ja/ko/ru 等的语气与专业措辞建议上线前由母语者快速复核。

🤖 Generated with Claude Code

Wangnov and others added 6 commits June 8, 2026 01:18
Walk navigator.languages and match the closest supported locale, falling back to English. Chinese splits into Simplified vs Traditional by region/script (zh-TW/HK/MO/Hant). The user's saved choice in localStorage wins over detection.

Adds zh-TW, ja, ko, fr, de, es, pt-BR, ru and ar alongside the existing zh-CN/en. Arabic drives full RTL via the provider setting <html dir>, and t() now falls back to the English string for any missing key.
A 2-column .langgrid replaces the segmented control, which can't fit 11 languages in one row. RTL flips the few physical bits flexbox/logical properties don't handle automatically (toggle knob, back arrow, chevron); version strings, URLs and the % readout stay LTR.
Render the picker from LANGS metadata (endonym labels) instead of a hardcoded 2-item list, and use logical margins so the recommended tag mirrors correctly under RTL.
Versions, download sizes, the % readout and repo URL kept reordering inside RTL copy because only .input.mono and .pctbig were isolated. Pure-LTR spans (.ver/.dlmeta/.pct/.pctbig) now get an isolated LTR direction, and mixed prose (.sub/.flow/.foot/.rsub/.banner span) uses unicode-bidi: plaintext so each run picks its own direction — Arabic stays RTL, embedded versions and URLs stay LTR. Addresses codex review [P2].
Export matchTag and factor the detectLang choice into a pure, global-free
pickLang(saved, prefs) so the BCP-47 → supported-language mapping is unit
testable. Add vitest and cover the tricky cases: zh-Hant-HK/zh-MO → zh-TW,
pt-PT → pt-BR, region tags → primary language, unsupported → null, saved
choice precedence, first-supported-preference, and English fallback.
@Wangnov
Wangnov force-pushed the claude/compassionate-wilbur-cb6c63 branch from b9e0adb to b39730e Compare June 7, 2026 17:18
@Wangnov
Wangnov merged commit 996fe15 into main Jun 7, 2026
3 checks passed
@Wangnov
Wangnov deleted the claude/compassionate-wilbur-cb6c63 branch June 7, 2026 17:27
Wangnov added a commit that referenced this pull request Jun 7, 2026
…fixes folded in)

Lets Windows users choose where the portable Codex build installs, persisted
across uninstalls. The backend gains a validated `install_root` (migrated from
old settings) used across plan/stage/status/adopt/perform/uninstall; the UI adds
a native folder picker (invoked through a Rust command), a Settings location row,
and a fresh-install location sheet.

Rebased onto main after the i18n PR (#7) merged, so the previously duplicated
install-location strings now come from #7 only. The unused npm
@tauri-apps/plugin-dialog dependency is dropped — the picker goes through a Rust
command and nothing imports the JS binding (the Rust tauri-plugin-dialog stays).

Review fixes folded in:
- validate_install_root_path no longer creates the target directory to probe it
  (it probes the nearest existing ancestor), so selecting/resetting a location
  no longer leaves folders on disk; the dir is created at install time.
- the chosen install root is persisted only AFTER a successful install, and the
  Browse flow is one-shot, so a failed/cancelled attempt keeps the saved default.
- a managed portable build is gracefully closed before MSIX sideload, instead of
  potentially being left running after the switch.
- uninstall and status use is_managed_build (path + build) like the macOS path,
  not path-only is_managed — safer now that the install root is user-configurable
  and paths can be reused.

Co-authored-by: Wangnov <w15365132161@gmail.com>
Wangnov added a commit that referenced this pull request Jun 7, 2026
…fixes folded in) (#8)

Lets Windows users choose where the portable Codex build installs, persisted
across uninstalls. The backend gains a validated `install_root` (migrated from
old settings) used across plan/stage/status/adopt/perform/uninstall; the UI adds
a native folder picker (invoked through a Rust command), a Settings location row,
and a fresh-install location sheet.

Rebased onto main after the i18n PR (#7) merged, so the previously duplicated
install-location strings now come from #7 only. The unused npm
@tauri-apps/plugin-dialog dependency is dropped — the picker goes through a Rust
command and nothing imports the JS binding (the Rust tauri-plugin-dialog stays).

Review fixes folded in:
- validate_install_root_path no longer creates the target directory to probe it
  (it probes the nearest existing ancestor), so selecting/resetting a location
  no longer leaves folders on disk; the dir is created at install time.
- the chosen install root is persisted only AFTER a successful install, and the
  Browse flow is one-shot, so a failed/cancelled attempt keeps the saved default.
- a managed portable build is gracefully closed before MSIX sideload, instead of
  potentially being left running after the switch.
- uninstall and status use is_managed_build (path + build) like the macOS path,
  not path-only is_managed — safer now that the install root is user-configurable
  and paths can be reused.
Wangnov added a commit that referenced this pull request Jun 7, 2026
Ships the i18n (11 languages + Arabic RTL, #7) and Windows portable install
location picker (#8) work on top of the released v0.1.0. Bumps all version
sources in lockstep — package.json, package-lock.json, tauri.conf.json,
Cargo.toml, Cargo.lock — so the built app version matches the v0.1.1 tag that
drives latest.json (mismatch would loop the updater).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant