Skip to content

feat: add i18n infrastructure with Chinese (Simplified) translation - #84

Open
lunaship wants to merge 2 commits into
hardbeat920:mainfrom
lunaship:feat/i18n-zh-CN
Open

feat: add i18n infrastructure with Chinese (Simplified) translation#84
lunaship wants to merge 2 commits into
hardbeat920:mainfrom
lunaship:feat/i18n-zh-CN

Conversation

@lunaship

@lunaship lunaship commented Sep 5, 2026

Copy link
Copy Markdown

Summary

Adds internationalization (i18n) support with a complete Chinese (Simplified) translation. The i18n system is lightweight (zero dependencies) and designed for easy extension to other languages.

What's included

i18n infrastructure

  • src/lib/i18n.ts — Core module with t(), tNamed(), tPlural(), pluralKey() APIs
  • src/lib/bootLocale.ts — sets the app locale; imported FIRST in main.tsx so module-evaluation-time t() calls (model catalogs) translate correctly
  • src/lib/i18n.test.ts — Unit tests (8 tests, all passing)
  • src/lib/locales/en.ts — English locale template (1021 keys, identity mapping)
  • src/lib/locales/zh-CN.ts — Chinese Simplified translation (1021 entries, key sets aligned)

Translation coverage

  • ~120 source files modified with t() calls
  • All user-visible UI strings: sidebar, title bar, composer, settings, file tree, git panel, inbox, notes, search, terminal, diff views, dialogs, error messages
  • Model settings catalogs (Claude / Codex / Cursor / OpenCode / fx) and transcript tool-title fallbacks now go through t()
  • Native macOS menu bar translated to Chinese; merged with upstream main (Windows support, notifications, UI scaling, transcript folding) with the new surfaces translated too
  • Simplified Chinese README added as README.zh-CN.md, linked from the top of the English README; upstream docs stay in English

Design decisions

  • English strings as keys — Adding a new language requires only creating a locale file; no code changes needed
  • Default locale is "en" — Users who don't switch languages see zero difference. The app sets zh-CN via bootLocale.ts, imported before any module that calls t() at evaluation time
  • Lazy-evaluated functionsgetSettingsSections(), getKeybindings(), getHarnessTitle() ensure translations apply correctly at render time
  • Not translated — LLM prompt strings (sent to AI models), brand names, technical identifiers

How to add a new language

  1. Create src/lib/locales/xx.ts mapping English keys to translated strings
  2. Register it in src/lib/i18n.ts
  3. Call setLocale("xx") at app startup

Testing

✅ TypeScript: 0 errors
✅ Tests: 120 files / 1254 tests passing
✅ Rust: cargo fmt / clippy / test clean
✅ Build: Tauri desktop app builds successfully

Screenshots

The translation covers all settings sections, sidebar, composer, and every user-facing string in the app.

- Add lightweight i18n module (src/lib/i18n.ts) with t(), tNamed(),
  tPlural(), and pluralKey() APIs - zero external dependencies
- Add English locale template (src/lib/locales/en.ts) as reference
- Add Chinese Simplified locale (src/lib/locales/zh-CN.ts) with 986
  translated strings covering all UI components
- Add unit tests for i18n module (src/lib/i18n.test.ts)
- Replace hardcoded English strings with t() calls across ~110 files,
  including model settings catalogs and transcript tool-title fallbacks
- Import bootLocale first in main.tsx so setLocale("zh-CN") runs before
  module-evaluation-time t() calls; models.ts and harness catalogs
  otherwise froze English labels
- Localize the native macOS menu bar to Chinese (labels only; dispatch
  matches on item IDs)
- Add README.zh-CN.md with a language switcher; upstream docs stay in
  English
- Use lazy-evaluated functions (getSettingsSections, getKeybindings,
  getHarnessTitle, getRuntimeModeLabel/Hint) to ensure translations
  apply correctly at render time
- Default locale is 'en' (identity mapping) for backward compatibility

Translation scope: all user-visible UI strings including sidebar,
title bar, composer, settings, file tree, git panel, inbox, notes,
search, terminal, diff views, dialogs, and error messages.

Not translated: LLM prompt strings (sent to AI models, not shown to
users), brand names (MonoCode, Claude, GitHub, Linear), and technical
identifiers.
…olding

Resolves conflicts with 64fb6d3..2bc69af and extends zh-CN coverage to
the new surfaces:
- menu bar and settings zoom items (放大/缩小/重置缩放)
- notifications settings row and window-close confirmation
- transcript work summaries (editing/reading/running…) via t()
- native notification "Show" action buttons (显示)
- fix hardcoded English "for" in the working-duration template

Locales now 1021 keys, en/zh aligned; tsc, vitest (1284), cargo
(fmt/clippy/test) and the Tauri build all pass.
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