Files
zn-ai/docs/i18n-implementation-reference.md
DEV_DSW 79bea4f107 Refactor UUID generation, remove unused logger and encryption utilities, and clean up request handling
- Updated `generateUUID` function for improved readability and performance.
- Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed.
- Simplified TypeScript configuration by removing unnecessary paths and aliases.
- Enhanced Vite configuration for better project structure and maintainability.
2026-04-17 15:38:08 +08:00

668 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<SettingsState>()(
persist(
(set) => ({
...defaultSettings,
// 初始化时加载远程设置并同步 i18n
init: async () => {
try {
const settings = await hostApiFetch<Partial<typeof defaultSettings>>('/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 (
<div>
{/* 直接翻译 */}
<h1>{t(`steps.${step.id}.title`)}</h1>
{/* 语言选择器 */}
<div className="flex justify-center gap-2 py-2">
{SUPPORTED_LANGUAGES.map((lang) => (
<Button
key={lang.code}
variant={language === lang.code ? 'secondary' : 'ghost'}
onClick={() => setLanguage(lang.code)}
>
{lang.label}
</Button>
))}
</div>
{/* 带参数的翻译 */}
<p>{t('runtime.status.gatewayRunning', { port: gatewayStatus.port })}</p>
</div>
);
}
```
**使用模式:**
- **命名空间**`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` 等
### 任务 3vue-i18n 配置升级
- [ ] 重写 `src/i18n/index.ts`
- 支持多命名空间导入
- 集成语言解析工具
- 配置智能回退链:`zh-CN` → `zh` → `en`
- 添加开发调试选项
- [ ] 验证配置正确性:
- 运行 `pnpm run typecheck` 检查类型
- 运行 `pnpm run build:vite` 验证构建
- 启动开发服务器测试基础功能
### 任务 4Pinia 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
- 更新所有静态文本为翻译键
- 验证动态插值功能
- [ ] 迁移侧边栏菜单:
- 更新菜单项文本
- 验证语言切换实时生效
### 验收标准
- [ ] 类型检查通过 (`pnpm run typecheck`)
- [ ] 生产构建通过 (`pnpm run build:vite`)
- [ ] 开发服务器正常启动 (`pnpm run dev`)
- [ ] 中英文切换功能正常
- [ ] 语言设置持久化生效
- [ ] 控制台无 i18n 相关错误
## 第一阶段完成状态
### 任务完成情况
- ✅ **任务 0语言选择器 UI 试点** - 已完成(设置页面版本组件)
- ✅ **任务 1语言文件重组** - 已完成(创建模块化目录结构,拆分现有翻译)
- ✅ **任务 2核心工具开发** - 已完成(创建 constants.ts 和 resolver.ts
- ✅ **任务 3vue-i18n配置升级** - 已完成(重写 index.ts支持多命名空间
- ✅ **任务 4Pinia Store集成** - 已完成(创建 locale.ts实现状态管理
- ✅ **任务 5基础组件迁移试点** - 已完成(创建 useLocale composable迁移登录页面
### 验证结果
- ✅ 类型检查通过 (`pnpm run typecheck`)
- ✅ 生产构建通过 (`pnpm run build:vite`)
- ✅ 无代码缺失,保持向后兼容
### 下一步建议
第一阶段基础架构已成功建立,建议继续推进第二阶段(状态管理集成优化)和第三阶段(组件集成优化),逐步将新的国际化架构推广到全应用。
## 结论
ClawX 的 i18n 实现提供了一个优秀的参考架构,其核心思想——**模块化、类型安全、状态集成、智能解析**——完全适用于 zn-ai 项目。通过分阶段实施上述开发计划zn-ai 可以在 1-2 周内建立专业级的国际化系统,为多语言用户提供更好的体验,同时提高代码的可维护性和开发效率。
建议立即开始第二阶段实施,逐步推广到全应用。