Skip to content

feat(desktop): add i18n with zh-CN translations - #37276

Closed
falser101 wants to merge 1 commit into
NousResearch:mainfrom
falser101:feat/i18n-zh-cn-settings
Closed

feat(desktop): add i18n with zh-CN translations#37276
falser101 wants to merge 1 commit into
NousResearch:mainfrom
falser101:feat/i18n-zh-cn-settings

Conversation

@falser101

Copy link
Copy Markdown

Summary

Introduce i18next + react-i18next in the desktop renderer and ship a Simplified Chinese (zh-CN) translation of the entire settings panel. The infrastructure is set up so that future languages can be contributed by dropping in a single JSON file.

What's in this PR

i18n infrastructure (src/lib/i18n.ts, src/types/i18next.d.ts, src/main.tsx)

  • i18next + react-i18next + browser-language-detector
  • Resources statically imported (Vite codeSplitting: false so they all bundle; the two locales are ~30KB combined)
  • Detection: localStorage['hermes-desktop-locale-v1']navigator.language'en'
  • nsSeparator: false + keySeparator: false so flat namespace:section.subsection keys match literally
  • returnNull: false so missing keys fall back to the key string (visible in dev)

Translation resources (src/locales/)

  • en/translation.json — English source
  • zh-CN/translation.json — Simplified Chinese, parity-locked with English
  • README.md — contributor guide (how to add a new language)
  • locales.test.ts — vitest parity test: same key set, all leaf values are strings, {{var}} placeholder tokens match between locales. Fails CI if a key drifts.

Language picker (src/app/settings/appearance-settings.tsx)

  • New "Language" card at the top of the Appearance section
  • English / 简体中文 buttons with aria-pressed; choice persists to localStorage
  • Adding a new language in the future: drop a JSON file → register in src/lib/i18n.ts → add a button

Translated surface (8 sub-pages, 1 main panel, 1 constants file, 1 primitives file)

  • index.tsx (nav, search placeholders, header buttons)
  • appearance-settings.tsx (mode/theme cards, tool-call display, language picker)
  • gateway-settings.tsx (mode cards, remote URL/token, save/test buttons, env-override warning)
  • keys-settings.tsx (LLM provider groups, env-var rows, show-advanced toggle)
  • mcp-settings.tsx (server list, edit form, transport labels, reload flow)
  • sessions-settings.tsx (archived sessions list, unarchive/delete actions)
  • tools-settings.tsx (skills + toolsets, toggle/save toasts)
  • toolset-config-panel.tsx (provider selection, env-var inline editor, post-setup notice)
  • config-settings.tsx (schema-driven form, field labels/descriptions, import, autosave)
  • about-settings.tsx (update status, version, branch info, relative time)
  • constants.tsFIELD_LABELS / FIELD_DESCRIPTIONS / SECTIONS / SEARCH_PLACEHOLDER now hold i18n key strings
  • primitives.tsx — shared <SectionHeading> / <EmptyState> / <LoadingState> / <Pill> default labels translated

Design choices

  • Flat keys with : separator (e.g. settings:mcp.configured) instead of nested objects. Grep-friendly and matches the convention we use everywhere else. nsSeparator: false + keySeparator: false are required to make literal matching work.
  • Static imports rather than i18next-http-backend. Two languages don't justify the dynamic-loader complexity, and Vite bundles them into the main chunk anyway.
  • Parity test, not auto-translation. The user's responsibility to add new languages is "copy en/, translate, run the parity test". A failed test blocks the PR.

Out of scope

  • Translating the Python-side CLI/Gateway (apps/agent/locales/*.yaml — separate i18n layer)
  • Translating other desktop modules (chat composer, sidebar, overlays, onboarding, etc.) — these will be follow-up PRs, one module at a time
  • RTL layout
  • Intl.DateTimeFormat / Intl.NumberFormat localization

Verification

# Parity test (CI gate)
npm run test:ui -- src/locales/locales.test.ts

# Type-check (no i18n-related errors; pre-existing @testing-library/react
# version mismatch in unrelated test files is not introduced by this PR)
npm run type-check

# Lint (no errors in any i18n-touched file)
npm run lint

Manual:

  1. npm run dev
  2. Open Settings → Appearance → top "Language" card → 简体中文
  3. All settings sub-pages should switch to Chinese immediately
  4. Reload the app — choice persists
  5. Switch back to English — UI matches the pre-PR state (no missing keys shown as xxx.xxx)

Adding a new language

See src/locales/README.md. TL;DR: copy en/translation.json, translate, add an entry in src/lib/i18n.ts's SUPPORTED_LANGUAGES and resources, add a button in the language picker.

@falser101
falser101 requested a review from a team June 2, 2026 07:38
@falser101

falser101 commented Jun 2, 2026

Copy link
Copy Markdown
Author
图片 图片

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have labels Jun 2, 2026
@falser101 falser101 changed the title feat(desktop): add i18n with zh-CN translations for settings panel feat(desktop): add i18n with zh-CN translations Jun 3, 2026
@falser101
falser101 force-pushed the feat/i18n-zh-cn-settings branch from 0208dba to ad5e87b Compare June 4, 2026 01:22
@falser101 falser101 closed this Jun 4, 2026
@falser101
falser101 force-pushed the feat/i18n-zh-cn-settings branch from ad5e87b to fabca0b Compare June 4, 2026 02:16
@falser101 falser101 reopened this Jun 4, 2026
Introduce i18next + react-i18next in the desktop renderer with a flat-key
translation resource under src/locales/ (en + zh-CN), a parity test, and a
contributor guide. Translate the entire settings surface (nav, Appearance,
Gateway, API Keys, MCP, Skills & Tools, Archived Chats, About, Config
schema) to use t() lookups. Add a language picker in Appearance that
persists the choice to localStorage.

Future languages drop a new src/locales/<lang>/translation.json with the
same key set, register it in src/lib/i18n.ts, and add a button in the
language picker.
@falser101
falser101 force-pushed the feat/i18n-zh-cn-settings branch from ad5e87b to a8619bf Compare June 4, 2026 02:56
@falser101

Copy link
Copy Markdown
Author

@alt-glitch Please review this, and then we can submit more PRs.

@teknium1

teknium1 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Superseded by #38241, which we merged as the desktop i18n foundation + Simplified Chinese translation. It aligns with our existing web/src/i18n pattern (typed Translations, I18nProvider/useI18n, display.language config key), was already green across CI, and merged cleanly. Thanks for the work on localization — this is exactly the direction we wanted, and your effort helped confirm it. #38241

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants