适用于 Web 与原生 UI 的本地化工作流程
实用的本地化工作流:组织翻译键、明确责任、处理复数与语法,并运行 QA,让 Web 与原生界面不会被本地化破坏。

当本地化没有被管理时会出什么问题
未管理的本地化通常先在小处以恼人的方式失败,随后以昂贵的方式崩盘。昨天还能容下的标签今天会溢出。缺失的键以原始标识符出现。英文里听起来自然的复数在另一种语言里变得错误,甚至粗鲁。
大多数团队最终在压力下修复同样的问题:
- 按钮被截断、标题被裁切或文字与图标重叠
- 缺失键回退到英文或显示键名
- 复数形式错误(例如,"1 items")以及带性别的语言中语法错误
- 同一概念在不同界面中措辞不一致
- 因一处界面缺少翻译而临时修补导致的最后一刻热修复
Web 和原生界面常以不同方式出问题。在 Web 上,灵活的布局可能隐藏问题,直到特定视口或浏览器暴露它们。文本可能意外换行、把按钮往下推或破坏网格。在原生应用中,间距更严格。较长的翻译可能把重要元素推出屏幕,与无障碍字体大小冲突,或因组件不自动调整尺寸而被截断。
一个稳固的本地化工作流通过让键稳定、翻译可审查和常规 UI 检查来预防大多数问题。它能让你更少惊讶地发布更新。但它无法修复源文本本身模糊的问题。如果原始文案不清(比如没有上下文的“Open”或“Apply”),翻译仍然是猜测。
简单的成功定义不是“所有内容都被翻译”,而是:
- 界面在 Web 和原生屏幕上保持可读
- 更新速度快,因为键不会频繁变动
- QA 在用户之前发现问题
举例:如果购物车界面显示“{count} item(s)”,未管理的字符串会导致尴尬的复数形式和错位的间距。受控的方法强制使用正确的复数规则,并在发布前发现一个在德语里增长 30% 的按钮。
决定所有权与单一真实来源
当没人能回答“哪个文本是真正的?”这个问题时,本地化工作流就会迅速崩溃。为字符串选择一个单一的真实来源并让它枯燥地明确。这个来源可以是仓库文件、翻译平台或内部表格,但必须是能够解决争议的唯一位置。
按决策而不是职位定义角色。需要有人批准含义和语气(通常是产品或市场),需要有人保持键在代码中可用且稳定(通常是工程),还需要有人保护 UI 约束(通常是设计),特别是在 Web 与原生表现不同的时候。
一种能避免大多数冲突的职责划分:
- 键创建者:发布界面的人在 UI 需要新文本时创建新键。
- 措辞审批者:PM 或文案负责人签署基础语言文本。
- 翻译编辑者:翻译人员可以更改翻译,但不能重命名键。
- 键变更:只有键的所有者可以废弃或合并键,并需说明原因。
设定响应时间预期以避免发布被拖延。例如:新键请求在 1 个工作日内确认,基础措辞在 2 天内审批,关键修复(断裂的 UI、错误的法律文本)在数小时内响应。
具体示例:团队构建一个新的“重置密码”流程,包含 Web 和原生界面。开发者添加键,PM 批准最终英文文本,翻译人员填写其他语言。如果翻译者注意到“Reset” 应为 “Change”,他们更新翻译,但键保持不变。如果 PM 想在多个界面重用文案,只有键所有者能做这种结构性改动以免静默破坏其他部分。
键策略:重用、稳定性与界面边界
良好的本地化工作流从一个规则开始:键是标识符,不是英文句子。把它们当成零件编号。如果以后改了措辞,键通常应保持不变。
当含义不同就创建新键。当含义相同就重用键,即便屏幕不同。如果 profile 屏幕上的 “Save” 与设置屏上的 “Save” 都表示“保存更改”,它们可以共享一个键。但如果 “Save” 表示“收藏”,则应使用不同键,因为翻译可能需要不同的动词。
把短的 UI 标签与较长的内容分开。按钮标签、提示和错误信息通常会有不同的翻译和长度限制。将它们作为独立键便于在不破坏其他界面的情况下调整语气和标点。
屏幕边界而不强制一致措辞
目标是跨 Web 和原生重用,但当平台需要不同用语时不要强制统一。原生权限提示通常需要比 Web 提示更清晰、更正式的文字。在这种情况下,保留相同概念但使用平台专用键,以便每个 UI 都读起来自然。
一个实用模式是按功能和 UI 类型对键分组,然后在这些边界内重用:
- 在同一功能内重用相同含义的键
- 按 UI 类型拆分键(标签 vs 帮助 vs 错误 vs 系统提示)
- 仅在措辞必须不同的时候使用平台变体
- 保持键稳定,只改显示文本
- 添加上下文说明(出现位置、字符限制)
例如,相同的“删除客户”操作可能出现在 Web 管理面板和原生外勤应用中。你可以重用核心操作标签,但为原生确认文本保留单独键,以便在需要更强警告或更短行时使用。
翻译键的命名与组织
良好的命名系统让本地化变得无聊(而这是好事)。人们可以快速找到字符串,翻译者获得上下文,键在文案变更时仍保持稳定。
使用一个可读的约定来回答四个问题:在什么地方、是什么、用途是什么、是否是变体。一个适用于 Web 和原生的简单模式是:
<product_or_domain>.<screen_or_flow>.<component>.<purpose>[.<variant>]
例如,在客户门户中:portal.login.button.submit 或 portal.orders.empty_state.title。这让键按屏幕或流程分组,也方便按组件搜索。
糟糕的键要么太模糊,要么太绑定当前英文文本:
- 好:
portal.profile.field.email.label - 差:
emailText(无范围,无意图) - 差:
please_enter_your_email(当文案变更时就会失效) - 好:
portal.checkout.error.payment_failed - 差:
error_12
变体应明确表示,而不是通过标点或混合大小写来变通。如果需要为移动标题准备更短的标签,添加后缀变体:...title.short vs ...title.long。如果需要大小写差异,除非平台无法安全转换文本,否则优先使用平台转换;否则再用单独键,如 ...button.save 和 ...button.save_titlecase。
占位符也需要规则,以免翻译者猜测。
- 使用命名占位符:
{user_name}、{count}、{date} - 切勿拼接:不要构建像 "Hello " + name 这样的字符串
- 当单位与语言相关时把单位留在字符串内:
{count} items,而不是把items放在外面拼接 - 定义允许的格式:ISO 日期、货币或平台特定的日期格式
- 对复杂字符串添加简短备注(例如
{count}是否可以为零)
能节省返工的复数与语法规则
复数通常是工作流首次崩溃的地方。很多团队假设每种语言只有“单数”和“复数”,随后发现界面听起来怪异或需要最后一刻修正。
语言可能有多种复数类别。英语主要用 one 与 other,但像俄语、波兰语、阿拉伯语和捷克语可能使用 few、many 或 zero 等形式。如果你早期硬编码了单一模式,之后就会在 Web 与原生上重写字符串。
为复数字符串选择一个标准并在所有地方坚持它(Web、iOS、Android、后端渲染文本)。一个实用方法是为每个键存储复数形式集合,而不是为每种形式分开建键。基于 CLDR 类别选择表单,以匹配真实语言规则。
一个防止返工的规则:不要把 UI 句子拆成碎片然后拼接,比如 "You have " + count + " messages"。词序会变,有些语言根据数字需要不同的词尾或格位。
一个实用的键模式
对于消息计数器,定义一个稳定键并把数字当参数传入。然后为每种语言提供翻译者所需的形式。
- 每个概念使用一个键(例如:
inbox.message_count) - 支持 CLDR 表单(zero、one、two、few、many、other)
- 在完整句子中始终使用占位符(例如:
{count}) - 当含义不清时添加翻译备注(这是“消息”还是“未读消息”?)
性别与语法格
有时复数规则还不够。如果界面在称呼某人("Welcome, Alex")或指代角色("assigned to him/her"),某些语言需要基于性别使用不同词。其他语言在某些介词后会改变词尾(语法格)。
遇到这种情况时,为真正不同的语法创建单独字符串,而不是仅为风格差异添加键。目标是在减少键数量的同时,避免 QA 时出现“正确但上下文错误”的翻译意外。
跨平台的格式与布局约束
翻译可能正确但仍会破坏 UI。Web 与原生对文本的渲染不同,因此你的工作流应包含格式化规则与布局检查,而不仅仅是翻译字符串。
标准化数字、货币与日期的显示方式。避免像 "$" + amount 这样的拼接或在标签中硬编码日期格式。使用面向地区的格式化,以便分隔符与顺序符合期望(1,000.50 vs 1 000,50;日-月-年 vs 月-日-年)。时区是常见陷阱:把时间戳存为 UTC,按用户本地时区格式化,并在时间为特定时区时明确标注(例如取货时间)。
文本方向是另一个无声的破坏因素。如果支持从右到左(RTL)语言,需计划镜像布局和会“移动”的标点。表示方向的图标(箭头、返回按钮、进度步骤)通常也需翻转。即便尚未全面支持 RTL,也应把快速的 RTL 检查纳入评审。
在移动端,字体与间距的变化比 Web 更明显。某个在 Web UI 中能容纳的字符串,在 SwiftUI 或 Kotlin 中可能会尴尬换行。决定一个安全的最小字体大小,允许标签在合适位置换行,并为默认字体无法覆盖的脚本定义备用字体。
无障碍也需要本地化检查。屏幕阅读器在读数字、缩写和混合语言文本时可能出现意外行为。
能防止大多数问题的布局守则:
- 设计时考虑文本膨胀(30–50%),避免固定宽度按钮。
- 把动态值(计数、价格、日期)作为独立的已格式化 token。
- 使用平台原生的日期和数字格式化,而不是自定义模式。
- 在发布前测试一个 RTL 语言和一个“长文本”语言。
- 在核心流程(登录、结账、设置)上运行屏幕阅读器检查。
示例:一个 “Total: $1,234.50” 标签可能需要变成 “1 234,50 €”,货币符号位于数值之后,间距不同,并且在屏幕阅读器中需要在 “Total” 与金额之间加入停顿以便更好地朗读。
从新界面到发布的逐步工作流
本地化工作流应比大多数团队预期的更早开始:在屏幕仍在设计阶段时就启动。如果等到 UI“完成”才开始,你会匆忙翻译、发布被截断的文本或为图方便而硬编码字符串。
在设计每个标签、按钮和消息时就添加翻译键。用基础语言写好默认文本,并附上简短的上下文,例如出现位置和操作目的。像 checkout.pay_button 这样的键只有当翻译者知道它是动词(“Pay”)还是标签(“Payment”)时才有用。
实现 UI 时使用占位符并以默认语言作为回退。保持变量明确(如 {name} 或 {count}),避免把句子拼接在一起。这是破坏跨语言语法的最快方式之一。
将字符串发给翻译时,提供翻译者所需的信息以保证准确性:每个屏幕的截图(或文本变化时的短视频)、紧凑位置的字符限制(标签、选项卡标题、提示)、语气与术语说明,以及动态占位符及其含义清单。
翻译回传后,尽早合并并构建 Web 与原生版本。在最高风险的屏幕上做快速 UI 检查:登录、引导、结账与设置。检查截断文本、重叠元素、缺失键与错误的复数形式。
最后,发布并监控。跟踪缺失键、回退到默认语言的事件以及经常发生文本溢出的屏幕。
给翻译者他们需要的上下文
准确翻译始于第一个字被翻译之前。如果翻译者只看到键和英文短语,他们会猜测。那样会得到在错误位置使用正确词汇、或让界面显得怪异或不礼貌的翻译。
一个简单的“上下文包”能消除大多数猜测。对每个字符串说明出现位置(屏幕和组件)、用户的目的和语气(友好、正式、紧急)。还要标注它是按钮标签、错误信息、菜单项还是提示文本——这些类别的翻译方式不同。
当空间有限时提前说明。Web 与原生有不同的断点方式,所以在重要场景声明限制:短按钮标签、选项卡标题、Toast 提示以及任何在固定卡片内的文字。如果字符串必须单行显示,明确标注;如果允许换行,指出安全的换行点。
把“不要翻译”的部分明确标注。产品名、套餐名、优惠码、API 字段和像 {name} 这样的占位符必须保持不变。没有指导的话,翻译者可能会本地化它们,导致应用出现混乱。
每个字符串的实用包应包含:
- 截图或屏幕名称(例如:“Checkout - Payment method”)
- 类型与意图(确认支付的按钮)
- 语气说明(冷静、安抚)
- 约束(最多 18 个字符、单行)
- 受保护 token(产品名、集成名、
{amount})
将法律文本与支持内容视为独立流。法律文案通常有审批要求且更新慢,应与产品 UI 字符串分开管理并做版本控制。支持文章和帮助文稿通常是较长的翻译,可放在不同系统或文件集中。
示例:移动端的“Continue”按钮可能比 Web 需要更严格的长度限制。如果翻译者知道这一点,他们可以在扩展较多的语言中选择更短的动词,从而避免晚期重设计。
防止本地化破坏 UI 的 QA 与审查循环
本地化导致的 UI 断裂通常一开始看起来不像“Bug”。它们表现为缺失标签、按钮换成两行或占位符显示错值。良好的工作流包含能在用户看到之前发现这些问题的 QA 步骤。
在开发构建中先做伪本地化。用更长、有重音的版本替换真实字符串(例如 "[!!! Šéttïñĝš !!!]"),并将长度扩展 30–50%。这能快速暴露截断、重叠和硬编码字符串问题,适用于 Web 与原生。
在每次构建中加入自动检测。它们能捕捉人眼在审查大量行时容易错过的枯燥错误:
- 任意本地化语言中缺失的键(回退会掩盖问题直到更晚)
- 未使用的键(表明你在漂移并发布了死文本)
- 占位符不匹配("Hello, {name}" vs "Hello, {username}")
- 某个语言缺少复数表单(zero、one、few、many)
- 手机字符串中出现原始 HTML 等禁止模式
然后使用明确的人工签核流程。产品负责关键屏幕的含义与语气,QA 负责布局与交互检查。
保持测试矩阵小而严格。不必测试所有内容,只测试会首当其冲出问题的:登录/注册、找回密码、结账/支付确认、设置与个人资料编辑、通知与空状态、以及包含表格、徽章或小按钮的任何屏幕。
在报告问题时,让修复变得容易:提供语言、设备与系统版本(或浏览器与宽度)、期望文本、实际文本以及显示截断区域的截图。如果涉及复数或占位符,贴上确切的键与渲染后的字符串。
常见错误与避免方法
大多数本地化 bug 并不是“翻译问题”。它们是工作流问题,表现为断裂的 UI、缺失文本或令人困惑的信息。
一个常见陷阱是当你只想改文案时却重命名键。键应是稳定的 ID,而非文本本身。如果你把 checkout.button.pay 改成 checkout.button.pay_now,所有旧翻译就会变成“缺失”,历史记录也丢失。保持键不变,更新基础语言文本,并在含义变化时补充上下文。
另一个常见问题是某个平台硬编码字符串。Web 团队使用键,但移动端临时放了硬编码文本。一月后,iOS 上出现只有英文的警告。把“禁止在面向用户的界面中硬编码字符串”设为 Web 与原生共享的规则。
当你假设词序不变时,占位符会导致细微错误。英语可以用 "{count} items",但其他语言可能需要不同顺序或额外单词。使用命名占位符(不要用位置占位符),并在各平台保持一致。
值得早期捕捉的错误:
- 把键当文案来对待,从而破坏现有翻译。保持键稳定。
- 为两个不同含义重用一个键。含义不同就拆分键。
- 占位符风格混用(有的命名有的编号)。统一一种风格。
- 只测试英文。至少检查一种长文本语言与一种短文本语言。
- 无回退计划就发布。发布前约定缺失键应如何处理。
仅测试一个“长文本语言”并不足够。德语常常会膨胀,而中文可能隐藏间距问题。对两者做快速检查,并测试复数的边界情况如 0、1、2。
在发布前商定回退行为。例如:如果法语缺失,则回退到英文、记录缺失键,并仅在关键屏幕存在缺口时阻止发布。
快速检查表与实用后续步骤
当检查变得小而可重复时,本地化工作流就会健康运行。目标很直接:更少意外字符串、更少断裂布局、更少最后一刻的翻译抢修。
在合并 UI 变更前,快速核查常见的“哎呀”问题:
- 新键遵循命名规则并位于正确的命名空间(屏幕或功能)
- 占位符在各语言间精确匹配(相同变量,相同含义)
- 为支持语言准备完整的复数形式(不仅仅是英文的单复数)
- 界面中不再有硬编码文本(包括错误状态和空状态)
- 新增或变更的文本附带了基本上下文(截图或清晰注释)
在发布前,运行一轮短时的发布 QA,重点检查本地化最先出问题的地方。把它时间盒化但保持一致:在每个平台上检查顶级用户流程、一处 RTL 快速检查、长文本屏幕(设置、法律、引导、表格、窄按钮)以及几个语言的日期/数字/货币格式化。
设定与团队匹配的节奏。很多团队每周更新翻译,然后在发布前 1–2 天冻结字符串。要点是避免将最后一刻的文案改动与最终 QA 混在一起。
付出回报快的后续步骤:把你的约定(键命名、占位符、复数规则、所有权)写下来,然后端到端运行一个试点屏幕,根据出问题的地方调整流程。
如果你在单个平台上同时面向后端、Web UI 和原生移动(例如使用 AppMaster)构建,保持键与占位符一致更容易,因为相同的屏幕与逻辑能共享单一约定。保持该约定稳定会让本地化变得常规而非脆弱。
常见问题
从把字符串放在一个稳定的位置、统一键命名规则开始,并规定仅更改显示文本而不随意改键。然后建立一个小型 QA 流程,在发布前捕捉缺失键、溢出和复数形式问题。
选定一个在冲突时“最终胜出”的系统,例如代码仓库中的翻译文件或翻译平台的导出。明确大家只能通过该源编辑内容,代码仅消费它。
按职责而不是头衔划分:一人负责基础语言的含义与语气审批,一人负责键结构与下线管理,翻译人员只修改翻译值。这能避免静默改键和临时改文案导致的构建问题。
当含义变化时创建新键,即便英文看上去相似。含义相同则重用键,这有助于保持翻译一致并减少维护成本。
把键当作标识符而不是英文句子,包含功能范围(feature)、屏幕/流程、组件和用途。像 portal.checkout.button.pay 这样的键,即使按钮文案变了也依然有用。
复数问题常出在把语言只分为单数/复数上。为每个概念存一个键并支持适当的复数类别(按 CLDR),并把 {count} 放在完整句子里,便于翻译者按语序调整。
不要通过拼接片段(如 "Hello " + name)来构建句子,因为语序和词尾会随语言变化。统一使用命名占位符(例如 {user_name}),并记录每个占位符的含义。
假设文本会膨胀 30–50%,并设计可换行或可扩展的组件。然后在 Web 和原生上测试一个“长文本”语言和无障碍字体大小,尽早捕捉截断与重叠问题。
在开发中使用伪本地化以暴露硬编码字符串和布局问题,并在构建时加入缺失键、未使用键、占位符不匹配和复数形式错误等自动检测。手动审查集中在最易出问题的流程上,如登录、结账和设置。
在发布前回退到基础语言,同时记录缺失键,便于快速修补而不阻塞所有发布。对于关键界面或法律文本,缺失或过期的翻译应阻止发布更为安全。


