国际化(i18n)
本项目提供一套前后端共享的完整本地化方案,当前支持三种 locale:
enzh-Hanszh-Hant
产品默认跟随浏览器语言,但用户也可以在 Settings 中手动覆盖 locale。 该页面同时展示浏览器侧看到的工作区姿态(API base、theme、timezone), 帮助操作员确认本地会话实际采用的上下文。前后端会保持一致, 从而保证 API 错误消息、active-runs 界面与格式化日期都与当前 UI 语言匹配。
设计原则
- 把支持的 locales 单一事实源放在
locales/manifest.json - 文案以稳定翻译 key 存储,而不是在 UI 中内联字符串
- 优先翻译整句,而不是字符串拼接
- 用户手动选择 locale 的优先级高于浏览器自动协商
- 使用 locale-aware 的格式化(
Intl、后端翻译错误、Content-Languageheaders) - 把技术标识符(
provider.type、model IDs、dataset paths)视为数据,而不是可翻译文案
仓库布局
manifest.json:共享 locale registry 与 native namesfrontend.json:通过react-i18next渲染的 React UI 文案backend.json:由 FastAPI middleware/helpers 翻译的 API 侧消息
运行时行为
Frontend
frontend/src/i18n/index.ts初始化i18nextfrontend/src/app/locale-provider.tsx解析最终 locale,并同步<html lang>frontend/src/i18n/locale.ts包含 locale detection、browser matching、持久化与手动覆盖逻辑frontend/src/api/client.ts在 API 请求中发送X-Eval-Locale- SSE 请求通过
?locale=传递 locale,因为EventSource不能发送自定义 headers
Backend
backend/src/eval_752/i18n/__init__.py加载locales/manifest.json,负责 locale 解析与后端消息翻译LocaleMiddleware的优先级如下:X-Eval-Localelocalequery parameterAccept-Languagemanifest.json中的默认 locale
- 响应会带上
Content-Language,方便客户端确认实际应用了哪个 locale
新增或更新文案
Frontend 文案
- 在
locales/en/frontend.json中新增稳定 key - 在所有其他
frontend.json中镜像同一 key - 在 React 组件中使用
useTranslation(),或在非 React 工具 / hooks 中使用i18n.t(...) - 优先使用插值:
- 日期与数字优先使用 locale-aware 格式化,并尽量复用现有 helpers
Backend 文案
- 在
locales/en/backend.json中新增稳定 key - 在所有其他
backend.json中镜像同一 key - 在 routes、validators 与后端 response builders 中使用
translate("path.to.key", value=name) - 除非明确需要返回上游原始输出,否则不要新增面向用户的
str(exc)文本
添加新语言
- 在
locales/manifest.json中添加 locale code 与 native name - 创建
locales/<locale>/frontend.json - 创建
locales/<locale>/backend.json - 先完整复制英文 key 结构,再翻译 value
- 在
frontend/src/i18n/resources.ts中注册前端资源导入 - 如果新语言需要特殊浏览器匹配规则,请检查
frontend/src/i18n/locale.ts - 如果后端需要特殊 locale 协商逻辑,请检查
backend/src/eval_752/i18n/__init__.py - 确认该语言会出现在 Settings 中,并验证浏览器匹配行为符合预期
贡献者检查清单
PR 若修改了面向用户的文案,请确认:
- 更新了全部 locale catalogs,而不仅是英文
- translation keys 保持稳定;只有语义变化时才重命名
- 不通过多个 key 拼接一句话
- 占位符(如
{{name}}、{{count}})在各语言中保持一致 - 验证浏览器跟随模式与手动覆盖模式
- 至少验证一条由后端翻译的错误或校验路径
测试与验证
修改 i18n 后,请运行相关检查:
自动化覆盖目前包括:
backend/tests/app/test_i18n.py中的 locale negotiation testsbackend/tests/test_locale_catalogs.py中的 locale catalog parity checksfrontend/src/i18n/locale.test.ts中的前端 locale helper testsfrontend/src/api/client.test.ts中 API client locale-header 的覆盖
常见陷阱
- 不要在组件内直接写面向用户的 fallback English
- 不要本地化持久化标识符或 API enum values,除非它们仅用于展示
- 若可以用整句 key,就不要围绕标点拼接多个已翻译片段
- 不要只在
manifest中加 locale,却没补双份 catalogs 和前端资源注册
另见:
