← Back to PRs

#13622: feat(i18n): add complete multi-language support (EN, TR, FR, DE)

by vaur94 open 2026-02-10 19:13 View on GitHub →
app: web-ui stale
## Summary This PR adds a comprehensive internationalization (i18n) system to the Control UI, enabling full multi-language support with four languages: **English**, **Turkish**, **French**, and **German**. ## Changes ### New Files - `ui/src/ui/i18n.ts` — Core i18n module with `t()` translation function, locale detection, and reactive locale switching - `ui/src/ui/locales/en.json` — English locale (905 keys) - `ui/src/ui/locales/tr.json` — Turkish locale (905 keys) - `ui/src/ui/locales/fr.json` — French locale (905 keys) - `ui/src/ui/locales/de.json` — German locale (905 keys) ### Modified Files (40+) All user-facing hardcoded strings have been replaced with `t()` calls across views, controllers, and chat components: - Navigation, tabs, subtitles - Overview, Chat, Channels, Sessions, Usage, Config, Debug, Logs - Agents, Skills, Nodes, Cron Jobs - Error messages, confirmation dialogs, tooltips, placeholders - Config section labels and descriptions (27 sections) ## i18n Architecture ``` i18n.ts ├── t(key, params?) — Translate with dot-notation keys and {{interpolation}} ├── setLocale(locale) — Switch language reactively ├── getLocale() — Get current locale ├── detectBrowserLocale() — Auto-detect from navigator.language ├── LOCALE_REGISTRY — Available locales with native labels └── BUNDLES — Lazy-flattened nested JSON bundles ``` **Adding a new language** is straightforward: 1. Create `locales/<code>.json` with the same key structure 2. Import and register in `i18n.ts` ## Translation Quality - All translations are done from English with accurate, context-appropriate wording - Technical terms remain consistent across platforms (Gateway, Token, Cron, etc.) - Interpolation parameters (`{{count}}`, `{{value}}`, `{type}`) are preserved - No ambiguity — natural, professional expressions in each language ## Verification - **Build**: ✅ 133 modules, 0 errors - **Key count**: 905 keys × 4 languages = 3,620 total translations - **Coverage**: All user-facing UI strings (340+ replacements in 40+ files) ## Screenshots The language selector appears in the Settings section, allowing users to switch between EN, TR, FR, DE at runtime. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR introduces a lightweight i18n layer for the Control UI (`ui/src/ui/i18n.ts`) with JSON bundles for EN/TR/FR/DE and updates many views/controllers to replace hardcoded strings with `t(...)` calls. Navigation/tab labels were refactored to be translated dynamically via `getTabGroups()`, and a language selector was added to the sidebar with locale persisted in UI settings. Key behavioral changes: locale is initialized on connect (saved locale or `navigator.language`), and locale changes trigger UI re-render via a listener. <h3>Confidence Score: 3/5</h3> - Moderate risk to merge due to runtime i18n/state issues. - The overall i18n integration looks consistent, but there are a few concrete runtime issues: module-level translated constants won’t update on locale changes, nav group collapse state is keyed by translated labels (breaking persistence across languages), and a locale-change listener is registered without cleanup (can leak on reconnect/remount). These should be fixed before merging to avoid user-visible regressions. - ui/src/ui/chat/copy-as-markdown.ts, ui/src/ui/app-render.ts, ui/src/ui/app-lifecycle.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs