你的 App 即将进军新市场。产品团队已批准翻译文案,市场部已准备好发布,客服也更新了话术。然而测试发现:结账按钮被硬编码为英文,日期格式错误,货币分隔符不符合习惯,甚至更长的翻译导致主操作按钮超出了屏幕。阻碍发布的不仅是翻译质量,更是几个月前在 codebase 中做出的决策。
这种情况正是 App 国际化的实际切入点。国际化(通常简称为 i18n)旨在做好产品准备,以便在不重写业务逻辑的情况下,即可添加不同的语言、地区、书写系统和文化惯例。随后,通过本地化(Localization)将准备好的产品适配到特定市场。
其商业价值在应用经济中显而易见。对 730,024 个 iOS App Store 应用的 2026 年快照调查显示,中位数应用仅支持 一种语言,而 68.6% 仅支持单一语言。据估计,月收入达到 $10,000 或以上的应用 平均支持 五种语言,以及 50.7% 。在这一高收入层级中,有应用支持五种或更多语言。这些数据并不能证明仅靠本地化就能创造收入,但它们表明,对于具有更广商业雄心的应用来说,多语言支持是非常普遍的。
本指南将从思维模型深入到工程模式、平台差异、工作流自动化、测试及迁移。它适用于原生移动产品、Web 应用、Capacitor 混合应用以及 Electron 桌面软件。隐私和区域合规性也应纳入发布计划,因此,在应对监管要求的团队可以将本指南与 GDPR 合规检查清单.
目录
- App 国际化简介及为何现在至关重要
- App 国际化的真正含义
- 国际化应用必备的核心模式
- 移动端 Web Capacitor 与 Electron 的平台特定注意事项
- 可扩展的工具库与翻译工作流
- 全球化应用的测试、QA、性能与安全
- 结合 Code 示例与迁移清单综合实践
App 国际化简介及为何现在至关重要
团队往往在市场发布前几天才发现国际化问题。产品要求加语言选择器,设计要调整多个界面,工程团队则发现面向用户的文本散落在组件、校验规则、通知、分析标签和原生配置文件中。日期和数字也有同样的问题。以显示文本形式存储的日期无法安全地重新格式化,而由多个独立字符串拼接出的价格,在其他 locale 中可能需要不同的顺序。
这种滞后发现会带来三个代价高昂的选择:推迟发布、接受明显缺陷,或修改从未设计为随 locale 变化的 code。把 i18n 视为架构能力会改变工作流。市场扩张将变成一项涉及资源、展示、测试和发布配置的可控操作,而不是重写。
实用原则: 构建 App 时,要让新增 locale 只改变资源和展示,而不是业务规则。
翻译只是全球化准备工作的一部分。 即使翻译正确,如果布局无法适应文本长度,仍可能导致界面错乱。如果底层值以格式化文本形式存储,即使货币翻译正确,也可能误导用户。此外,当 Web 层和 Native 层检测到的 Locale 不一致时,语言选择器也可能产生异常行为。
过晚发现 i18n 问题会增加运维成本。工程师必须在旧组件中追踪字符串,翻译人员会收到不完整的上下文,审核人员只能匆忙测试变更,而发布团队则需在多个平台包之间协调修复。对于 Capacitor 和 Electron 团队,在平台和发布策略允许的情况下,通过 Live Update 工作流交付已批准的本地化资源和展示修复,无需等待应用商店审核,从而缩短反馈周期。核心转变在于:将本地化变更视为受管理的发布产物,而非最终的翻译交付。
前进的方向很明确:
- 夯实基础: 将面向用户的资源与应用逻辑分离,并正确处理 Locale 相关的值。
- 处理语言行为: 支持复数规则、文本扩展、书写方向、格式化以及无障碍语言切换。
- 适配各平台: 兼顾 iOS、Android、浏览器、Capacitor WebViews 以及 Electron 打包。
- 保持发布节奏: 打通提取、翻译、审核、测试和部署流程,确保新字符串不会因项目后期阶段而滞后。
- 验证界面: 测试长文本、从右至左布局、语言区域组合、回退机制、性能以及更新安全性。
App 国际化是一项发布工程实践。它让后续的产品变更保持可本地化,让团队能通过合适的交付路径修复语言问题,并涵盖区域隐私工作,例如 GDPR 合规检查清单.
App 国际化的真正含义
我们先用房子来做类比。 国际化(Internationalization)是在装修房间之前预先装好的、可灵活调整的布线和管道。 本地化(Localization)是为特定地区装饰和布置这栋房子。翻译(Translation)则是更换标签、说明和标识上的语言。
顺序至关重要。如果布线被埋在为某一种电器设计的墙体里,增加新电器就会变得非常昂贵。在软件中,硬编码字符串、固定宽度的控件、拼接的句子以及与特定区域绑定的业务逻辑,也会造成同样的限制。
三个术语,三种职责
国际化,即 i18n, 是指通过设计和开发工作,让 App 在不改变核心行为的前提下支持不同的语言和区域。它包括资源加载、语言区域选择、格式化、文本方向、字体支持以及灵活的布局。
本地化,即 l10n, 将准备好的 App 适配到特定区域。这包括翻译后的界面文案、特定地区的格式、本地术语、符合文化背景的图像以及针对特定市场的默认设置。
翻译 将内容从一种语言转换为另一种语言。它主要处理含义和措辞,但一个优秀的翻译工作流还需要上下文、截图、字符限制以及每个字符串出现位置的信息。

