i18n: add Russian, and backfill every t() key into the locale bundles - #1648
Merged
Merged
Conversation
Adds Russian as a third UI language alongside English and Chinese. - New `i18n/locales/ru.ts` covering every key in en.ts (the fallback bundle) plus the remoteControl / bots / notify namespaces that only zh.ts overrides, so Russian is not worse off than Chinese on the Remote Control surfaces. Plural keys carry the four Russian Intl.PluralRules categories (_one/_few/_many/_other). - `i18n/index.ts` now exports SUPPORTED_LANGUAGES / AppLanguage / resolveLanguage as the single source of truth. The ActivityBar menu and badge, the System settings chips and the guide dialog toggle all render from that list instead of hard-coding language codes, so a fourth language is one row plus a locale file. - resolveLanguage() replaces the `=== 'zh' ? 'zh' : 'en'` checks, which silently mapped every non-Chinese tag to English. Used by the MUI locale bundle (ruRU added), the token heatmap's date locale, and the co-located Record<AppLanguage, ...> copy in AgentNode, the Claude Code quick-config / config modal / profile overrides, and the Codex and dsh quick-config panels — all of which gained Russian entries. - Russian nav and field labels are deliberately shorter than a literal translation where the ActivityBar rail (~11 chars) or the 180px config label column would otherwise ellipsise them; English fits those widths and Russian did not. - New localeParity test asserts ru covers every key in en and in zh, so a future key added to en.ts cannot silently drop Russian back to English. Verified: typecheck unchanged at 35 pre-existing errors (none in touched files), lint clean, production build passes, and the test suite is back to its 3 pre-existing failures with the new parity test green. Screenshots of the Russian UI checked via the ui-preview skill. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018CAigqrGygAebgepPY2kjL
The codebase's inline-English pattern — t('some.key', { defaultValue: '…' })
— lets a key be referenced by the UI without existing in any locale file.
English still renders, so the gap is invisible in development, and 326 keys
had drifted out that way: the Bots, IM Notify and Remote Control pages were
largely English even in Chinese.
- 130 keys existed in no bundle at all: added to en, zh and ru.
- 196 more existed in zh/ru but not en; added to en so the fallback bundle
is complete and the coverage guard below can be enforced.
- Two of those pass `count`, so they are registered as en plurals
(bots.overview.subtitle, remoteControl.bots.configuredCount).
Also internationalizes four strings hardcoded in JSX: the ActivityBar's
Tools and Servertool nav labels, the Claude Code "Default Mode" row label,
and the config modal's preview Close button. ChatNode's Direct/Group chips
now use the notify.target.* keys its sibling NotifyTestDialog already used.
New tKeyCoverage test walks the sources via import.meta.glob, collects every
literal key passed to t(), and asserts all bundles define it — verified to
fail when a key is removed. Two Russian nav labels are shortened because the
ActivityBar rail clips at ~11 characters where English fits.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CAigqrGygAebgepPY2kjL
andreasfoo
force-pushed
the
claude/i18n-russian-support-nobgmh
branch
from
August 26, 2026 09:46
2dcb9a9 to
dceb3f0
Compare
FFengIll
pushed a commit
that referenced
this pull request
Sep 19, 2026
…#1648) ## Summary Tingly Box shipped English and Chinese only; this adds Russian. Doing so surfaced a second problem: 326 keys the UI references were never in any locale file, so whole pages rendered English even in Chinese. Implement #1641 . ## Key Changes - **Russian locale**: full `ru.ts` covering every key `en.ts` and `zh.ts` define, with all four Russian plural categories on the plural keys. - **One language source of truth**: `SUPPORTED_LANGUAGES` now feeds the switchers, the MUI locale bundle and the heatmap's date locale, replacing scattered `=== 'zh'` checks that mapped every other tag to English. - **Locale coverage backfill**: 326 keys existed only as inline `t(…, { defaultValue })`, leaving Bots / IM Notify / Remote Control largely English in every language — 130 were in no bundle at all, 196 were missing from `en` itself. - **Four hardcoded strings**: the Tools and Servertool nav labels, the Claude Code "Default Mode" row, and the config modal's Close button now go through `t()`. - **Two test guards**: `localeParity` and `tKeyCoverage` fail the build when a key is missing from a bundle, instead of silently rendering English. ## Notes - Two Russian nav labels use shorter synonyms than a literal translation: the ActivityBar rail clips at ~11 characters, which English fits and Russian did not. - ~430 English literals remain hardcoded in JSX across 93 files; deliberately out of scope, and `tKeyCoverage` cannot see them since they never reach `t()`. - Persian and Arabic, with the RTL layout work they need, are stacked on this branch in #1646. - Supersedes #1643, which could not be reopened after the branch was split. --- _Generated by [Claude Code](https://claude.ai/code/session_018CAigqrGygAebgepPY2kjL)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tingly Box shipped English and Chinese only; this adds Russian. Doing so surfaced a second problem: 326 keys the UI references were never in any locale file, so whole pages rendered English even in Chinese.
Implement #1641 .
Key Changes
ru.tscovering every keyen.tsandzh.tsdefine, with all four Russian plural categories on the plural keys.SUPPORTED_LANGUAGESnow feeds the switchers, the MUI locale bundle and the heatmap's date locale, replacing scattered=== 'zh'checks that mapped every other tag to English.t(…, { defaultValue }), leaving Bots / IM Notify / Remote Control largely English in every language — 130 were in no bundle at all, 196 were missing fromenitself.t().localeParityandtKeyCoveragefail the build when a key is missing from a bundle, instead of silently rendering English.Notes
tKeyCoveragecannot see them since they never reacht().Generated by Claude Code