配置 HelloWorld 语言包的核心是把“词条”当成代码来管理:统一资源格式与命名、全程使用 UTF-8、明确占位符与复数规则、处理 RTL 与字体替换、建立提取—翻译—校验—打包的自动化流水线,并在上线前做伪本地化与截图回归,通过版本化和回滚策略确保平滑发布。

先说为什么要认真做语言包配置
很多团队把本地化当作“翻译工作”,结果上线后出现乱码、变量错位、占位符暴露、复数错误、UI 溢出、或是某些语言根本看不懂。其实,把语言包当成工程化对象去管理,能大幅降低这些问题的发生概率,也能让产品在不同市场表现一致。
用费曼法简单拆解本质
- 什么是语言包? 就是一组键值对(key→译文),外加元信息(语言、区域、版本、编码等)。
- 为什么出问题? 因为文件格式不统一、占位符不一致、编码错误、没有复数/性别规则、缺乏测试。
- 目标是什么? 减少人工干预,把翻译流程变成可重复、可验证、可回滚的工程流程。
准备阶段:要准备哪些东西
先别急着翻译,先把基础铺好:
- 定义语言表(supported locales):例如 en, en-US, zh-CN, zh-TW, ja, ko, fr, de, es, ru, ar 等。
- 选定资源格式:.json/.po/.resx/strings.xml/xliff 等(下文详述)。
- 确定编码:全部使用 UTF-8(无 BOM)。
- 定义占位符规范:比如使用 ICU MessageFormat({name}、{count, plural, one {…} other {…}})或简单的 %s/%1$s,但项目内要统一。
- 准备风格词典与术语表(glossary):品牌名、产品名、不可翻译词、专业术语及示例。
常见资源格式与适用场景
不同平台偏好不同格式,选对格式能省很多事:
| 平台 | 文件格式 | 优点 |
| Web / JavaScript | JSON(i18next) | 结构化、易于加载,适配前端框架 |
| Mobile Android | strings.xml | 原生支持,资源合并机制成熟 |
| Mobile iOS | Localizable.strings / .stringsdict | 支持性别、复数,通过 .stringsdict 处理复数 |
| 桌面 / .NET | .resx | 支持二进制资源及元信息 |
| 专业本地化流程 | XLIFF / PO | 翻译工具友好,支持上下文与注释 |
占位符与 ICU MessageFormat
ICU MessageFormat 很强,能处理复数、选择(select)、参数化文本。举例:
{count, plural, =0 {没有消息} one {1 条消息} other {# 条消息}}
推荐优先使用 ICU,有助于减少因复数规则不同而导致的逻辑错误(比如俄语、阿拉伯语)。
工程化的工作流(推荐)
把语言包当成代码,建议的步骤是:
- 提取(Extraction):从代码中自动提取待翻译字符串,生成基线资源文件。
- 伪本地化(Pseudo-localization):先把资源替换为伪译文(加长、加符号、改变方向),用于发现 UI 问题。
- 机器翻译 + 人工校对:MT 快速覆盖,人工校对保证质量(MTPE)。
- 术语一致性校验:自动化检查术语表、品牌名是否被误译或被翻译。
- 自动化 QA:字符串长度校验、占位符检查、HTML 标签平衡、RTL 检查、编码检查。
- 截图回归 / UI 测试:关键页面在目标语言环境下截图比对,发现溢出或错位。
- 打包与发布:版本化语言包,支持回滚与灰度发布。
具体的自动化校验项(示例)
- 占位符完整性:所有 key 在源语言和目标语言占位符一致(数量、命名)。
- 编码与 BOM 检查:UTF-8 无 BOM。
- 未翻译检测:目标语言中不应出现英文(或源语言)原文,除特殊术语。
- 复数规则检查:目标语言存在正确的 plural 分支。
- HTML / Markdown 标签完整性。
- 长度阈值告警:对长文本做截断或 UI 预案。
RTL(从右到左语言)的额外注意事项
阿拉伯语、希伯来语等需要从右到左显示,单纯翻译文字并不能解决布局问题:
- 在 CSS/样式层面支持 dir=”rtl” 切换。
- 注意图标方向(比如箭头、进度条)和排版对齐。
- 日期/时间/数字位置在 RTL 环境下也可能调整。
- 测试要在真实 RTL 操作系统或浏览器模拟器里进行。
字体与排版
不同语言对字体的支持差别大,配置语言包时要一并考虑字体降级和替换:
- 提供备选字体集(font-family 回退链),确保常用字形可显示。
- 中文、日文、韩文一般需要更宽的字重支持,避免字符缺失。
- 对于复杂字形(如阿拉伯语连写、印地语合字),选择合适的 OpenType 支持字体。
版本管理与打包策略
语言包应像代码一样被版本控制,并纳入 CI/CD:
- 每次翻译变更都产生一次提交,并带上变更说明(哪些 key、哪些语言)。
- 使用语义化版本或内容哈希来标识语言包版本。
- 部署时支持灰度发布(部分用户先行),发现问题可回滚到上一个语言包版本。
与翻译团队的协作规则
工程化之外,人也是关键:
- 给译员提供上下文:截图、使用场景、字符限制。
- 准备风格指南与术语表,且保持可编辑和可追溯。
- 建立反馈渠道:译员能提交问题、开发能提供注释。
- 定期维护翻译记忆(TM)与术语库,提升一致性与效率。
示例:一个简单的配置清单(可复制)
你可以把下面的条目当作 checklist:
- 所有资源文件 UTF-8 编码,统一存放路径 /i18n/{locale}/。
- 占位符统一使用 ICU(或团队约定格式)。
- CI 流水线包含:提取 → 伪本地化 → 自动校验 → 推送给翻译 → 回归测试 → 打包发布。
- 每次翻译变更由机器人提交 MR,人工复核后合并。
- 关键页面做截图差异化检测,非关键页面做抽样检测。
常见问题与快速应对策略
出现乱码怎么办?
优先检查文件编码与 HTTP header(Content-Type: text/plain; charset=utf-8),确认构建工具未在打包时改变编码。
占位符错位或被翻译了?
建立占位符的严格校验:在 CI 中加入脚本比较源文件与译文件的占位符列表,发现差异即阻断。
复数处理不对?
使用 ICU MessageFormat 或平台原生复数支持,并让译员在翻译工具里看到复数变量示例。
工具与实践参考(不外链,只列名)
- i18next(前端国际化库)
- react-intl / formatjs(React 国际化)
- Android Studio strings.xml 管理
- Xcode Localizable.strings 管理
- POEdit / Lokalise / Crowdin(常见的本地化管理工具)
- ICU MessageFormat 文档(用于复杂参数化)
收尾的话,关于迭代与度量
本地化不是一次性工作,而是持续迭代的过程。建议建立几个关键指标来衡量:翻译完成率、线上回退次数、国际化相关缺陷数、平均翻译交付时间。根据这些数据调整流程。
说到这儿我忽然想到一个小技巧:在每次大版本前做一次“伪本地化冒烟”,就是把所有译文替换成易识别的伪译(比如在前后加 [[ ]],并把文本长度加 30%),这样能在 UI 层面很快发现溢出、错位和未国际化的软素材,常常能挽救上线后的尴尬。