一个实用的实现边界是本地化资源。与其将内容直接放入 Payment failed 组件中,不如让组件请求一个语义化 Key,例如 payment.error。英文资源将该 Key 映射为英文文本,而另一个资源则将相同的 Key 映射为不同的翻译。组件只需知道它需要显示支付错误,而无需关心错误的具体措辞。
这种解耦同样适用于字符串之外。货币值应存储为数值,而非带有符号的字符串。时间戳应存储为时间戳,而非已格式化的日期。应将本地化信息传递给格式化工具,而不是将分隔符或月份名称嵌入到业务 code 中。
为什么夯实基础能降低风险
当资源和格式化规则独立于业务逻辑时,新增语言无需改动购买计算、身份验证流程或数据模型。工程师可以更新资源 bundle,译员可以在翻译管理系统中工作,QA 也能测试生成的界面,而不会影响无关行为。
这种分离也能明确职责归属。设计师可以定义可安全扩展的组件,译员可以审核上下文,产品经理可以决定支持哪些市场,工程师可以落实缺失 key 和 fallback 规则。每个角色在工作流中都有清晰定位。
跳过 i18n 的团队常把每个新 locale 当成特殊例外;为 i18n 设计的团队则把 locale 当作输入。仅此一点,就能让全球化支持更容易理解和推理。
国际化应用必备的核心模式
优秀的 i18n 靠少量可重复的模式落地。应在组件、数据和发布层应用这些模式,而不是在单 locale 代码库上叠加一个语言切换器。

