Skill: anyaoqi/dy-skill-i18n (version 1.0.0)

--- name: dy-skill-i18n description: 处理前端国际化翻译工作。当用户提到需要做国际化、i18n、翻译、多语言支持时使用此 skill。主要功能：1) 识别代码中的硬编码静态文字；2) 判断是否应使用现有公共翻译或需要新增；3) 将翻译添加到对应的语言文件中；4) 将硬编码替换为国际化调用；5) 检查翻译完整性和正确性。 --- # 国际化翻译 Skill ## 目录 - [核心原则](#核心原则) - [工作流程](#工作流程) - [常见问题处理](#常见问题处理) - [翻译准确性要求](#翻译准确性要求) - [注意事项](#注意事项) - [验证与错误处理](#验证与错误处理) --- ## 概述 此 skill 用于处理前端项目的国际化翻译工作。当你需要将代码中的硬编码中文（或英文）文字转换为国际化支持时使用。 **前提**：以实际项目结构为准，不破坏现有项目规则。 --- ## 核心原则 1. **以实际项目结构为准** - 不假设固定目录结构，根据项目现有配置灵活调整 2. **配置放对应位置** - 公共翻译放公共目录，模块翻译放模块目录，不混淆 3. **优先复用现有翻译** - 已有相同含义的翻译时直接使用，不要重复添加 4. **只翻译静态文字** - 不翻译后端接口返回的数据、字典/枚举中的内容 5. **不破坏现有规则** - 所有修改基于项目现有规则，不改变现有结构 --- ## 工作流程 ### Step 1: 了解项目结构 首先探索项目的国际化配置： 1. 查找语言文件目录（常见名称：lang, locales, i18n, language, messages） 2. 确认目录结构模式： - **有模块区分**：是否存在 common/, module/, 或按模块名划分的子目录 - **无模块区分**：所有翻译是否都在一个或少数几个文件中 3. 确认文件命名规范（如 zh_CN.ts, zh-CN.ts, en.ts, en_US.ts 等） 4. 确认国际化调用方式（如 $t(), t(), useI18n() 等） 5. 确认支持的语言种类（是否只有中英文，还是支持更多语言） 6. 确认是否使用了 vue-i18n 的特殊功能（复数、插值等） ### Step 2: 识别需要翻译的内容 **✅ 需要翻译**： - 静态显示的中文/英文字符串 - 按钮文字、提示信息、表单标签 - 表格列标题、对话框标题 - 占位符文字、选项文字 **❌ 不需要翻译**： - 从后端 API 返回的数据 - 字典/枚举中获取的内容 - 变量和动态计算的值 - 数字、日期格式（需要使用专门的格式化方法） - 技术性错误信息（后端返回的 error message） ### Step 3: 判断翻译放哪里 根据项目实际结构判断翻译应该添加到哪里： #### 情况A: 项目有模块区分 ``` lang/ ├── common/ # 公共翻译 │ ├── zh.ts │ └── en.ts ├── module/ # 模块翻译 │ ├── product/ │ ├── order/ │ └── ... └── index.ts ``` **决策规则**： - 如果是**通用性质**的翻译（如：新增、编辑、删除、搜索、重置、确定、取消、请输入、请选择等）→ 放 `common/` - 如果是**特定业务模块**的翻译（如：产品名称、订单状态，品牌分类等）→ 放对应模块目录 #### 情况B: 项目无模块区分 ``` lang/ ├── zh_CN.ts ├── en_US.ts └── index.ts ``` **决策规则**： - 所有翻译都直接添加到对应的语言文件中 - 使用有前缀的 key 区分不同模块，如 `product.*`, `order.*`, `common.*` #### 情况C: 其他结构 根据项目实际结构灵活处理： - 可能存在多个语言文件（按语言分、按模块分、混合分） - 可能使用 JSON 格式或 TS 格式 - 总之**遵循项目现有模式，不打破现有结构** ### Step 4: 添加翻译 1. **检查现有翻译** - 先搜索是否已有相同含义的翻译，有则复用 2. **新增翻译 key** - 如果没有，添加新的翻译 3. **确保所有支持的语言一致** - 添加时同步添加所有支持的语言，保持 key 路径一致 **添加位置判断**： ``` IF 项目有 common/ 或类似的公共目录 THEN IF 翻译是通用性质的 THEN 添加到公共目录 ELSE 添加到对应模块目录 ELSE 添加到主语言文件中，使用模块前缀区分 ``` ### Step 5: 替换硬编码 根据项目实际的调用方式替换。常见使用方式如下： ```vue <!-- Template 中使用 $t --> {{ $t("key.path") }} <!-- 在 script 中使用 --> <script setup> const { t } = useI18n(); const text = t("key.path"); </script> <!-- 属性绑定 --> <el-input :placeholder="t('key.path')" /> ``` ### Step 6: 检查验证 1. **完整性检查**： - 所有支持的语言翻译都已添加 - key 路径在所有语言文件中一致 2. **正确性检查**： - 翻译 key 正确 - 页面显示正常 3. **遗漏检查**： - 扫描文件确认没有遗漏的硬编码 - 检查相似场景是否需要同样处理 --- ## 常见问题处理 ### Q1: 如何判断是公共翻译还是模块翻译？ ``` 通用性质 = 任何模块都可能用到 - 操作类：新增、编辑、删除、查看、导入、导出、提交、审核 - 提示类：确定、取消、关闭，保存、成功、失败 - 占位符类：请输入、请选择、开始日期、结束日期 - 表格类：序号、操作、状态 模块特有 = 只有特定模块使用 - 产品名称、产品编码、产品分类 - 订单号、订单状态 - 客户名称、客户电话 ``` ### Q2: 项目没有模块目录怎么办 直接添加到主语言文件中，使用模块前缀区分： ```typescript // zh_CN.ts export default { common: { action: { add: "新增", edit: "编辑" }, }, product: { name: "产品名称", code: "产品编码", }, order: { no: "订单号", status: "订单状态", }, }; ``` ### Q3: 已有公共翻译但想保持模块独立性 如果业务确实需要独立管理（如不同模块由不同人维护），可以在模块目录中重复定义，但建议优先复用公共翻译。 ### Q4: 如何处理动态参数/插值 如果翻译中需要动态参数（如用户名、数量、时间等）： 1. **在 key 中使用占位符**： ```typescript // zh_CN.ts export default { deleteSuccess: "删除成功，共 {count} 条记录", welcome: "欢迎 {username} 登录系统", selectedCount: "已选择 {n} 项", }; ``` 2. **在组件中传递参数**： ```vue <!-- 使用对象参数 --> {{ $t("deleteSuccess", { count: deletedCount }) }} <!-- 在 script 中 --> <script setup> const { t } = useI18n(); const message = t("deleteSuccess", { count: deletedCount }); </script> ``` 3. **注意事项**： - 遵循项目现有的插值语法（占位符格式可能不同，如 `{count}` 或 `%{count}`） - 占位符命名应简洁明了 - 确保所有语言中占位符名称一致 ### Q5: 如何处理复数形式 如果项目使用 vue-i18n 的复数功能： ```typescript // zh_CN.ts（中文通常不需要复数变化，使用相同形式） export default { itemCount: "{n} 个项目 | {n} 个项目", }; // en_US.ts export default { itemCount: "{n} item | {n} items", }; ``` 使用方式： ```vue {{ $t("itemCount", { n: count }, count) }} ``` vue-i18n 会根据 count 的值自动选择单数或复数形式。 **注意**：如果项目没有使用复数功能，将复数和单数分别定义为不同的 key，如 `itemCount` 和 `itemCount_plural`。 ### Q6: 如何处理日期/数字/货币格式化 日期、数字、货币通常需要专门的格式化方法，**不要**使用简单的翻译： 1. **使用项目现有的格式化方法**： - 查找项目中是否有现成的格式化工具 - 如使用 `dayjs`, `Intl.NumberFormat` 等 2. **如果确实需要翻译日期格式**： ```typescript // 仅翻译格式说明文字，不翻译实际日期 dateFormat: { year: '年', month: '月', day: '日' } ``` 3. **数字和货币**： ```typescript // 建议使用专门的格式化，不走翻译 // 如：Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }) ``` ### Q7: 如何处理 UI 框架组件的国际化 对于 Element Plus、Ant Design 等 UI 框架的组件： 1. **遵循项目配置** - 查看项目是否已经全局配置了框架的 i18n 2. **组件自带属性** - 很多组件有内置的 i18n 属性（如 `empty-text`, `confirm-btn-text` 等） 3. **使用项目配置** - 如果项目有全局的组件文案配置，优先使用 ```vue <!-- Element Plus 示例 --> <el-table :data="list" :empty-text="$t('common.table.empty')"> </el-table> ``` ### Q8: 如何处理后端返回的错误信息 1. **如果后端返回的是国际化 key** - 直接使用，无需翻译 2. **如果后端返回原始错误信息** - 建议： - 在前端建立错误码映射表 - 或让后端支持国际化 key 返回 3. **如果是业务性质的提示** - 可以翻译： ```typescript // 错误码映射 error: { 1001: '用户名不存在', 1002: '密码错误', 1003: '账号已被锁定' } ``` ### Q9: 项目需要支持多种语言怎么办 1. **确认支持的语言种类** - 查看项目现有语言文件 2. **所有语言同步添加** - 新增翻译时，必须同时添加所有支持的语言 3. **遵循语言代码规范** - 使用项目现有的语言代码格式（如 zh-CN vs zh_CN） ### Q10: 翻译 key 冲突怎么办 1. **检查现有 key** - 确认是否真的冲突 2. **使用更具体的路径** - 添加模块前缀区分 3. **与项目成员协商** - 如果是公共 key 的修改，需沟通 ### Q11: 如何处理部分国际化的遗留代码 项目中可能存在部分已国际化但风格不一致的代码： 1. **保持现有风格** - 不强制统一，避免大规模改动 2. **新添加的遵循规范** - 新翻译使用规范写法 3. **必要时可重构** - 如果发现明显问题，可提出建议 ### Q12: 旧翻译 key 废弃怎么办 1. **保留旧翻译** - 暂时保留，避免线上报错 2. **标记废弃** - 添加注释说明已废弃 3. **后续清理** - 定期清理未使用的废弃翻译 ### Q13: 如何处理 slot 中的文字 对于 scoped slot 中的静态文字： ```vue <!-- 转换前 --> <template #default="{ row }"> <span>产品名称：{{ row.name }}</span> </template> <!-- 转换后 --> <template #default="{ row }"> <span>{{ $t("product.name") }}：{{ row.name }}</span> </template> ``` ### Q14: script 中如何使用翻译 ```vue <script setup> // useI18n 通常由项目自动导入，无需手动 import // 如项目无自动导入，则需要：import { useI18n } from 'vue-i18n' const { t } = useI18n(); // 在方法中使用 function handleClick() { const message = t("common.message.success"); ElMessage.success(message); } // 在计算属性中使用 const statusText = computed(() => { return t(`product.status.${status.value}`); }); </script> ``` ### Q15: v-html 和 $t 结合使用需要注意什么 **谨慎使用** `v-html`： ```vue <!-- 不推荐：可能有 XSS 风险 --> <span v-html="$t('message.withHtml')"></span> <!-- 推荐：分开处理 --> <span>{{ $t('message.prefix') }}<a :href="url">{{ $t('message.link') }}</a></span> ``` 如果必须使用 `v-html`，确保内容来自可信来源。 ### Q16: 函数式组件中如何使用翻译 对于使用 render 函数或 JSX 的组件： ```typescript // 使用 this.$t（需要确保组件可访问到 i18n 实例） export default { render() { return h("span", this.$t("key.path")); }, }; // 或者通过 provide/inject 传递翻译函数 // 父组件 const { t } = useI18n(); provide("i18n", { t }); // 子组件 const { t } = inject("i18n"); return h("span", t("key.path")); ``` ### Q17: keep-alive 缓存组件翻译切换问题 使用 keep-alive 缓存的组件在切换语言后可能不会重新渲染： 1. **监听语言变化** - 在 activated 生命周期中强制刷新 ```vue <script setup> import { watch } from "vue"; import { useI18n } from "vue-i18n"; const { locale } = useI18n(); // 监听语言变化，强制刷新 watch(locale, () => { // 强制组件重新渲染 refreshData(); }); </script> ``` 2. **使用 key 变化** - 为 keep-alive 组件添加 key ```vue <keep-alive> <component :is="component" :key="locale" /> </keep-alive> ``` ### Q18: 异步组件的翻译加载 异步组件的翻译需要在主应用或单独加载： 1. **如果项目使用全局翻译** - 异步组件会自动继承 2. **如果需要单独加载** - 使用 vue-i18n 的懒加载功能 ```typescript // 懒加载翻译 const messages = { en: () => import("./locales/en.json"), zh: () => import("./locales/zh.json"), }; ``` --- ## 翻译准确性要求 作为经验丰富的翻译专家，你需要遵循以下严格要求： ### 1. 理解上下文语境 翻译前必须理解文字的使用场景： | 场景 | 示例 | 翻译注意事项 | | ---------- | ---------------------------- | -------------------- | | 按钮文字 | "提交"、"确认"、"取消" | 简洁有力，通常用动词 | | 表单标签 | "产品名称"、"创建时间" | 名词短语，明确指示 | | 占位符 | "请输入名称"、"请选择日期" | 引导性语句 | | 提示信息 | "操作成功"、"保存失败" | 结果导向，说明状态 | | 对话框标题 | "新增产品"、"编辑品牌" | 动作 + 对象 | | 表格列 | "状态"、"创建人"、"更新时间" | 简洁名词 | ### 2. 根据场景选择准确翻译 同一个中文词在不同场景可能有不同译法： ``` 示例：中文 "状态" ├── 表格列标题 → "Status" ├── 业务流程中 → "State" 或 "Process Status" ├── 设备状态 → "Device Status" └── 订单状态 → "Order Status" 示例：中文 "确认" ├── 按钮文字 → "Confirm" 或 "Submit" ├── 二次确认提示 → "Are you sure?" └── 确认框标题 → "Confirmation" 示例：中文 "查看" ├── 表格操作列 → "View" ├── 查看详情 → "Details" ├── 查看记录 → "View Record" └── 查看图片 → "Preview" ``` ### 3. 保持翻译一致性 - **相同含义 → 相同翻译**：整个项目中，相同含义的文字必须使用相同的翻译 - **相同场景 → 相同模式**：类似场景使用类似的翻译结构和用词 - **建立术语表**：对于专业术语，建立统一的翻译标准 ``` ✅ 正确：所有"产品名称"都翻译为 "Product Name" ❌ 错误：有时翻译为 "Product Name"，有时翻译为 "Name" ``` ### 4. 专业术语处理 - **行业标准术语**：使用公认的英文术语 - **产品特定术语**：保持与产品文档一致 - **缩写和缩写词**：如需使用缩写，应在首次出现时提供全称 ``` 示例： - SKU → Stock Keeping Unit（库存单位） - MDM → Master Data Management（主数据管理） - CRM → Customer Relationship Management（客户关系管理） ``` ### 5. key 命名规范 遵循项目的命名规范，项目没有特殊规定时参考以下原则： ``` 命名原则： - 使用小写字母 - 使用点分隔层级 - 保持简洁但有意义 - 避免缩写（除非是公认的缩写） 层级结构建议： - 动作相关：{模块}.action.{具体动作} product.action.add, product.action.edit, product.action.delete - 字段相关：{模块}.{实体}.{字段名} product.product.name, product.product.code - 提示相关：{模块}.message.{类型} product.message.success, product.message.error - 占位符：common.placeholder.{类型} common.placeholder.input, common.placeholder.select 公共部分：common.{类型}.{具体项} common.action.add, common.action.edit common.table.index, common.table.action common.message.success, common.message.error ``` ### 6. 长度和空间考虑 - 英文翻译通常比中文短，但也要考虑UI空间 - 避免过长的翻译导致布局问题 - 必要时可以使用更简洁的表达 ### 7. 复数和单数 - 注意英文的单复数形式 - 根据实际场景选择单复数形式 - 如果项目使用 vue-i18n 复数功能，按规范使用 ### 8. 大小写规范 - 按钮文字：首字母大写（Save, Cancel, Confirm） - 表格列标题：首字母大写（Product Name, Status） - 占位符文字：首字母小写（please enter, please select） - 标题和标签：首字母大写 - **遵循项目现有规范** ### 9. 标点符号 - 英文使用英文标点（, . 而不是 ，） - 但按钮文字、标签等通常不加句号 - 提示信息根据语气决定是否加句号 --- ## 翻译决策流程 当遇到翻译时，按以下流程决策： ``` 1. 理解文字含义和用途 ↓ 2. 查看项目现有翻译库 ├── 已有相同翻译？→ 直接复用 └── 没有？→ 继续 ↓ 3. 分析使用场景 ├── 什么类型的UI元素？ ├── 在什么上下文中使用？ └── 用户期望什么语气？ ↓ 4. 选择最准确的翻译 ↓ 5. 判断翻译放哪里 ├── 通用性质？→ 公共目录 └── 模块特有？→ 模块目录 ↓ 6. 检查一致性 ├── 是否与现有术语冲突？ └── 是否需要更新术语表？ ``` --- ## 注意事项 1. **不修改项目结构** - 只在现有结构中添加内容，不创建新目录（除非项目本身就需要） 2. **保持风格一致** - 使用项目现有的命名风格（camelCase, kebab-case, SCREAMING_SNAKE_CASE 等） 3. **验证替换结果** - 修改后测试页面显示，确保没有破坏现有功能 4. **公共翻译不放模块** - 通用性质的翻译不要放到模块目录中 5. **模块翻译不放公共** - 特定业务模块的翻译不要放到公共目录中 6. **所有语言同步** - 项目支持的所有语言都要同步更新 7. **不破坏现有** - 所有修改基于现有规则，不改变现有结构 --- ## 验证与错误处理 ### 验证翻译质量 修改完成后，必须验证： 1. **语义准确性**：翻译是否准确表达原意？ 2. **场景合适性**：在当前场景下是否自然？ 3. **一致性检查**：类似文字是否使用类似翻译？ 4. **拼写和语法**：英文翻译是否有拼写错误或语法问题？ 5. **UI适配性**：翻译后是否超出UI空间？ ### 验证方法 1. **运行时检查**： - 切换语言测试页面显示 - 检查控制台是否有 missing translation 警告 2. **代码检查**： - 搜索是否还有遗漏的硬编码 - 确认所有 key 都已正确添加 3. **如果项目有 lint 工具**：按项目规范执行 ### 错误处理 1. **翻译错误**： - 立即修正错误翻译 - 检查是否影响其他使用该翻译的地方 2. **遗漏翻译**： - 补充遗漏的翻译 - 检查是否还有其他遗漏 3. **格式问题**： - 保持与项目现有格式一致 - 使用项目的格式化工具（如果有） 4. **如果出现问题**： - 使用 git 回滚到修改前 - 检查问题原因后重新修改


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)