# ClawX 项目国际化 (i18n) 实现参考 本文档分析了 ClawX 项目的国际化实现架构,为 zn-ai 项目的国际化改进提供参考和开发计划。 ## 概述 ClawX 使用 **React + i18next** 框架实现国际化,具有以下特点: - **模块化语言文件**:按功能模块组织翻译内容 - **多语言支持**:支持英文 (en)、中文 (zh)、日文 (ja) - **智能语言检测**:自动根据系统语言和用户偏好选择语言 - **状态管理集成**:与 Zustand 状态存储深度集成,支持持久化 - **类型安全**:完整的 TypeScript 类型支持 ## 架构设计 ### 核心文件结构 ``` src/ ├── i18n/ │ ├── locales/ │ │ ├── en/ # 英文翻译 │ │ │ ├── common.json # 通用翻译 │ │ │ ├── settings.json # 设置页面翻译 │ │ │ ├── dashboard.json # 仪表盘翻译 │ │ │ ├── chat.json # 聊天页面翻译 │ │ │ ├── channels.json # 频道页面翻译 │ │ │ ├── agents.json # 代理页面翻译 │ │ │ ├── skills.json # 技能页面翻译 │ │ │ ├── cron.json # 定时任务翻译 │ │ │ └── setup.json # 设置向导翻译 │ │ ├── zh/ # 中文翻译 (同上结构) │ │ └── ja/ # 日文翻译 (同上结构) │ └── index.ts # i18n 配置入口 ├── shared/ │ └── language.ts # 语言解析工具 └── stores/ └── settings.ts # 语言状态管理 ``` ### 技术栈 ```json { "dependencies": { "i18next": "^25.8.11", "react-i18next": "^16.5.4" } } ``` ## 核心代码解析 ### 1. 语言解析工具 (`shared/language.ts`) ```typescript export const SUPPORTED_LANGUAGE_CODES = ['en', 'zh', 'ja'] as const; export type LanguageCode = (typeof SUPPORTED_LANGUAGE_CODES)[number]; // 标准化语言代码(处理 zh-CN、zh_TW 等变体) function normalizeLocale(locale: string | null | undefined): string { return locale?.trim().toLowerCase().replaceAll('_', '-') ?? ''; } // 解析支持的语言代码 export function resolveSupportedLanguage( locale: string | null | undefined, fallback: LanguageCode = 'en', ): LanguageCode { const normalizedLocale = normalizeLocale(locale); if (!normalizedLocale) return fallback; const [baseLanguage] = normalizedLocale.split('-'); return SUPPORTED_LANGUAGE_CODE_SET.has(baseLanguage) ? (baseLanguage as LanguageCode) : fallback; } ``` **关键特性:** - 自动处理语言变体(如 `zh-CN` → `zh`, `en-US` → `en`) - 安全的默认值回退机制 - 类型安全的语言代码枚举 ### 2. i18n 配置入口 (`src/i18n/index.ts`) ```typescript import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import { SUPPORTED_LANGUAGE_CODES, resolveSupportedLanguage } from '../../shared/language'; // 导入所有语言文件(按模块) import enCommon from './locales/en/common.json'; import enSettings from './locales/en/settings.json'; // ... 其他模块导入 // 定义支持的语言列表(包含显示标签) export const SUPPORTED_LANGUAGES = [ { code: 'en', label: 'English' }, { code: 'zh', label: '中文' }, { code: 'ja', label: '日本語' }, ] as const; // 构建 i18next 资源结构 const resources = { en: { common: enCommon, settings: enSettings, // ... 其他命名空间 }, zh: { /* 同上结构 */ }, ja: { /* 同上结构 */ }, }; // 初始化 i18next i18n .use(initReactI18next) .init({ resources, lng: resolveSupportedLanguage( typeof navigator !== 'undefined' ? navigator.language : undefined ), fallbackLng: 'en', supportedLngs: [...SUPPORTED_LANGUAGE_CODES], defaultNS: 'common', // 默认命名空间 ns: ['common', 'settings', 'dashboard', 'chat', 'channels', 'agents', 'skills', 'cron', 'setup'], interpolation: { escapeValue: false }, // React 已处理转义 react: { useSuspense: false }, }); export default i18n; ``` **配置亮点:** - **多命名空间**:按功能模块分离,避免单个文件过大 - **智能语言检测**:自动根据浏览器语言选择 - **安全的回退机制**:确保始终有可用的翻译 - **React 优化**:禁用 Suspense 避免渲染问题 ### 3. 状态管理集成 (`src/stores/settings.ts`) ```typescript import i18n from '@/i18n'; import { resolveSupportedLanguage } from '../../shared/language'; interface SettingsState { language: string; // ... 其他设置 } const defaultSettings = { language: resolveSupportedLanguage( typeof navigator !== 'undefined' ? navigator.language : undefined ), // ... 其他默认值 }; export const useSettingsStore = create()( persist( (set) => ({ ...defaultSettings, // 初始化时加载远程设置并同步 i18n init: async () => { try { const settings = await hostApiFetch>('/api/settings'); const resolvedLanguage = settings.language ? resolveSupportedLanguage(settings.language) : undefined; set((state) => ({ ...state, ...settings, ...(resolvedLanguage ? { language: resolvedLanguage } : {}), })); if (resolvedLanguage) { i18n.changeLanguage(resolvedLanguage); // 同步 i18n 实例 } } catch { /* 降级处理 */ } }, // 设置语言时同步更新 i18n 和远程存储 setLanguage: (language) => { const resolvedLanguage = resolveSupportedLanguage(language); i18n.changeLanguage(resolvedLanguage); // 1. 更新 i18n 实例 set({ language: resolvedLanguage }); // 2. 更新本地状态 void hostApiFetch('/api/settings/language', { // 3. 同步到主进程 method: 'PUT', body: JSON.stringify({ value: resolvedLanguage }), }).catch(() => { }); }, }), { name: 'clawx-settings' } // Zustand 持久化配置 ) ); ``` **集成特点:** - **三级同步**:i18n 实例 ↔ 本地状态 ↔ 主进程存储 - **持久化**:使用 localStorage 持久化用户偏好 - **错误处理**:网络失败时降级到本地存储 ### 4. 应用集成 (`src/App.tsx`) ```typescript import i18n from './i18n'; import { useSettingsStore } from './stores/settings'; function App() { const language = useSettingsStore((state) => state.language); // 挂载时同步 i18n 语言与持久化设置 useEffect(() => { if (language && language !== i18n.language) { i18n.changeLanguage(language); } }, [language]); return <>{/* 应用内容 */}; } ``` ### 5. 组件使用示例 (`src/pages/Setup/index.tsx`) ```typescript import { useTranslation } from 'react-i18next'; import type { TFunction } from 'i18next'; import { SUPPORTED_LANGUAGES } from '@/i18n'; export function Setup() { // 使用多个命名空间 const { t, i18n } = useTranslation(['setup', 'channels']); // 获取语言设置操作 const { language, setLanguage } = useSettingsStore(); // 动态翻译函数(用于生成动态内容) const getSteps = (t: TFunction): SetupStep[] => [ { id: 'welcome', title: t('steps.welcome.title'), // setup 命名空间 description: t('steps.welcome.description'), }, // ... ]; return (
{/* 直接翻译 */}

