• Will Chen's avatar
    Add i18n internationalization support with language selector (#2450) · b1c4aa28
    Will Chen 提交于
    ## 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: 's avatarClaude Opus 4.5 <noreply@anthropic.com>
    Co-authored-by: 's avatarclaude[bot] <41898282+claude[bot]@users.noreply.github.com>
    b1c4aa28
名称
最后提交
最后更新
..
AgentConsentBanner.tsx 正在载入提交数据...
AttachmentsList.tsx 正在载入提交数据...
AuxiliaryActionsMenu.tsx 正在载入提交数据...
ChatActivity.tsx 正在载入提交数据...
ChatError.tsx 正在载入提交数据...
ChatErrorBox.tsx 正在载入提交数据...
ChatHeader.tsx 正在载入提交数据...
ChatInput.tsx 正在载入提交数据...
ChatMessage.tsx 正在载入提交数据...
CodeHighlight.tsx 正在载入提交数据...
ContextLimitBanner.tsx 正在载入提交数据...
DeleteChatDialog.tsx 正在载入提交数据...
DragDropOverlay.tsx 正在载入提交数据...
DyadAddDependency.tsx 正在载入提交数据...
DyadAddIntegration.tsx 正在载入提交数据...
DyadCardPrimitives.tsx 正在载入提交数据...
DyadCodeSearch.tsx 正在载入提交数据...
DyadCodeSearchResult.tsx 正在载入提交数据...
DyadCodebaseContext.tsx 正在载入提交数据...
DyadCompaction.tsx 正在载入提交数据...
DyadDatabaseSchema.tsx 正在载入提交数据...
DyadDelete.tsx 正在载入提交数据...
DyadEdit.tsx 正在载入提交数据...
DyadExecuteSql.tsx 正在载入提交数据...
DyadExitPlan.tsx 正在载入提交数据...
DyadGrep.tsx 正在载入提交数据...
DyadListFiles.tsx 正在载入提交数据...
DyadLogs.tsx 正在载入提交数据...
DyadMarkdownParser.tsx 正在载入提交数据...
DyadMcpToolCall.tsx 正在载入提交数据...
DyadMcpToolResult.tsx 正在载入提交数据...
DyadOutput.tsx 正在载入提交数据...
DyadProblemSummary.tsx 正在载入提交数据...
DyadRead.tsx 正在载入提交数据...
DyadRename.tsx 正在载入提交数据...
DyadSearchReplace.tsx 正在载入提交数据...
DyadStatus.tsx 正在载入提交数据...
DyadSupabaseProjectInfo.tsx 正在载入提交数据...
DyadSupabaseTableSchema.tsx 正在载入提交数据...
DyadThink.tsx 正在载入提交数据...
DyadTokenSavings.tsx 正在载入提交数据...
DyadWebCrawl.tsx 正在载入提交数据...
DyadWebSearch.tsx 正在载入提交数据...
DyadWebSearchResult.tsx 正在载入提交数据...
DyadWrite.tsx 正在载入提交数据...
DyadWritePlan.tsx 正在载入提交数据...
FileAttachmentDropdown.tsx 正在载入提交数据...
FixAllErrorsButton.tsx 正在载入提交数据...
FreeAgentQuotaBanner.tsx 正在载入提交数据...
HistoryNavigation.tsx 正在载入提交数据...
HomeChatInput.tsx 正在载入提交数据...
LexicalChatInput.tsx 正在载入提交数据...
MessagesList.tsx 正在载入提交数据...
PromoMessage.tsx 正在载入提交数据...
QuestionnaireInput.tsx 正在载入提交数据...
RenameChatDialog.tsx 正在载入提交数据...
SelectedComponentDisplay.tsx 正在载入提交数据...
StreamingLoadingAnimation.tsx 正在载入提交数据...
SummarizeInNewChatButton.tsx 正在载入提交数据...
TodoList.tsx 正在载入提交数据...
TokenBar.tsx 正在载入提交数据...
UncommittedFilesBanner.tsx 正在载入提交数据...
VersionPane.tsx 正在载入提交数据...
monaco.ts 正在载入提交数据...
stateTypes.ts 正在载入提交数据...
types.d.ts 正在载入提交数据...