chore: restructure project and add i18n support

- Reorganize project structure with new electron and shared directories
- Add comprehensive i18n support with Chinese, English, and Japanese locales
- Update build configurations and TypeScript paths for new structure
- Add various UI components including chat interface and task management
- Include Windows release binaries and localization files
- Update dependencies and fix import paths throughout the codebase
This commit is contained in:
duanshuwen
2026-04-06 14:39:06 +08:00
parent e76b034d50
commit 6615d11dd6
311 changed files with 823682 additions and 4460 deletions

View File

@@ -0,0 +1,667 @@
# 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`
- 添加开发调试选项
- [ ] 验证配置正确性:
- 运行 `npm run typecheck` 检查类型
- 运行 `npm 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
- 更新所有静态文本为翻译键
- 验证动态插值功能
- [ ] 迁移侧边栏菜单:
- 更新菜单项文本
- 验证语言切换实时生效
### 验收标准
- [ ] 类型检查通过 (`npm run typecheck`)
- [ ] 生产构建通过 (`npm run build:vite`)
- [ ] 开发服务器正常启动 (`npm run dev`)
- [ ] 中英文切换功能正常
- [ ] 语言设置持久化生效
- [ ] 控制台无 i18n 相关错误
## 第一阶段完成状态
### 任务完成情况
- ✅ **任务 0语言选择器 UI 试点** - 已完成(设置页面版本组件)
- ✅ **任务 1语言文件重组** - 已完成(创建模块化目录结构,拆分现有翻译)
- ✅ **任务 2核心工具开发** - 已完成(创建 constants.ts 和 resolver.ts
- ✅ **任务 3vue-i18n配置升级** - 已完成(重写 index.ts支持多命名空间
- ✅ **任务 4Pinia Store集成** - 已完成(创建 locale.ts实现状态管理
- ✅ **任务 5基础组件迁移试点** - 已完成(创建 useLocale composable迁移登录页面
### 验证结果
- ✅ 类型检查通过 (`npm run typecheck`)
- ✅ 生产构建通过 (`npm run build:vite`)
- ✅ 无代码缺失,保持向后兼容
### 下一步建议
第一阶段基础架构已成功建立,建议继续推进第二阶段(状态管理集成优化)和第三阶段(组件集成优化),逐步将新的国际化架构推广到全应用。
## 结论
ClawX 的 i18n 实现提供了一个优秀的参考架构,其核心思想——**模块化、类型安全、状态集成、智能解析**——完全适用于 zn-ai 项目。通过分阶段实施上述开发计划zn-ai 可以在 1-2 周内建立专业级的国际化系统,为多语言用户提供更好的体验,同时提高代码的可维护性和开发效率。
建议立即开始第二阶段实施,逐步推广到全应用。