Repository navigation
feat(i18n): localization foundation and language picker - #57
Conversation
|
@noahbclarkson I'm a native Simplified Chinese speaker — happy to review, done. The translation is in good shape: terminology is consistent (Appearance = 外观, One suggestion, purely idiomatic polish (not a bug): Two things worth flagging from your own "Known gaps" section, since they hit
|
Adds `rgitui_i18n` and wires it into settings, so a language can be chosen and applied without a restart. This is the infrastructure only — the Appearance settings panel is converted as the working example; the other ~1500 user-facing strings are still English literals. English is the source of truth in `src/en.rs` rather than a JSON asset, for the same reason the built-in themes are Rust: it is always present and cannot drift, so any missing translation has something to fall back to. Translations are JSON under `assets/locales/`, embedded at build time, with user overrides from the config directory so a translator can iterate against a release build. The catalogue is a process-wide RwLock rather than a GPUI global, because error strings are built on background threads and need translating too. The tradeoff is that GPUI cannot know a language change dirties the frame, so `set_language` must be followed by `cx.refresh_windows()`. `t!` and `tp!` return `SharedString`, which every `rgitui_ui` builder already accepts — converting a call site is a one-line change. Locale files are validated by tests: unknown keys fail (they would silently never render), placeholders must survive translation, and plural forms must be declared in pairs. Missing keys are deliberately allowed so partial translations are worth shipping. Simplified Chinese ships as the first translation and needs native review. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the loader
Keys: t!, tp! and the new key! take literal keys and evaluate const
assertions against the English table, so a key missing from en.rs, or named
arguments that do not match the English message's placeholders, fail the
build at the call site instead of rendering the raw key. tp! fills {count}
itself. en.rs is one `key => message` line per entry, and an unsorted or
duplicated table fails the build naming the first key out of place, which is
what lets the lookup be a binary search. A test reports English keys that no
code uses.
Language changes: set_language takes the App, refreshes every window and
replaces an ActiveLanguage global, so callers no longer have to remember
refresh_windows, and views that keep translated text outside render can
observe it. The settings view reads the selection from rgitui_i18n instead of
keeping its own copy.
Matching: Traditional Chinese systems (zh-TW, zh-HK, zh-MO, zh-Hant) matched
the shipped zh-CN on the primary subtag alone and got Simplified characters;
matching now requires the same script, stated or implied. POSIX tags such as
zh_CN.UTF-8 are accepted. The system language and per-locale missing counts
are read once at init rather than on every render, and the count no longer
includes plural forms a locale's rule never selects, so a complete zh-CN
stops reporting one missing string.
Loader: user locale files must be regular files under 1 MiB, are read in path
order, and are layered over a shipped locale with the same id instead of
replacing it; keys English does not define are logged. An unknown plural_rule
is an error rather than silently becoming one_other. Shipped locales must use
exactly the English placeholders and only the plural forms their rule selects.
The UI font gains Simplified Chinese fallback families when the UI is
Simplified Chinese, and only then, so Japanese and Traditional Chinese text in
an English UI keeps the platform's glyph choice. The cached font is keyed on
the locale as well as the family.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3893905 to
4bc9034
Compare
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Foundation for #55: the
rgitui_i18ncrate and the language setting. #89's Simplified Chinese translations are being ported onto this in a follow-up PR (stacked on this branch), and git operation messages in another after that.Rebased onto main (0.5.0) and reworked after reviewing it against #89. The original commit is kept as the first of two; the second carries the review fixes.
What works
settings.jsonfiles follow the OS language. A missinglanguagekey defaults tosystem.Design
English is Rust, translations are JSON.
crates/rgitui_i18n/src/en.rsis the source of truth, onekey => messageline per entry. Translations live inassets/locales/*.json, embedded at build time. User files in<config>/rgitui/locales/are layered over a shipped locale with the same id, so a translator can fix a few strings against a release build.Keys are checked at compile time.
t!,tp!andkey!take literal keys and expand toconstassertions against the English table:This keeps #89's main advantage (rustc catches key typos) without putting translations in Rust. Lookup is a binary search. An unsorted or duplicated
en.rsfails the build and names the first key out of place.key!checks a key stored as data, for menus and filter lists that are translated later.set_language(cx, …)refreshes every window and replaces anActiveLanguageGPUI global. Anything translated inrenderupdates on its own. Views that keep text outsiderender(input placeholders) observeActiveLanguage, and only that, instead of every settings change.Plurals:
tp!("key", n)picks.one/.otherunder the locale's rule and fills{count}itself.Changes since the original commit
zh-CNon the primary subtag. Matching now requires the same script, stated or implied. POSIX tags (zh_CN.UTF-8) are accepted.*.jsoncan't hang startup.plural_ruleis an error instead of silently becomingone_other.rgitui_i18ninstead of keeping a second copy. "Detected:" shows the matched language's own name, or says the system language has no translation yet.{count} 条尚未翻译.Verified
cargo fmt --check: clean.cargo clippy --workspace --all-targets -D warnings: clean.cargo test -p rgitui_i18n -p rgitui_settings -p rgitui_workspace: 50 + 31 + 771 passed.Known gaps
🤖 Generated with Claude Code