{t(`steps.${step.id}.title`)}

{/* 语言选择器 */}
{SUPPORTED_LANGUAGES.map((lang) => ( ))}
{/* 带参数的翻译 */}

{t('runtime.status.gatewayRunning', { port: gatewayStatus.port })}

); } ``` **使用模式:** - **命名空间**:`useTranslation(['setup', 'channels'])` 加载多个模块 - **动态键**:`t(`steps.${step.id}.title`)` 支持动态翻译键 - **参数插值**:`t('key', { param: value })` 支持动态内容 - **类型安全**:通过 `TFunction` 类型提供类型提示 ## 语言文件结构 ### 模块化设计 ```json // locales/zh/common.json { "sidebar": { "chat": "聊天", "newChat": "新对话", "cronTasks": "定时任务", "skills": "技能", "agents": "Agents", "channels": "频道", "dashboard": "仪表盘", "settings": "设置", "devConsole": "开发者控制台", "models": "模型", "deleteSessionConfirm": "确定要删除对话 \"{{label}}\" 吗?", "openClawPage": "OpenClaw 页面" }, "actions": { "save": "保存", "cancel": "取消", "delete": "删除", "edit": "编辑", "refresh": "刷新", "close": "关闭", "copy": "复制", "search": "搜索", "confirm": "确认", "dismiss": "忽略" }, "status": { "running": "运行中", "stopped": "已停止", "error": "错误", "connected": "已连接", "disconnected": "已断开" } } // locales/zh/setup.json (设置向导专用) { "steps": { "welcome": { "title": "欢迎使用 ClawX", "description": "让我们快速完成初始设置" }, "runtime": { "title": "运行环境检查", "description": "确保所有依赖项已就绪" } }, "welcome": { "title": "欢迎!", "description": "ClawX 是一个基于 OpenClaw 的图形化 AI 助手...", "features": { "noCommand": "无需命令行经验", "modernUI": "现代化的图形界面", "bundles": "预置技能包", "crossPlatform": "跨平台支持" } } } ``` **组织原则:** 1. **按功能模块分离**:避免单个文件过大 2. **嵌套结构**:使用对象嵌套提高可读性 3. **参数化**:支持 `{{variable}}` 插值 4. **上下文清晰**:键名反映使用场景 ## 构建配置 ### package.json 依赖 ```json { "devDependencies": { "i18next": "^25.8.11", "react-i18next": "^16.5.4" } } ``` ### Vite 配置 无需特殊配置,i18next 与构建工具无关。 ## 为 zn-ai 项目的改进建议 ### 当前 zn-ai i18n 状态分析 zn-ai 项目目前使用 Vue 3 + vue-i18n,但实现较为简单: **优势:** - ✅ 已集成 vue-i18n 基础框架 - ✅ 基本的中英文翻译已就绪 - ✅ 目录结构已优化 (`src/i18n/`) **不足:** - ❌ 缺少模块化语言文件组织 - ❌ 缺乏智能语言检测和解析 - ❌ 未与状态管理集成(持久化) - ❌ 没有类型安全的语言代码 - ❌ 缺少多命名空间支持 ### 推荐架构迁移 鉴于 zn-ai 使用 Vue 3,建议采用以下架构: ``` src/i18n/ ├── locales/ │ ├── en/ # 英文模块 │ │ ├── common.json # 通用翻译 │ │ ├── login.json # 登录页面 │ │ ├── dashboard.json # 仪表盘 │ │ ├── task.json # 任务管理 │ │ ├── rate.json # 费率管理 │ │ ├── knowledge.json # 知识库 │ │ ├── setting.json # 设置页面 │ │ └── component.json # 组件翻译 │ ├── zh/ # 中文模块(同上结构) │ └── ja/ # 日文模块(可选) ├── constants.ts # 语言常量定义 ├── resolver.ts # 语言解析工具 ├── store.ts # 语言状态管理 └── index.ts # vue-i18n 配置 ``` ### 技术选择 1. **核心库**:继续使用 `vue-i18n@9.x`(与 Vue 3 兼容) 2. **状态管理**:集成到现有的 Pinia store 3. **类型安全**:使用 TypeScript 增强类型提示 4. **持久化**:通过 `electron-store` 或 `localStorage` ## 当前进展 ### 语言选择器 UI 试点实现 已在设置页面的版本信息组件 (`src/pages/setting/components/Version/index.vue`) 中实现语言选择器 UI,作为国际化改进的试点。 **实现内容:** - 添加了语言设置区域,包含三个按钮:中文、English、日本語 - 默认语言为中文,当前选中语言高亮显示 - 集成了现有的 `vue-i18n` 实例,使用 `setLanguage`/`getLanguage` API - 支持日语语言文件占位 (`ja.json`) **技术细节:** - 使用 Element Plus 按钮组件 (`el-button`) - 响应式当前语言状态管理 - 类型安全的语言代码 (`LanguageType`) - 遵循 ClawX 项目的 UI 设计模式 **下一步:** - 将语言选择器集成到全局设置页面 - 添加语言状态持久化(Pinia Store) - 完善日语翻译内容 - 推广到其他组件 ## 开发计划 ### 第一阶段:基础架构升级 (预计: 2-3 天) **目标**:建立模块化、类型安全的 i18n 基础架构 1. **语言文件重组** - 创建模块化目录结构 (`src/i18n/locales/en/`, `src/i18n/locales/zh/`) - 按功能拆分现有翻译:`common`, `login`, `dashboard`, `task`, `rate`, `knowledge`, `setting`, `component` - 保持向后兼容,逐步迁移 2. **核心工具开发** - 创建 `src/i18n/constants.ts`:定义 `SUPPORTED_LANGUAGES` 等常量 - 创建 `src/i18n/resolver.ts`:语言检测和解析工具 - 增强类型定义:`LanguageCode`, `NamespaceKey` 等 3. **vue-i18n 配置升级** - 重写 `src/i18n/index.ts`:支持多命名空间、智能语言检测 - 配置回退链:`zh-CN` → `zh` → `en` - 添加开发调试工具 ### 第二阶段:状态管理集成 (预计: 1-2 天) **目标**:实现语言设置的持久化和全应用同步 1. **Pinia Store 创建** - 创建 `src/store/locale.ts`:管理语言状态 - 集成语言解析工具 - 实现与 vue-i18n 实例的同步 2. **持久化机制** - 集成 `electron-store` 或使用 `localStorage` - 实现设置保存/加载 - 添加错误处理和降级方案 3. **主进程同步**(可选) - 通过 IPC 与主进程设置同步 - 系统语言变化监听 ### 第三阶段:组件集成优化 (预计: 2-3 天) **目标**:更新所有组件使用新的 i18n 架构 1. **工具函数创建** - 创建 `useLocale()` composable:提供类型安全的翻译函数 - 添加 `t()` 函数的 TypeScript 增强 - 开发批量翻译更新脚本 2. **组件迁移** - 按页面逐步更新组件:Login, Dashboard, Task, Rate, Knowledge, Setting - 更新路由和菜单的国际化 - 验证所有动态插值功能 3. **开发体验优化** - 添加 VSCode 扩展建议 (i18n-ally) - 配置提取工具 - 添加缺失翻译标记 ### 第四阶段:高级功能与测试 (预计: 1-2 天) **目标**:添加高级功能和确保质量 1. **语言切换界面** - 在设置页面添加语言选择器 - 实时预览功能 - 语言包元信息显示(作者、版本) 2. **测试与验证** - 单元测试:语言解析工具 - 集成测试:语言切换流程 - E2E 测试:多语言场景 3. **构建优化** - 按需加载语言包 - 构建时提取和验证 - 生产环境优化 ### 第五阶段:维护与扩展 (持续) **目标**:建立可持续的国际化工作流 1. **工作流建立** - 翻译提取脚本 - 与翻译平台集成方案 - 版本控制和协作流程 2. **扩展准备** - 支持 RTL 语言(阿拉伯语等) - 日期、数字、货币格式化 - 复数规则支持 3. **文档完善** - 开发者指南 - 翻译贡献指南 - 最佳实践文档 ## 实施优先级 ### 高优先级(立即执行) 1. 模块化语言文件重组 2. 语言解析工具开发 3. vue-i18n 配置升级 4. Pinia store 集成 ### 中优先级(本周内) 1. 组件迁移(按页面) 2. 语言切换界面 3. 持久化实现 ### 低优先级(后续迭代) 1. 主进程同步 2. 高级格式化功能 3. 自动化翻译流程 ## 预期收益 1. **可维护性**:模块化结构使翻译更易管理 2. **开发者体验**:类型安全、智能提示、调试工具 3. **用户体验**:智能语言检测、无缝切换、持久化偏好 4. **扩展性**:轻松添加新语言、支持高级 i18n 功能 5. **代码质量**:统一模式、减少硬编码、便于测试 ## 具体实施任务清单(第一阶段) ### 任务 0:语言选择器 UI 试点(已完成) - [x] 在设置页面版本组件中添加语言选择器 UI (`src/pages/setting/components/Version/index.vue`) - [x] 实现三个语言按钮:中文、English、日本語,默认选中中文 - [x] 集成现有 `vue-i18n` API (`setLanguage`/`getLanguage`) - [x] 添加日语语言文件占位 (`src/i18n/locales/ja.json`) - [x] 导出 `LanguageType` 类型供组件使用 ### 任务 1:语言文件重组 - [x] 创建目录结构:`src/i18n/locales/en/` 和 `src/i18n/locales/zh/` - [ ] 分析现有翻译内容,按功能模块拆分: - `common.json`:通用翻译(按钮、状态、提示) - `login.json`:登录页面相关 - `dashboard.json`:仪表盘相关 - `task.json`:任务管理相关 - `rate.json`:费率管理相关 - `knowledge.json`:知识库相关 - `setting.json`:设置页面相关 - `component.json`:组件专用翻译 - [ ] 迁移现有翻译内容到新结构 - [ ] 验证 JSON 格式正确性 ### 任务 2:核心工具开发 - [ ] 创建 `src/i18n/constants.ts`: ```typescript export const SUPPORTED_LANGUAGE_CODES = ['en', 'zh', 'ja'] as const; export type LanguageCode = (typeof SUPPORTED_LANGUAGE_CODES)[number]; export const SUPPORTED_LANGUAGES = [ { code: 'en', label: 'English' }, { code: 'zh', label: '中文' }, { code: 'ja', label: '日本語' }, ] as const; ``` - [ ] 创建 `src/i18n/resolver.ts`: - `normalizeLocale()`:标准化语言代码 - `resolveSupportedLanguage()`:解析支持的语言 - 处理 `zh-CN`、`zh-TW`、`en-US` 等变体 - [ ] 添加类型定义:`LanguageCode`、`Namespace`、`TranslationKey` 等 ### 任务 3:vue-i18n 配置升级 - [ ] 重写 `src/i18n/index.ts`: - 支持多命名空间导入 - 集成语言解析工具 - 配置智能回退链:`zh-CN` → `zh` → `en` - 添加开发调试选项 - [ ] 验证配置正确性: - 运行 `npm run typecheck` 检查类型 - 运行 `npm run build:vite` 验证构建 - 启动开发服务器测试基础功能 ### 任务 4:Pinia Store 集成 - [ ] 创建 `src/store/locale.ts`: - 状态:`language: LanguageCode` - 动作:`setLanguage(lang: LanguageCode)` - 持久化:集成 `localStorage` 或 `electron-store` - [ ] 实现与 vue-i18n 实例的同步: - Store 初始化时读取持久化设置 - 语言切换时更新 i18n 实例 - 监听 i18n 语言变化更新 Store - [ ] 在 `src/main.ts` 中集成 Store ### 任务 5:基础组件迁移(试点) - [ ] 创建 `src/composables/useLocale.ts`: - 提供类型安全的 `t()` 函数 - 集成命名空间支持 - 添加语言切换功能 - [ ] 迁移登录页面 (`src/pages/login/index.vue`): - 使用新的 `useLocale()` composable - 更新所有静态文本为翻译键 - 验证动态插值功能 - [ ] 迁移侧边栏菜单: - 更新菜单项文本 - 验证语言切换实时生效 ### 验收标准 - [ ] 类型检查通过 (`npm run typecheck`) - [ ] 生产构建通过 (`npm run build:vite`) - [ ] 开发服务器正常启动 (`npm run dev`) - [ ] 中英文切换功能正常 - [ ] 语言设置持久化生效 - [ ] 控制台无 i18n 相关错误 ## 第一阶段完成状态 ### 任务完成情况 - ✅ **任务 0:语言选择器 UI 试点** - 已完成(设置页面版本组件) - ✅ **任务 1:语言文件重组** - 已完成(创建模块化目录结构,拆分现有翻译) - ✅ **任务 2:核心工具开发** - 已完成(创建 constants.ts 和 resolver.ts) - ✅ **任务 3:vue-i18n配置升级** - 已完成(重写 index.ts,支持多命名空间) - ✅ **任务 4:Pinia Store集成** - 已完成(创建 locale.ts,实现状态管理) - ✅ **任务 5:基础组件迁移试点** - 已完成(创建 useLocale composable,迁移登录页面) ### 验证结果 - ✅ 类型检查通过 (`npm run typecheck`) - ✅ 生产构建通过 (`npm run build:vite`) - ✅ 无代码缺失,保持向后兼容 ### 下一步建议 第一阶段基础架构已成功建立,建议继续推进第二阶段(状态管理集成优化)和第三阶段(组件集成优化),逐步将新的国际化架构推广到全应用。 ## 结论 ClawX 的 i18n 实现提供了一个优秀的参考架构,其核心思想——**模块化、类型安全、状态集成、智能解析**——完全适用于 zn-ai 项目。通过分阶段实施上述开发计划,zn-ai 可以在 1-2 周内建立专业级的国际化系统,为多语言用户提供更好的体验,同时提高代码的可维护性和开发效率。 建议立即开始第二阶段实施,逐步推广到全应用。