国际化
apps/web 和 apps/admin 都支持国际化。实现是自研的(没有使用 react-i18next 等库),使用 Zustand store 和平面的 TypeScript locale 文件。
Locale 文件
Web 门户(apps/web)
app/locales/
├── index.ts # 导出 useLocaleStore 和 t() 辅助函数
├── en-US.ts # 英文翻译
└── zh-CN.ts # 中文翻译每个 locale 文件导出一个平面的键值对记录:
ts
export default {
"dashboard.title": "能源仪表盘",
"dashboard.welcome": "欢迎,{name}",
"nav.overview": "概览",
"nav.energy": "能耗",
// ...
};使用翻译
在 React 组件中:
tsx
import { useLocaleStore } from "~/locales";
function Header() {
const { t } = useLocaleStore();
return <h1>{t("dashboard.title")}</h1>;
}支持插值:
tsx
<p>{t("dashboard.welcome", { name: user.username })}</p>切换语言
locale store 将用户选择持久化到 localStorage。首次访问时,它会检测浏览器语言,如果浏览器偏好中文则回退到 zh-CN,否则 en-US。
tsx
const { setLocale } = useLocaleStore();
setLocale("zh-CN"); // 或 "en-US"添加新翻译键
将键添加到 两个
en-US.ts和zh-CN.ts中,填入相应翻译。在组件中通过
t("your.new.key")使用。运行死码检查器确保没有遗留键:
bashuv run apps/web/scripts/check-locale-dead-code.py
删除翻译键
- 从组件中移除所有使用该键的地方。
- 从 两个 locale 文件中删除该键。
- 运行死码检查器确认清理干净。
Admin 后台 i18n 注意事项
admin 后台目前未使用 locale 系统 — 大部分 admin 文本保持英文内联。只有 apps/web 实现了完整的 i18n。
Locale 文件约定
- 使用点号命名空间:
"nav.overview"、"form.email.placeholder"。 - 在每个命名空间内按字母顺序排列键,便于阅读。
- 不要嵌套对象——平键更容易搜索和 grep。
- 英文使用句首大写,避免全大写。