feat: 国际化支持拓展至中文、英文、繁體中文、日本語、Español、Português-Brasil、Deutsch、Français、Русский - #33
feat: 国际化支持拓展至中文、英文、繁體中文、日本語、Español、Português-Brasil、Deutsch、Français、Русский#33gy212 wants to merge 2 commits into
Conversation
Angelahanshuang
commented
Feb 9, 2026
好家伙,我就晚提交了一步 |
gy212
commented
Feb 9, 2026
今天凌晨1点就干完了,只是我睡着了没提交。刚才又review修了一些安全问题才提上来 |
Angelahanshuang
commented
Feb 9, 2026
不过还是老兄你写的完善 |
op7418
left a comment
There was a problem hiding this comment.
Good i18n architecture, but a few issues:
- Merge conflicts: PR has CONFLICTING status, please rebase onto latest main
- Scope: Touches 27+ files, very high conflict risk with other active PRs. Consider splitting into smaller PRs (core i18n infra first, then page-by-page translations)
- Internal error messages: Error messages in
throw new Error()and internal logging shouldn't be translated - only user-facing UI text should uset() - Dependency arrays: Adding
tto useEffect dependency arrays may cause unnecessary re-renders when language changes mid-session
Please rebase and address these issues. Thanks for the work on i18n support!
gy212
commented
Feb 9, 2026
基本完成了0.6.1版本的翻译。 |
gy212
commented
Feb 9, 2026
已修复 lint 报错(当前仅剩 warnings)。 |
gy212
commented
Feb 9, 2026
适配了0.6.4 |
op7418
commented
Feb 9, 2026
哈哈好 |
gy212
commented
Feb 10, 2026
适配了0.7 |
op7418
left a comment
There was a problem hiding this comment.
Great work on the i18n implementation! The zero-dependency approach with React Context + typed translation keys is clean and well-suited for a 2-locale app. Covering 295 keys across all UI modules is impressive.
A few things to address:
Medium — please fix:
Error message regression in
ChatView.tsx— The originalerror instanceof Error ? error.message : 'Unknown error'is replaced with justt('chat.failedToSend'), losing the actual server error message. Please preserve the original error detail, e.g.t('chat.failedToSend') + ': ' + (error instanceof Error ? error.message : '').chat.helpContentis a ~700-char markdown string — This massive block is not maintainable as a translation key. Since it references CLI commands that are always in English, consider keeping it untranslated or splitting it into structured pieces.
Low — nice to have:
Unrelated changes bundled — The PR includes several non-i18n improvements (require→import conversions, code-block highlight fix, shimmer component refactor, Header hydration simplification, McpServerEditor key prop fix, etc.). These are all fine individually but make the PR harder to review and bisect. Consider splitting them into a separate PR.
t()stability concern —tusesuseCallbackwith empty deps +localeRef. Components that only destructure{ t }without subscribing tolocalemay not re-render on locale switch. This works in practice because most components use context, but it's fragile.Duplicate
formatRelativeTime— Same function exists in bothChatListPanel.tsxandImportSessionDialog.tsx. Should be extracted to a shared utility.Brand names in translations — "Anthropic", "OpenRouter", "AWS Bedrock", "Google Vertex" are brand names and don't need to be in translation files.
No security concerns. The locale validation is properly scoped to 'en' | 'zh'. Architecture is solid — looking forward to the revised version!
7cd6361 to
bf94c71Comparegy212
commented
Feb 10, 2026
@op7418 绝大部分问题都修了,我本地一切完好。 |
gy212
commented
Feb 10, 2026
已根据 review 完成修复并推送到 eat/i18n-zh-en(commit: 24aad56)。\n\n本次修复点:\n- 修复 i18n 参数插值中 $ 被 String.replace 误解释的问题:改为函数式替换,并对参数名做正则转义(src/i18n/index.ts)。\n- 已保证语言切换后聊天内即时文案可实时更新:ChatView 的 sendMessage/handleCommand 回调依赖已覆盖 与消息上下文(该部分此前已在分支上的 d931bc4 处理,本次确认保留)。\n- 修复内置命令 badge 描述的国际化:对 built-in command 记录并渲染 descriptionKey,避免固定英文描述。\n- 修复文件-only 发送兜底文案的语言切换闭包问题:handleSubmit 依赖包含 。\n\n本地校验:\n- |
gy212
commented
Feb 11, 2026
语言拓展至 9 种语言在原有中文、英文基础上,新增以下 7 种语言支持:
校验情况每种语言均通过逐 key 深度校验,主要修复内容:
|
op7418
left a comment
There was a problem hiding this comment.
The i18n architecture itself is well-designed (zero-dep Context + hook, type-safe keys, secure interpolation). However:
- Please split non-i18n changes into separate PRs — `mcp-config.ts`, mcp-cli-parser tests, session-parser test changes, and settings route changes should not be in the i18n PR. This overlaps with PR #43 and makes review very difficult at 5000+ lines
- Don't translate internal error messages — `throw new Error(t(...))` should remain in English for debugging. Only translate user-facing UI text
- Consider phased language rollout — Ship en/zh first (well-tested), add other languages in follow-up PRs after native speaker review. 442 keys × 7 AI-generated languages is hard to verify
- Rebase instead of merge — The 19-file merge commit creates messy history and conflict resolutions are hard to verify
Add internationalization support with useTranslation hook, I18nProvider, and language files for: zh, en, zh-TW, ja, es, pt-BR, de, fr, ru Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gy212
commented
Feb 13, 2026
Review 修复已完成1. 错误消息不再翻译
catch 块中用户可见的错误统一使用 2. Rebase 替代 Merge已用 rebase 重建为基于
|
op7418
commented
Feb 23, 2026
你好 @gy212,感谢你提交这个国际化方案!工作量很大,架构设计也很清晰。 经过检查,主分支目前还没有国际化的实现,这个功能对项目的国际化推广很有意义。 不过有几点需要讨论:
我们会在后续详细评估这个 PR 的合并方案。再次感谢你的贡献! |
gy212
commented
Feb 23, 2026
此 PR 已拆分为多个独立 PR,便于逐语言审核和合并:
|
…18#31) Codex review second round caught two real P1 inconsistencies introduced by the Dashboard/CLI split slice plus non-blocking contract drift. P1.1 — Dashboard injection gate ≠ route auth gate. runtime.ts injected the dashboard read/write MCPs whenever prompt + working directory + dashboard keyword matched, but the route's `authorize` requires `sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath` passed as `workspacePath`) so "inject" and "route-authorize" never disagree. CLI tools don't need this (no workspace scope). P1.2 — Matrix promoted only for codex_account; runtime injects for ALL codex_runtime providers. The runtime didn't gate injection by provider, so under a CodePilot proxy provider the dashboard/cli MCPs WERE injected (callable), but the matrix returned `perception_only` for non-codex_account — the opposite drift from P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option: move the promotion into `capabilityMatrixForRuntime` so it applies to ALL codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds codex_account-specific overrides (native notes + image/media demotion). `buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every matrix entry point stays aligned. Non-blocking op7418#1 — contract text drift. capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes` rewritten — explicit that the LEGACY provider-proxy bridge is unsupported (true), and that the codex_runtime path now ships via the mutation-level MCP split + matrix-layer promotion. No schema changes (`kind: 'unsupported'` stays accurate for the legacy bridge surface); the existing matrix invariant test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two promoted cells are allowed to be executable despite `kind: 'unsupported'`. Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception list) tracked as tech-debt op7418#33. Non-blocking op7418#2 — elicitation policy pins. codex-mcp-events.test.ts now pins all 4 new server names: codepilot_{dashboard,cli_tools}_read → auto_accept, codepilot_{dashboard,cli_tools}_write → user_approval. Also added a regression guard: `codex_runtime + non-codex_account provider` must STILL show dashboard/cli_tools executable with mixed trust + the right noteKey. Updated the two pre-existing tests that asserted the OLD behaviour (dashboard/cli perception_only on codex_runtime) — they now assert the promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map. Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the op7418#31 capability table — this commit fixes the inconsistencies, but the real-account end-to-end smoke for natural-conversation triggering + write approval card + Deny blocking is still owed by the user. Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate intact); tools/list subsets unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
概述
基于 React Context + 自定义 Hook 实现完整的中英文国际化系统(零外部依赖)。用户可在设置页面切换 English / 中文 (简体),语言偏好持久化到 SQLite。
架构
nav.newChat、settings.title)/api/settings/app存储到 SQLite(ALLOWED_KEYS中添加locale)t('key', { count: 5 })→ 替换{count}占位符新建文件(5 个)
src/i18n/en.tssrc/i18n/zh.tssrc/i18n/index.tssrc/components/layout/I18nProvider.tsxt()src/hooks/useTranslation.tsuseContext(I18nContext)的封装 Hook修改文件(27 个)
覆盖全部模块:聊天、布局、设置、扩展、插件、项目组件。
特殊处理
BUILT_IN_COMMANDS、MODE_OPTIONS):保持原定义不变,在组件渲染时用t()覆盖 description/label<html lang>:在 I18nProvider 的 useEffect 中通过document.documentElement.lang = locale动态更新formatRelativeTime()改为接受t函数参数