# 多语言资源的添加流程及实现原理 ## 概述 本项目采用 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. **部署阶段**: 执行转换脚本并上传到服务器 通过标准化的流程和自动化工具,确保了多语言功能的开发效率和维护质量。开发者可以专注于业务功能开发,而翻译部署工作可以通过规范化的脚本完成。