场景国际化
AweeClaw 支持场景独立国际化(i18n),每个场景持有独立的翻译文件,通过生命周期钩子注入/移除,避免场景特有 key 污染全局 i18n 文件。
设计原理
场景激活 (onActivate) → registerScenarioI18n() → 翻译注入 extraEn/extraZh
场景反激活 (onDeactivate) → unregisterScenarioI18n() → 翻译从 extraEn/extraZh 移除底层使用 Map<string, {...}> 按场景 ID 隔离,多场景共存互不覆盖。场景卸载后翻译自动移除,不会残留。
目录结构
scenarios/<scenario-name>/
├── i18n/
│ ├── index.ts # 注册/反注册入口
│ ├── enUS.ts # 英文翻译
│ └── zhCN.ts # 中文翻译创建翻译文件
enUS.ts
typescript
export const en: Record<string, string> = {
'my-scenario.welcome': 'Welcome to My Scenario',
'my-scenario.settings': 'Scenario Settings',
'my-scenario.tab.editor': 'Editor',
'my-scenario.tab.display': 'Display',
'my-scenario.save': 'Save Changes',
'my-scenario.cancel': 'Cancel',
}zhCN.ts
typescript
export const zh: Record<string, string> = {
'my-scenario.welcome': '欢迎使用我的场景',
'my-scenario.settings': '场景设置',
'my-scenario.tab.editor': '编辑器',
'my-scenario.tab.display': '显示',
'my-scenario.save': '保存更改',
'my-scenario.cancel': '取消',
}命名规范:建议使用
<scenario-id>.<feature>.<key>格式,避免跨场景 key 冲突。
注册入口
i18n/index.ts
typescript
import { registerScenarioI18n, unregisterScenarioI18n } from '@renderer/i18n'
import { en } from './enUS'
import { zh } from './zhCN'
const SCENARIO_ID = 'my-scenario'
export function registerMyScenarioI18n(): void {
registerScenarioI18n(SCENARIO_ID, { en, zh })
}
export function unregisterMyScenarioI18n(): void {
unregisterScenarioI18n(SCENARIO_ID)
}生命周期绑定
在场景入口 index.ts 中绑定:
typescript
import { registerMyScenarioI18n, unregisterMyScenarioI18n } from './i18n'
const myScenarioModule: ScenarioModule = {
id: 'my-scenario',
version: '1.0.0',
// ...
onActivate: async (context) => {
registerMyScenarioI18n() // 激活时注入翻译
// ...
},
onDeactivate: async (context) => {
unregisterMyScenarioI18n() // 反激活时移除翻译
// ...
},
}在组件中使用
翻译注册后,在场景组件中与全局 key 使用方式一致:
tsx
import { t, type Language } from '@renderer/i18n'
export function MyPanel({ language }: { language: Language }) {
return (
<div>
<h1>{t('my-scenario.welcome', language)}</h1>
<button>{t('my-scenario.save', language)}</button>
</div>
)
}核心 API
| 函数 | 说明 |
|---|---|
registerScenarioI18n(scenarioId, { en, zh }) | 按场景 ID 注册翻译,自动合并到 extraEn/extraZh |
unregisterScenarioI18n(scenarioId) | 移除指定场景的翻译,重建合并字典 |
registerTranslations({ en, zh }) | (deprecated) 旧版直接合并,不推荐使用 |
对比:全局 vs 场景 i18n
| 全局 i18n | 场景 i18n | |
|---|---|---|
| 文件位置 | renderer/i18n/locales/ | scenarios/<name>/i18n/ |
| 生命周期 | 应用启动时加载,常驻 | 场景激活时注入,反激活时移除 |
| 适用场景 | 共享组件、框架 key | 场景专属 UI、设置、工具描述 |
| 维护方式 | 修改全局文件 | 随场景版本独立维护 |
最佳实践
- Key 命名空间:始终使用场景 ID 作为前缀,避免跨场景冲突(如
dev-assistant.settings.editor) - 按需加载:场景不激活时翻译不驻留内存,减少全局 i18n 文件体积
- 独立维护:场景翻译随场景代码一起版本管理,不依赖全局文件更新
- 共享 key 不迁移:多个场景共用的 key(如
statusBar.cancel、success.settingsSaved)保留在全局 i18n

