# 多语言资源的添加流程及实现原理
## 概述
本项目采用 React-Intl 库实现国际化(i18n)支持,通过 Redux 状态管理维护多语言状态。本文档详细介绍多语言资源的添加流程、技术实现原理以及相关开发规范。
## 技术架构
### 核心技术栈
- **React-Intl v7.1.11**: React 国际化库
- **Redux Toolkit**: 状态管理
- **Ant Design**: UI 组件库(内置国际化支持)
- **Taro**: 跨平台开发框架
### 核心组件
1. **IntlProvider**: React-Intl 上下文提供者
2. **i18nSlice**: Redux 状态管理切片
3. **语言切换组件**: LanguageSettingModal
4. **转换脚本**: extract-i18n-json.js
## 语言资源文件结构
```
src/assets/i18n/messages/
├── zh.js # 中文语言资源
└── en.js # 英文语言资源
```
### 文件格式
每个语言文件都是标准的 ES6 模块:
```javascript
export default {
"greeting": "你好,世界!",
"login.username": "用户名",
"login.username.placeholder": "请输入用户名",
// ... 更多翻译项
};
```
## 添加多语言资源的完整流程
### 步骤1:代码开发阶段
在组件中定义翻译键,并提供默认消息:
```typescript
import { FormattedMessage, useIntl } from 'react-intl';
// 方法1:使用 FormattedMessage 组件
// 方法2:使用 useIntl hook
const intl = useIntl();
const title = intl.formatMessage({
id: 'newFeature.title',
defaultMessage: '新功能标题'
});
```
### 步骤2:添加翻译资源
#### 2.1 在中文文件中添加翻译
```javascript
// src/assets/i18n/messages/zh.js
export default {
// ... 现有翻译
"newFeature.title": "新功能标题",
"newFeature.description": "这是新功能的详细描述",
};
```
#### 2.2 在英文文件中添加对应翻译
```javascript
// src/assets/i18n/messages/en.js
export default {
// ... 现有翻译
"newFeature.title": "New Feature Title",
"newFeature.description": "This is the detailed description of the new feature",
};
```
### 步骤3:转换并部署
#### 3.1 执行转换脚本
```bash
node scripts/extract-i18n-json.js
```
脚本执行流程:
1. 读取所有语言文件 (`zh.js`, `en.js`)
2. 移除 `export default` 语法和结尾分号
3. 转换为纯 JSON 格式
4. 输出到 `scripts/output/i18n/` 目录
转换后的文件格式:
```json
{
"greeting": "你好,世界!",
"login.username": "用户名",
"newFeature.title": "新功能标题"
}
```
#### 3.2 上传到服务器
脚本执行后会自动询问服务器配置:
```
📤 SCP配置 (按Enter使用默认值):
IP地址 (默认: 192.168.110.245):
用户名 (默认: root):
中文文件路径 (默认: /root/gydr/trans/zh_CN/zh.js):
英文文件路径 (默认: /root/gydr/trans/en_US/en.js):
```
确认配置后自动通过 SCP 上传:
```bash
scp zh.js root@192.168.110.245:/root/gydr/trans/zh_CN/zh.js
scp en.js root@192.168.110.245:/root/gydr/trans/en_US/en.js
```
## 实现原理
### 1. React-Intl 集成原理
#### 1.1 应用入口配置
```typescript
// src/app.tsx
import { IntlProvider } from 'react-intl';
{/* 应用内容 */}
```
#### 1.2 状态管理架构
```typescript
// src/states/i18nSlice.ts
interface I18nState {
messages: I18nMessages; // 当前语言的翻译字典
currentLocale: string; // 当前语言代码 (en_US/zh_CN)
supportedLocales: string[]; // 支持的语言列表
availableLanguages: LanguageItem[]; // 后端返回的语言选项
loading: boolean; // 加载状态
error: string | null; // 错误信息
}
```
### 2. 语言切换流程
#### 2.1 用户操作流程
1. 点击 SystemZone 中的"语言管理"按钮
2. 弹出 LanguageSettingModal 对话框
3. 自动加载可用语言列表
4. 用户选择目标语言
5. 调用后端 API 更新系统语言
6. Redux store 更新当前语言
7. 应用重新渲染显示新语言
#### 2.2 API 接口
```typescript
// 获取语言列表
GET /dr/api/v1/pub/language
// 更新系统语言
POST /api/v1/auth/manage/language
{
"lang": "zh_CN.UTF-8" // 或 "en_US.UTF-8"
}
```
### 3. 转换脚本实现原理
#### 3.1 核心转换逻辑
```javascript
function extractJsonFromJs(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
// 移除 export default 语句
let jsonString = content
.replace(/export\s+default\s+/g, '')
.trim();
// 移除末尾分号
if (jsonString.endsWith(';')) {
jsonString = jsonString.slice(0, -1);
}
// 安全解析 JSON
const jsonObj = eval('(' + jsonString + ')');
return jsonObj;
}
```
#### 3.2 自动化部署流程
脚本集成了完整的部署流程:
1. 文件转换 (JS → JSON)
2. 配置询问 (服务器信息)
3. SCP 上传 (自动传输)
4. 结果反馈 (成功/失败状态)
## 翻译键命名规范
### 命名规则
采用点号分隔的多级命名结构,产品相关命名放在第一级:
```
[产品.]模块.子模块.元素[.状态]
```
### 产品层级命名
根据产品类型在第一级添加产品标识符:
#### 宠物产品 (VETDROS)
- 第一级使用 `animal.` 前缀
- 适用于宠物诊疗相关功能
#### 人医产品 (DROS)
- 无产品前缀,直接从模块开始
- 适用于人类医疗相关功能
### 实际示例
#### 宠物产品示例
- `animal.login.username` - 宠物产品登录模块用户名
- `animal.register.patientId` - 宠物注册模块宠物编号
- `animal.register.patientName.placeholder` - 宠物注册模块宠物昵称占位符
- `animal.exam.action.resetParams` - 宠物检查模块重置参数动作
#### 人医产品示例
- `login.username` - 登录模块用户名
- `register.patientId` - 注册模块患者编号
- `register.patientName.placeholder` - 注册模块患者姓名占位符
- `exam.action.resetParams` - 检查模块重置参数动作
### 语义化分类
#### 通用模块
- `login.*` - 登录相关
- `register.*` - 注册相关
- `exam.*` - 检查相关
- `worklist.*` - 工作清单相关
- `output.*` - 输出相关
- `actionPanel.*` - 操作面板相关
#### 宠物专用模块
- `animal.*` - 宠物相关功能
- `animal.register.*` - 宠物注册
- `animal.worklist.*` - 宠物工作清单
- `animal.actionPanel.*` - 宠物操作面板
#### 功能状态后缀
- `.placeholder` - 输入框占位符
- `.required` - 必填验证消息
- `.success` - 成功提示
- `.failed` - 失败提示
- `.loading` - 加载状态
- `.empty` - 空状态
- `.error` - 错误状态
### 命名原则
1. **产品优先**: 宠物产品必须使用 `animal.` 前缀,人医产品直接从模块开始
2. **模块清晰**: 使用具有语义的英文单词作为模块名
3. **层次分明**: 通过点号建立清晰的层次结构
4. **状态明确**: 对于不同状态的相同元素,使用状态后缀区分
5. **一致性**: 相同功能在不同产品中保持相似的命名结构
## 高级功能
### 1. 参数化翻译
```javascript
// 消息文件
"welcome.user": "欢迎,{name}!"
// 使用方式
```
### 2. 复数处理
```javascript
// 消息文件
"item.count": "有 {count, plural, =0 {没有项目} one {1 个项目} other {# 个项目}}"
// 使用方式
```
### 3. 日期和数字格式化
```typescript
const intl = useIntl();
// 日期格式化
const formattedDate = intl.formatDate(date, {
year: 'numeric',
month: 'long',
day: 'numeric'
});
// 数字格式化
const formattedNumber = intl.formatNumber(value, {
style: 'currency',
currency: 'CNY'
});
```
## 最佳实践
### 开发规范
1. **默认消息**: 始终提供 `defaultMessage` 作为降级
2. **键唯一性**: 确保翻译键在所有语言文件中唯一
3. **一致性**: 中英文翻译键必须完全一致
4. **模块化**: 按功能模块组织翻译键
### 部署规范
1. **环境隔离**: 不同环境使用不同服务器配置
2. **备份策略**: 上传前备份现有翻译文件
3. **回滚计划**: 准备翻译文件回滚方案
4. **测试验证**: 部署后验证多语言切换功能
## 常见问题及解决方案
### 1. 翻译不显示
**现象**: 界面显示翻译键而非翻译文本
**原因**: 翻译键不存在或语言文件未正确加载
**解决**:
- 检查翻译键拼写是否正确
- 验证所有语言文件是否包含该键
- 确认语言切换是否生效
### 2. IntlProvider 错误
**现象**: "Could not find required `intl` object"
**原因**: 组件渲染时 IntlProvider 还未挂载
**解决**: 确保 IntlProvider 始终存在,提供默认值
### 3. 转换脚本失败
**现象**: 脚本执行报错
**原因**: Node.js 环境问题或文件权限问题
**解决**:
- 检查 Node.js 版本
- 验证文件路径和权限
- 查看控制台错误信息
### 4. 上传失败
**现象**: SCP 上传失败
**原因**: 网络连接或服务器配置问题
**解决**:
- 检查网络连接
- 验证服务器地址和端口
- 确认 SSH 密钥或密码正确
## 扩展方向
### 1. 自动化改进
- 集成 CI/CD 流水线自动转换和上传
- 添加翻译键重复检查
- 实现翻译完成度统计
### 2. 开发体验优化
- VS Code 插件支持翻译键提示
- 翻译键提取工具自动化生成
- 实时翻译预览功能
### 3. 翻译管理平台
- 集成专业翻译管理工具
- 支持翻译记忆库
- 多版本翻译管理
## 总结
本项目的多语言实现方案提供了完整的开发到部署流程:
1. **开发阶段**: 定义翻译键并添加默认消息
2. **翻译阶段**: 在语言文件中添加对应翻译
3. **部署阶段**: 执行转换脚本并上传到服务器
通过标准化的流程和自动化工具,确保了多语言功能的开发效率和维护质量。开发者可以专注于业务功能开发,而翻译部署工作可以通过规范化的脚本完成。