Summary
termic currently has no internationalization layer: all user-facing strings are hardcoded in English directly inside React components. This issue proposes adding i18n support so the UI can be translated into other languages.
Current state
- No i18n library is present in
package.json (no react-i18next, @lingui/react, react-intl, etc.) — this would be greenfield work.
- Rough count of hardcoded user-facing strings in
src/:
- JSX text nodes: ~123 (dialogs 42, settings 29, task view 25, sidebar 16, root-level 8, views 2)
title= (tooltips): 83
placeholder=: 36
aria-label=: 12
- toast/notification calls: 8
- Realistic total: ~260-300 distinct strings, likely 350+ once conditional/template-literal text and multi-line JSX blocks are counted individually.
ui/ primitives (Radix wrappers) are string-free — extraction won't need to touch the design-system layer.
- 288 template literals with
${} interpolation in .tsx files, several with mid-sentence variable interpolation (e.g. "N files changed") that will need ICU MessageFormat/pluralization support rather than simple key lookup.
- No centralized strings/constants file exists today — all copy is inline.
- Rust side (
src-tauri/src/lib.rs) has ~217 error-construction sites, mostly internal/debug errors. A manual pass would be needed to separate developer-facing from user-facing messages before deciding scope; recommend deferring Rust-side i18n to a later phase.
Proposed plan
- Infra: adopt
@lingui/react over react-i18next — compile-time extraction (macros) avoids the runtime string-keyed lookup + context/hook subscription model that react-i18next uses, which fits this project's "no unnecessary re-renders" performance constraint better (see CLAUDE.md: no StrictMode, perf-sensitive terminal/editor panes).
- Extraction: wrap strings with the
t macro / <Trans>, run Lingui's extract CLI to generate .po catalogs. Migrate area by area to keep diffs reviewable: dialogs → settings → task view → sidebar → root.
- Verification: typecheck + visual smoke-check per area in the running app; watch for extra re-renders with the React DevTools profiler specifically on
TerminalPane/EditorPane, the performance-critical surfaces.
- Rust-side strings: separate follow-up, scoped to only the errors that are actually surfaced to the user (not debug/log-only ones).
Effort estimate
- Extraction phase alone: M, ~3-5 days for one engineer.
- Full i18n (locale catalogs, RTL/date formatting if needed, QA): L, ~1.5-2 weeks.
Open questions
- Which languages should be prioritized first?
- Should locale be auto-detected from the OS, or user-selectable in settings only?
- Is RTL support in scope, or English + LTR languages only for v1?
Summary
termic currently has no internationalization layer: all user-facing strings are hardcoded in English directly inside React components. This issue proposes adding i18n support so the UI can be translated into other languages.
Current state
package.json(noreact-i18next,@lingui/react,react-intl, etc.) — this would be greenfield work.src/:title=(tooltips): 83placeholder=: 36aria-label=: 12ui/primitives (Radix wrappers) are string-free — extraction won't need to touch the design-system layer.${}interpolation in.tsxfiles, several with mid-sentence variable interpolation (e.g. "N files changed") that will need ICU MessageFormat/pluralization support rather than simple key lookup.src-tauri/src/lib.rs) has ~217 error-construction sites, mostly internal/debug errors. A manual pass would be needed to separate developer-facing from user-facing messages before deciding scope; recommend deferring Rust-side i18n to a later phase.Proposed plan
@lingui/reactoverreact-i18next— compile-time extraction (macros) avoids the runtime string-keyed lookup + context/hook subscription model thatreact-i18nextuses, which fits this project's "no unnecessary re-renders" performance constraint better (seeCLAUDE.md: no StrictMode, perf-sensitive terminal/editor panes).tmacro /<Trans>, run Lingui'sextractCLI to generate.pocatalogs. Migrate area by area to keep diffs reviewable: dialogs → settings → task view → sidebar → root.TerminalPane/EditorPane, the performance-critical surfaces.Effort estimate
Open questions