Skip to content

场景国际化

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、设置、工具描述
维护方式修改全局文件随场景版本独立维护

最佳实践

  1. Key 命名空间:始终使用场景 ID 作为前缀,避免跨场景冲突(如 dev-assistant.settings.editor
  2. 按需加载:场景不激活时翻译不驻留内存,减少全局 i18n 文件体积
  3. 独立维护:场景翻译随场景代码一起版本管理,不依赖全局文件更新
  4. 共享 key 不迁移:多个场景共用的 key(如 statusBar.cancelsuccess.settingsSaved)保留在全局 i18n

AweeClaw AI 应用构建平台