将字符串提取到资源中
这项改造是落地的第一步:
改造前:
showToast("Your profile was saved");
改造后:
showToast(t("profile.saved"));
资源文件:
{
"profile": {
"saved": "Your profile was saved"
}
}
使用描述含义的 key,而不是英文句子本身。 profile.saved 即使英文措辞变化也仍然有用,而基于原句的 key 则可能产生误导。当同一个词可能有不同含义时,请提供翻译上下文,例如 “Present” 是按钮操作还是状态。
一个正确实现国际化的应用会把所有面向用户的字符串,以及日期、数字、货币和符号,提取到 locale 资源或 formatter 中。这 移动端 i18n 工程蓝图 解释了这种分离为何能让团队添加语言而无需改动业务逻辑。
使用 message format 处理语法
这样做不安全:
`${count} items`
硬编码模式假定每个 locale 的复数行为和词序都相同。Unicode CLDR 为日期、时间、时区、数字、货币和复数类别提供通用的本地化数据层。正如 CLDR 的本地化最佳实践指南所述,复数规则因 locale 而异,因此应用需要能感知 locale 的选择机制,而不是单一固定模式。
ICU 风格的消息可能如下所示:
{count, plural,
=0 {No items}
one {# item}
other {# items}
}
formatter 会选择正确的分支。请保持整条消息完整,以便译者在语法需要时重新排列数字和名词。
使用能感知 locale 的 API 格式化值
不要手动拼接日期:
`${day}/${month}/${year}`
使用 formatter:
new Intl.DateTimeFormat(locale, {
dateStyle: "medium"
}).format(date)
同样的原则也适用于数字和货币:
new Intl.NumberFormat(locale, {
style: "currency",
currency: currencyCode
}).format(amount)
Intl,ICU 和基于 CLDR 的库可以处理因地区而异的规范。它们还能将显示逻辑保持在应有的表现层附近。
针对方向和扩展性进行设计
文本在不同语言间的长度扩展并不可预测。按钮需要灵活的宽度,卡片需要可自适应的高度,标签也不应局限于单行。请使用允许内容增长的布局系统,并在翻译人员进行最终审核前,使用长文本伪翻译(pseudo-translations)来测试控件。
从右至左(RTL)的支持不仅仅是翻转文本对齐方式。图标、导航顺序、内边距、动画和方向性手势可能也需要镜像处理。在平台支持的情况下,请使用逻辑属性,例如 margin-inline-start 而不是仅限左侧的规则。图片、字体和嵌入文本也需要审查。一种能很好渲染某种脚本的字体可能无法覆盖另一种,而包含英文单词的图片可能需要本地化资源,而非仅仅是翻译后的覆盖层。
有关界面设计的具体指导,使用 Capacitor 的团队还可以参考这些 跨平台 UI 和 UX 实践.
移动端 Web Capacitor 与 Electron 的平台特定注意事项
核心规则保持一致,但不同的运行时环境会提供不同的语言信号和打包限制。原生应用可以通过平台 API 读取设备偏好设置;浏览器通过浏览器设置和 JavaScript API 暴露语言偏好;而混合应用(Hybrid App)同时拥有 WebView 和原生壳层,这意味着团队必须决定 Locale 的数据源究竟该以哪里为准。
| 平台 | Locale 检测 | 格式化方案 | 关键坑点 |
|---|---|---|---|
| iOS | 设备或应用语言设置,在支持的情况下具备应用特定的行为 | Foundation formatters 与 JavaScript Intl 用于 Web 内容 |
如果原生页面与 WebView 页面使用独立的 Locale 状态,可能会出现不一致的情况 |
| Android | 设备与应用语言设置,取决于具体实现 | Android locale APIs 与 JavaScript Intl 在 Web 内容中 |
资源限定符与 WebView 资源需要完善的降级策略 |
| Web | 浏览器语言偏好、用户选择、URL 或账户设置 | JavaScript Intl、基于 ICU 的库以及服务端 locale 处理 |
服务端与客户端的 locale 决策必须保持一致,以避免渲染冲突 |
| Capacitor | 原生偏好结合 WebView 状态 | 原生格式化程序、JavaScript Intl以及共享资源包 |
通过 Live Update 更新 JavaScript,无需更改 Native Build 资源即可实现本地化内容变更 |
| Electron | 操作系统语言、应用偏好或账号设置 | JavaScript Intl, Node 端逻辑以及渲染器资源 |
在生产环境构建中,必须正确包含并加载打包好的本地化资源 |
原生移动应用
iOS 和 Android 各自提供原生本地化系统,但许多团队也会通过 JavaScript 渲染大量 UI。需决定原生层与 Web 层是否共享语言代码、翻译 Key 和回退规则。确保语言选择逻辑清晰,避免用户选定的语言在下次启动时被设备偏好覆盖。
应用商店的元数据也值得关注。如果应用的标题、副标题和描述仍保持单一语言,即使应用本身已本地化,也可能降低搜索曝光率。 2023 年针对进入海外市场的主流美国应用的分析 发现 60% 本地化了其 iOS 标题,几乎 90% 本地化了产品描述,并且 60% 本地化了副标题。在 Android 上, 70% 本地化了标题和 89% 本地化了描述。这些属于应用商店层面的决策,而非运行时 UI 决策,因此应将其列入发布清单,而不是默认由工程端的 bundle 处理。
Web 应用
Web 端需要在 URL、服务端渲染、浏览器偏好和账户偏好之间建立稳定的关联。如果服务端渲染的是英文,而浏览器立即切换到德文,用户可能会看到闪烁或 hydration mismatch。请确定优先级顺序,持久化用户的选择,并确保回退语言(fallback locale)是确定性的。
当应用包含大量翻译内容时,请对 locale bundles 进行懒加载。保持默认体验的快速响应,同时确保在离线或获取失败时,仍有安全的 fallback 路径进行渲染。
Capacitor 与 Electron
Capacitor 应用通常在 iOS、Android 和浏览器端共享 Web 代码库。这提高了共享资源的效率,但 native plugins 可能仍会暴露特定平台的 locale 行为。WebView 应当从单一权威源接收标准化的 locale,而不是分别根据浏览器和设备设置进行猜测。评估这些边界的团队可以查看 Capacitor 如何处理平台差异.
Electron 增加了打包方面的复杂性。渲染进程在开发环境和打包后的应用中加载本地化文件的方式可能不同,因此生产环境构建必须验证资源是否存在、是否可寻址,并确保它们同步更新。如果 JavaScript bundles 支持 Live Update,则需要明确本地化文件是否属于同一个签名 bundle,以及更新失败时如何回滚。
可扩展的工具库与翻译工作流
仅靠翻译库本身无法建立起本地化工作流。团队可能会使用 i18next、FormatJS 或原生 Intl API,但如果 key 的所有权、上下文、审核、交付和回滚机制不明确,仍可能导致发布失败。请将每一个新字符串视为软件制品,并像对待 code 一样通过相同的控制流程。
一个可扩展的工作流遵循清晰的链路:
- 开发者添加一个语义化 key 并提供必要的上下文、截图、变量和字符限制。
- 自动化工具提取或校验该 key 并将其发送至翻译管理系统 (TMS)。
- 翻译人员和审核人员使用相同的源文件 同时构建流程会检查占位符和必需的 locales。
- CI 检索已批准的资源 并将它们与应用程序打包,或通过经过批准的更新通道进行发送。
- QA 检查已更改的语言区域 而不是从头开始重复每一次语言审查。
- 发布控制管理曝光范围,从内部、Beta 或目标用户开始,然后再进行大规模推广。

为什么流水线至关重要
瓶颈通常在于等待审核通过的内容,而不是编写 code。 2026 年 i18n 工作流开发者调查 发现 64% 的受访者将翻译工作流效率列为首要挑战, 78% 表示等待翻译会延迟发布,并且 52% 缺乏除人工抽检之外的系统化翻译 QA。同一份报告指出, 41% 已采用 OTA 系统,并且 28% 计划在 2026 年实施。这些发现将本地化与发布交付相结合,而非将其视为独立的内容周期。
CI 应在打包前拦截可预见的错误:
- 缺失 Key: 当源语言 Key 缺少 fallback 时,触发失败或警告。
- 占位符偏移: 验证诸如
{count}之类的变量是否在每条翻译消息中都存在。 - 孤儿 Key: 标记不再出现在应用中的资源。
- 语法错误: 拒绝格式错误的 JSON、ICU 消息或资源文件。
- 语言区域覆盖范围: 报告哪些已支持的语言区域发生了变化,哪些仍需审核。
有关 CI 集成模式,请参阅 开发者体验工具概览.
将 Live Updates 视为发布工程
对于 Capacitor 和 Electron 团队,本地化修复可以包含在已签名的 JavaScript、CSS、文案、配置和资源 bundle 中。像 Capacitor 这样的 Live Update 平台 Capgo 可以针对特定 channel,交付仅包含变更文件的增量更新,展示采用率和失败指标,并提供自动回滚保护。只要团队定义了更新策略、审核流程、签名规则和 Native Build 兼容边界,就可以通过这种发布工程化的路径来修正翻译错误的标签或布局规则,而无需等待应用商店的完整审核。
Live Update 并不能取代应用商店发布。Native 字符串、权限、平台 API 以及超出已安装 Native 运行时的变更,仍需通过相应的分发渠道。它们为兼容的本地化变更提供了一条更快的通道,否则一个微小的文案修复可能需要等待下一次应用版本发布。
全球化应用的测试、QA、性能与安全
国际化测试应在用户发现问题之前暴露假设。仅凭一张翻译后的截图是不够的,因为失败往往取决于语言区域、数据长度、屏幕尺寸、书写方向和平台的特定组合。

从极端内容开始
伪本地化(Pseudolocalization)通过将普通字符串替换为故意加长、带重音符号或带有标记的测试文本,来帮助发现硬编码字符串、被截断的标签、固定高度的卡片以及仅支持英文的控件。请同时测试空状态和填充状态,因为复数消息和校验错误通常会触发不同的布局路径。
RTL(从右至左)测试需要进行完整的导航检查。检查文本对齐、返回按钮、图标、图表、滑动手势、表单字段,以及包含产品 code 的阿拉伯语等混合方向内容。不要自动镜像所有图标。方向性图标可能需要镜像,而品牌标识和某些物体图标应保持不变。
自动化 locale 矩阵
围绕支持的“语言+地区”组合构建测试矩阵,而不仅仅是语言名称。不同地区的同一种语言可能存在不同的习惯,尤其是在日期、数字、货币、日历和时区方面。
- 功能检查: 确认 Locale 选择、持久化、回退机制、复数分支及错误消息。
- 视觉检查: 截取包含长字符串、启用 RTL 以及窄屏宽度下的关键界面。
- 语言检查: 为审核人员提供上下文、截图、变量以及预期的操作逻辑。
- 回归检查: 测试更新安装、下载中断、离线启动和回滚行为。
随着本地化资源增长,性能优化需要严格把控。适时按语言或功能拆分大型 bundle,懒加载非必要语言,并缓存已验证的资源。除非应用有可靠的 fallback,否则应避免让首屏依赖缓慢的翻译请求。
安全也应纳入同一轮审查。将语言标识符和用户提供的翻译内容视为输入,验证资源结构,保护翻译管理凭据,并验证远程交付 bundle 的完整性。Live Update 工作流应使用签名制品、受控 channel、版本兼容性检查、可观测的失败以及经过测试的回滚路径。设计部署控制的团队也可以参考本指南进行 多区域部署.
结合 Code 示例与迁移清单综合实践
结账页面说明了迁移顺序为何重要。从用户接触最多的 code 开始,然后用能感知 locale 的边界替换每个假设。硬编码的标签、日期、货币、复数消息和固定宽度布局应拆成独立的迁移任务,并用 fallback locale 防止资源缺失导致控件空白。
例如,替换现有组件中的货币拼接逻辑。
改造前:
price.textContent = currencySymbol + amount;
改造后:
price.textContent = new Intl.NumberFormat(locale, {
style: "currency",
currency: currencyCode
}).format(amount);
保留 amount 作为原始数值。格式化程序会自动处理符号位置、分隔符、小数点习惯及其他区域细节。这避免了在结账逻辑中到处散布本地化规则。
实用的迁移清单:
- 盘点: 查找面向用户的字符串、格式化后的数值、包含文本的图片以及本地化假设。
- 外部化: 将文案移至资源文件,并使用语义化 Key 和翻译上下文。
- 规范化本地化状态: 定义检测机制、用户覆盖、持久化及回退行为。
- 替换手动格式化: 使用平台或 JavaScript 的本地化感知格式化程序。
- 加固布局: 测试文本扩充、截断、双向文本、字体及 RTL 镜像效果。
- 自动化校验: 在 CI 中检查缺失的键、占位符、资源语法以及已变更的语言区域。
- 安全发布: 通过应用商店流程或受控的 Live Update 通道发布兼容的本地化变更,并利用签名、分阶段发布、监控和回滚功能。
首选一个高流量流程(如 onboarding 或 checkout)进行试点。一旦其资源边界和校验 pipeline 运行正常,再将相同的规范推广至整个 App,而不是尝试进行失控的大规模重构。
对于 CapacitorJS 和 Electron 团队,Capgo 支持针对兼容的 JavaScript、CSS、文案、配置和资源变更进行签名的 Live Update bundle 发布。通过 Channels、差异化交付、可观测性和回滚保护,可以将本地化修复接入现有的 CI/CD 工作流,从而减少每次兼容性修正对应用商店审核的依赖。在将其扩展到其他语言区域之前,请根据您的部署控制机制评估该发布路径。