Add i18n internationalization support with language selector (#2450)
## Summary
- Set up i18n infrastructure using i18next with locale files for English
(chat, common, errors, home, settings namespaces)
- Add LanguageSelector component to the settings page for users to
switch languages
- Add language preference field to the app schema and integrate i18next
provider in the app layout and renderer
## Test plan
- Verify the app builds and starts without errors
- Navigate to Settings and confirm the Language Selector is visible and
functional
- Confirm English translations load correctly across all namespaces
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- devin-review-badge-begin -->
---
<a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2450">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
</picture>
</a>
<!-- devin-review-badge-end -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Broad UI text refactor plus new runtime language switching could
surface missing keys, incorrect namespaces, or layout regressions,
though changes are largely non-functional and localized to presentation.
>
> **Overview**
> Adds app-wide internationalization via `i18next`/`react-i18next`,
including a new `src/i18n` initialization with bundled namespaces and
locale resources.
>
> Introduces a persisted `language` setting (validated by
`LanguageSchema`) plus a new `LanguageSelector` UI, and syncs the active
i18n language at startup in `RootLayout`.
>
> Migrates many user-facing strings across chat, settings, integrations,
dialogs, banners, and preview panel components to use `t()` translation
keys (with interpolation/plurals) instead of hardcoded English, and adds
an i18n design doc. Dependencies are updated in `package.json`/lockfile.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a996131500b0f99ea766036084972f9863aca81d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Add app-wide internationalization with i18next and a language selector
in Settings. The chosen language persists and updates the UI instantly;
ships with English, Simplified Chinese (zh-CN), and Brazilian Portuguese
(pt-BR), aligned with the Linear issue, and migrates UI text across the
app.
- **New Features**
- Initialize i18next/react-i18next with namespaces (common, settings,
chat, home, errors) before render; sync to UserSettings.language on
startup.
- Add LanguageSelector in Settings → General showing only completed
locales; saves validated values and switches UI language.
- Include complete en, zh-CN, pt-BR translations, Intl-based
date/number/relative-time helpers, and docs/i18n.md.
- **Refactors**
- Replace hardcoded strings with t() across 50+ components.
- Validate settings.language via LanguageSchema.safeParse; defer
changeLanguage to layout sync to avoid duplicates; add error handling
for updateSettings; extract constants in formatRelativeTime.
<sup>Written for commit b670b0489415ca966db1f70f0a1ad3111a455538.
Summary will update on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
---------
Co-authored-by:
Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by:
claude[bot] <41898282+claude[bot]@users.noreply.github.com>
正在显示
docs/i18n.md
0 → 100644
差异被折叠。
| ... | ... | @@ -94,6 +94,7 @@ |
| "geist": "^1.3.1", | ||
| "glob": "^11.0.2", | ||
| "html-to-image": "^1.11.13", | ||
| "i18next": "^25.8.0", | ||
| "isomorphic-git": "^1.30.1", | ||
| "jotai": "^2.12.2", | ||
| "jsonrepair": "^3.13.1", | ||
| ... | ... | @@ -107,6 +108,7 @@ |
| "posthog-js": "^1.236.3", | ||
| "react": "^19.0.0", | ||
| "react-dom": "^19.0.0", | ||
| "react-i18next": "^16.5.4", | ||
| "react-konva": "^19.2.1", | ||
| "react-markdown": "^10.1.0", | ||
| "react-resizable-panels": "^2.1.7", | ||
| ... | ... |
src/i18n/format.ts
0 → 100644
src/i18n/index.ts
0 → 100644
src/i18n/locales/en/chat.json
0 → 100644
src/i18n/locales/en/common.json
0 → 100644
src/i18n/locales/en/errors.json
0 → 100644
src/i18n/locales/en/home.json
0 → 100644
差异被折叠。
src/i18n/locales/en/settings.json
0 → 100644
差异被折叠。
src/i18n/locales/pt-BR/chat.json
0 → 100644
差异被折叠。
差异被折叠。
差异被折叠。
src/i18n/locales/pt-BR/home.json
0 → 100644
差异被折叠。
差异被折叠。
src/i18n/locales/zh-CN/chat.json
0 → 100644
差异被折叠。
差异被折叠。
差异被折叠。
src/i18n/locales/zh-CN/home.json
0 → 100644
差异被折叠。
差异被折叠。
src/i18n/types.ts
0 → 100644
差异被折叠。
差异被折叠。
请
注册
或者
登录
后发表评论