Skip to content

feat(i18n): add 10 European language locales#253

Open
craigamcw wants to merge 2 commits into
OpenCoworkAI:mainfrom
craigamcw:feat/european-locales
Open

feat(i18n): add 10 European language locales#253
craigamcw wants to merge 2 commits into
OpenCoworkAI:mainfrom
craigamcw:feat/european-locales

Conversation

@craigamcw

Copy link
Copy Markdown

What

Adds full UI translations for 10 European languages alongside the existing English and Chinese:

es (Español), fr (Français), de (Deutsch), it (Italiano), uk (Українська), pl (Polski), sv (Svenska), no (Norsk), nl (Nederlands), ro (Română)

Changes

  • New locale files under src/renderer/i18n/locales/ — each a complete translation of en.json (all 866 keys), with native orthography and every {{interpolation}} placeholder / pluralization key preserved.
  • src/renderer/i18n/config.ts — import the locales and extend supportedLngs.
  • src/renderer/components/settings/SettingsGeneral.tsx — add the languages to the language switcher (native names).

The existing i18next-browser-languagedetector picks these up automatically, and users can also select them in Settings → General → Language.

Notes

🤖 Generated with Claude Code

Adds full UI translations for Spanish (es), French (fr), German (de),
Italian (it), Ukrainian (uk), Polish (pl), Swedish (sv), Norwegian (no),
Dutch (nl) and Romanian (ro), alongside the existing English and Chinese.

- New locale files under src/renderer/i18n/locales/ (all 866 keys, native
  orthography, interpolation placeholders preserved)
- Register the locales and extend supportedLngs in i18n/config.ts
- Add the languages to the Settings -> General language switcher

The browser/UI language detector already picks these up automatically.
Complements the Memory-settings English-fallback fix in OpenCoworkAI#246 (the new
locales include those keys).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review mode: initial

Findings

[MAJOR] Active language indicator broken for new languages

The currentLang variable in SettingsGeneral.tsx (line ~28) is defined as:

const currentLang = i18n.language.startsWith('zh') ? 'zh' : 'en';

This means for any language that doesn't start with 'zh', currentLang will always be 'en'. When a user selects Spanish (es), French (fr), etc., the active-language button highlight logic (currentLang === lang.code) will never match, so none of the new language buttons will appear selected. The bug exists at src/renderer/components/settings/SettingsGeneral.tsx:28.

Suggested fix:
Replace the currentLang assignment with:

const currentLang = i18n.language.split('-')[0];

This normalises region variants (e.g., es-ESes) and works for all languages including zh-CN. The active check then becomes currentLang === lang.code. Note that if you want to support region-specific fallbacks (e.g., nbno), you'd need a mapping, but that's beyond this PR's scope.

[MINOR] Cosmetic comment-only changes in config.ts

The diff in src/renderer/i18n/config.ts replaces Chinese comments with English equivalents. While harmless, these changes introduce unnecessary noise and are unrelated to the feature. They should have been omitted or done in a separate commit.

[NIT] Missing test coverage for locale key parity

There are no automated tests verifying that every locale file contains exactly the same keys as en.json. Without such a test, future edits to en.json may silently go untranslated in these 10 locales. Consider adding a Vitest test in src/tests/i18n/ that loads each locale and checks key-set equality.

Questions

  • Are there any plans to add region-aliases? For example, Norwegian Bokmål (nb) is not in supportedLngs; users with nb browser language will fall back to English. Should nb be added as an alias for no?

Summary

  • Review mode: initial
  • The PR adds 10 European locale files plus wiring in config.ts and SettingsGeneral.tsx.
  • 1 MAJOR issue: the active-language button highlighting is broken for all new languages due to unchanged currentLang logic. This must be fixed before merging.
  • 1 MINOR issue: cosmetic comment changes introduce diff noise.
  • 1 NIT: no key-parity test for the new locales.
  • No security or data-loss risks identified.

Testing

Not run (automation).

Open Cowork Bot

- Fix the active-language highlight in SettingsGeneral: the old
  `startsWith('zh') ? 'zh' : 'en'` logic never matched the new languages.
  Normalize to the base code (es-ES -> es, zh-CN -> zh) and map Norwegian
  nb/nn -> the shipped `no` locale.
- Add nb/nn -> no fallback and `nonExplicitSupportedLngs` so browser region
  variants (e.g. es-ES, de-DE, nb-NO) resolve to the right locale.
- Restore the original Chinese comments in i18n/config.ts (only functional
  changes remain in the diff).
- Add memory.* and api.* keys to en.json/zh.json so all 12 locales share an
  identical key set (these mirror OpenCoworkAI#246).
- Add a Vitest key-parity test (src/tests/i18n/) asserting every locale has
  exactly the same keys as en.json, to catch future drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@craigamcw

Copy link
Copy Markdown
Author

Thanks for the thorough review — all points addressed in the latest commit:

[MAJOR] Active-language highlight — Fixed. SettingsGeneral.tsx no longer uses the startsWith('zh') ? 'zh' : 'en' logic; it now normalizes to the base code (es-ES → es, zh-CN → zh) and maps Norwegian nb/nn → the shipped no locale, so every language button highlights correctly.

[MINOR] config.ts comment noise — Reverted. The original Chinese comments are restored; only the functional changes (locale imports/resources, supportedLngs, and the new fallback options) remain in the diff.

[NIT] Key-parity test — Added src/tests/i18n/locale-key-parity.test.ts, which asserts every locale has exactly the same key set as en.json (fails on missing or extra keys). To make this hold, I also added the memory.* / api.* keys to en.json/zh.json so all 12 locales are consistent — these mirror #246, so this PR now effectively supersedes its data changes (happy to rebase/close #246 whichever you prefer).

[Question] Region aliases / nb — Added fallbackLng: { nb: ['no'], nn: ['no'], default: ['en'] } plus nonExplicitSupportedLngs: true, so nb/nb-NO/nn resolve to Norwegian and region variants of the other languages resolve to their base locale.

tsc --noEmit is clean and the new parity test passes (11/11).

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review mode: follow-up after new commits

Findings

The previous review flagged three issues:

  1. MAJORcurrentLang logic broken for new languages → Fixed. The active language now correctly normalizes via i18n.language.split('-')[0] and maps Norwegian variants to no.
  2. MINOR – Cosmetic comment changes → Addressed. Comments have been reverted to Chinese (original style) and are no longer noise.
  3. NIT – Missing key-parity test → Added. A thorough Vitest test at src/tests/i18n/locale-key-parity.test.ts checks every locale against en.json for matching keys.

All previously identified issues are resolved. The following new observations are minor:

Minor: Edge case for nb-NO / nn-NO fallback

The fallbackLng object in src/renderer/i18n/config.ts correctly maps nb and nn to no. However, because nonExplicitSupportedLngs: true is set, the language detector may produce nb-NO (with region). While nb is mapped, nb-NO is not explicitly listed in the fallback object. In practice, a user with browser language nb-NO would fall to the default ['en'] rather than no. To fully cover this, consider adding region-specific entries or using a function-based fallback that strips the region first. This is a low-impact edge case.

Suggested fix (optional):

fallbackLng: {
  'nb': ['no'],
  'nb-NO': ['no'],
  'nn': ['no'],
  'nn-NO': ['no'],
  default: ['en'],
}

Summary

The PR now addresses all core feedback from the initial review. The currentLang logic works correctly for all 12 languages, the fallback for Norwegian variants is in place, and key-parity tests protect against silent missing translations. The code is clean, no security or data-loss risks are present, and the changes integrate smoothly with the existing i18n infrastructure.

Open Cowork Bot

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