Ver Fonte

docs : 添加多语言实现原理与最佳实践文档

dengdx há 2 semanas atrás
pai
commit
b67d7cddb3
1 ficheiros alterados com 386 adições e 0 exclusões
  1. 386 0
      docs/多语言资源的添加流程及实现原理.md

+ 386 - 0
docs/多语言资源的添加流程及实现原理.md

@@ -0,0 +1,386 @@
+# 多语言资源的添加流程及实现原理
+
+## 概述
+
+本项目采用 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 组件
+<FormattedMessage
+  id="newFeature.title"
+  defaultMessage="新功能标题"
+/>
+
+// 方法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';
+
+<IntlProvider
+  locale={currentLocale ? currentLocale.split('_')[0] : 'en'}
+  messages={messages || {}}
+>
+  {/* 应用内容 */}
+</IntlProvider>
+```
+
+#### 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}!"
+
+// 使用方式
+<FormattedMessage
+  id="welcome.user"
+  values={{ name: userName }}
+/>
+```
+
+### 2. 复数处理
+```javascript
+// 消息文件
+"item.count": "有 {count, plural, =0 {没有项目} one {1 个项目} other {# 个项目}}"
+
+// 使用方式
+<FormattedMessage
+  id="item.count"
+  values={{ count: itemCount }}
+/>
+```
+
+### 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. **部署阶段**: 执行转换脚本并上传到服务器
+
+通过标准化的流程和自动化工具,确保了多语言功能的开发效率和维护质量。开发者可以专注于业务功能开发,而翻译部署工作可以通过规范化的脚本完成。