Skip to content

feat(i18n): add Simplified Chinese (简体中文) language support - #89

Open
VedaChen wants to merge 10 commits into
noahbclarkson:mainfrom
VedaChen:feat/i18n-language
Open

VedaChen wants to merge 10 commits into
noahbclarkson:mainfrom
VedaChen:feat/i18n-language

Conversation

@VedaChen

@VedaChen VedaChen commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a language toggle (English / 简体中文) to Settings → General and translates the full UI into Simplified Chinese.

What changed

Infrastructure

  • Language enum (English / ChineseSimplified) + TrKey enum with 465+ translation keys in rgitui_settings/src/lib.rs
  • Language::tr(key) -> &'static str with English source text locked by unit tests
  • AppSettings.language field; settings version migrated 3 → 4
  • CJK font fallback added to build_ui_font so Chinese characters render correctly
  • Each view observes SettingsState (same pattern as ThemeState) for instant refresh on language switch

Translation coverage (4 phases)

  • Phase 1: Language/TrKey framework + General settings page + sidebar labels
  • Phase 2: Settings window (Theme/AI/Auth), toolbar, status bar, commit panel, confirm dialog, diff, detail panel
  • Phase 3: Home/tab/banners, graph column headers/menus, PRs panel, issues panel, all dialogs, interactive rebase, bisect, tooltips/placeholders
  • Phase 4: AI settings section (commit messages, provider cards, model picker, behaviour toggles), Auth section (profiles, HTTPS/SSH/GPG, how-auth-works), 8 keyboard shortcut descriptions, Git operation error messages

Intentionally NOT translated (per spec)

  • command_palette static labels and commands! doc strings (used by keybindings docs generator)
  • AI prompt templates sent to providers
  • Git-layer internal error strings; brand names (GitHub, GitLab, OpenAI, …)
  • Example/URL placeholders and data-driven tooltips (blame author, timestamps)

Quality gates

  • cargo fmt --all clean
  • cargo clippy --workspace --all-targets -- -D warnings — zero warnings
  • All existing tests pass; every new TrKey covered by non-empty and English-literal-lock tests
  • No dbg! / todo!

noahbclarkson added a commit that referenced this pull request Oct 19, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
noahbclarkson added a commit that referenced this pull request Oct 19, 2026
Ports @VedaChen's translation of the interface from #89 onto rgitui_i18n.
Their call-site work is kept file by file; the TrKey table, the settings
language enum and the git-layer changes are not.

- 469 strings carried over as written, under keys named by the panel that
  shows them (toolbar.push, confirm.force_push, branch_health.merged).
- Every `tr(TrKey::X)` call is now a compile-checked t!("key"); keys held as
  data (graph menu rows, toolbar tooltips, the settings quick reference) use
  key!. Positional `{}` templates filled by chained replacen are named
  placeholders filled in one pass, so user text containing "{}" can no longer
  swallow the next value.
- Sentence fragments joined with format! are whole sentences: "Pending changes
  on {branch}", "HEAD is detached at {commit}", "Return to {branch}",
  "Inspecting worktree: {name} ({branch})", "Failed to load comments: {error}".
  Counts are plurals ("1 file staged", "1 result", "1 commit"), and the four
  DescCount variants are one message built from two plural pieces.
- English words no longer land in Chinese sentences: the PR and issue empty
  states have a message per filter (which also fixes "No all issues found"),
  and the AI section translates its credential store names, catalogue ages,
  "verified" suffix and model-list footer.
- Relative dates in the graph, blame, history and detail panels go through
  shared time.* messages.
- Pill groups select by value instead of comparing the clicked label against
  both languages. The confirm dialog returns its translated label directly.

Dropped from #89:
- The 27 observe_global::<SettingsState> redraw observers. A language change
  refreshes every window already, and those observers redrew the main window
  on every settings write, including each move of the settings window.
- The placeholder resets in render. TextInput::set_placeholder_message takes a
  key and translates it when drawn, so inputs follow the language with no
  observer and no per-frame work.
- The General-page language dropdown, which duplicated the Appearance picker.
- The four #[allow(dead_code)] English label functions; the label functions
  that render are the ones tested now.
- description_tr's hard-coded Chinese in the keymap registry; the settings
  quick reference has message keys instead, with a test that keeps their
  English equal to each command's doc comment.

Terminology, from review of #89: rebase "pick" is 使用 (拣选 is cherry-pick),
bisect good/bad is 正常/有问题 everywhere with the menu saying 二分查找, the
"Open" filter is 打开, a stash message is 储藏说明, and the interface uses 你.

The working-tree row's labels and badges and the diff header were English on
the main screen in #89 too and are translated here. The settings window
rebuilds the AI model picker when the language changes, since the picker
keeps the notes it was handed.

Confirmation dialogs, which #89 left in English apart from their buttons,
build their title and warning from the action in render, so call sites pass
only the action. Aborting names the operation ("Abort Rebase") through
`ConfirmAction::AbortOperation(RepoState)`, which replaces `AbortMerge`.

Co-authored-by: chenjunjie <zmiss2024@foxmail.com>
Co-authored-by: VedaChen <251404213+VedaChen@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants