1. 项目概述与核心思路1.1 本地化UI元素到底是什么先说个场景。我早年做的一个工具类App一开始只上架国内市场界面全是中文一切正常。后来想试试海外市场就面临着把整个界面翻译成英文的活儿。当时年轻想着“翻译还不简单把中文文案替换成英文字符串不就行了”。结果真做起来才发现本地化UI元素这件事远不是“翻译”两个字能概括的。项目标题里的“Localize UI Elements”翻译过来就是“本地化用户界面元素”。它指的是一整套让界面能够适配不同语言、地区、文化习惯的工程手段。UI元素并不只是你屏幕上看到的那些按钮文字、提示语、菜单项它还包含日期格式、数字格式、货币符号、排序规则、文本方向、图标含义、甚至快捷键配置。任何一个环节没有做好用户在使用时就会觉得“这产品不像是为我们这里做的”。这也就是标题编号本身值得注意的地方。0.03.02.04.08这种缩进层级通常出现在企业内部国际化规范文档里它把一个庞大的“全球化Globalization”工程拆成了多个层级母项是本地化工程子项是内容本地化再往下拆到用户界面元素这一层。这种拆法本身就说明了一件事本地化UI元素是一个有边界、有结构、有先后顺序的工作而不是能靠一把梭“翻译完事”的杂活。我们这篇文章就聚焦在这一层级上界面上那些可以被用户直接看到、感知到的元素如何做本地化。1.2 为什么单独把“UI元素”拎出来讲很多人会问我做国际化的时候把文案抽出来放到strings文件里然后翻译不就是在做UI本地化了吗对但只做对了一半。UI元素和其他内容比如文章正文、商品详情最大的区别在于UI元素的空间是有限的、位置是固定的、交互是强绑定的。按钮就那么大弹出框就那么大你翻译出来的英文可能是中文长度的两倍直接撑破布局德语的一个复合词可能长到让tab栏溢出屏幕阿拉伯语是从右往左排版的你所有靠左对齐的图标和文本结构都要映射翻转。这些都是“用户界面元素”特有的问题。文章正文长了可以滚动详情页长了可以分页但导航栏标题、表单label、错误提示、按钮文字、Toast文案它们没有“变长”的余地。UI元素本地化的核心矛盾就是在多语言环境下如何让这些固定空间里的元素依然准确、完整、美观地呈现。此外UI元素还承担着“引导操作”的功能。一个“确认删除”的按钮在日语里如果用了过于礼貌的措辞用户可能不敢点在德语里如果用了过于直接的命令式又显得生硬。界面文案的语用效果直接影响用户对产品的信任感和操作意愿这还不是翻译公司能帮你解决的它需要产品和技术一起配合。1.3 这篇博文适合谁看如果你手头有以下任何一种情况这篇文章应该能帮到你你正在做一个准备出海的App或网站需要支持中英双语起步你的产品已经接到了海外用户反馈收到的差评里出现了乱码、日期看不懂、文字被截断这类问题你是独立开发者想提前把架构设计好不想以后为了多语言重构代码你是产品经理或测试需要对本地化质量做验收但不知道从哪些维度把关。这篇文章会从方案选型讲起一步步拆解字符串资源怎么组织、参数和复数怎么处理、RTL布局怎么适配、测试要测什么最后再分享一些我踩过的坑。整体走实操路线按着做基本不会跑偏。2. 整体设计本地化工程的结构化拆解2.1 国际化i18n和本地化l10n必须先分清不想清楚这件事后面的工作都会乱。国际化和本地化是两个不同层次的工作但很多人把它们混成一谈导致架构设计时漏掉了重要环节。国际化Internationalization缩写i18n是在代码和架构层面做的准备工作。它的核心目标是让产品具备支持多语言、多地区的能力。在代码层面这意味着你不能把任何用户可见的字符串硬编码在代码里日期、数字、货币的格式不能写死布局要能适应不同的文本长度和排版方向。一句话总结国际化是“把产品和特定语言解耦”。本地化Localization缩写l10n则是在国际化完成的基础上为某一个特定的语言和地区提供适配内容。翻译文案只是本地化的一部分它还包括调整日期格式、适配本地合规要求、选择符合当地审美的图标、甚至调整配色方案。从这个项目标题来看“Localize UI Elements”属于本地化层级的任务但它的前提是国际化已经做完了。你不可能在一个所有文案都硬编码在代码里的项目里直接跳到“本地化UI元素”这一步。所以在实际落地的过程中第一步永远是回头检查你的代码架构是否已经支持外部化的字符串、参数化格式、动态布局。2.2 典型的资源文件组织方式在实际项目中界面元素的本地化通常依赖平台提供的资源文件机制。以移动端和Web为例iOS这边最常见的做法是使用.strings文件每个语言一个文件比如Localizable.strings英文、Localizable.strings中文在Swift开发中也可以用.xcstrings统一管理Xcode 15之后对多语言的支持更完善了可以在一个可视化的编辑器里管理key和多种语言的译文。Android则是把字符串放在res/values/strings.xml里默认语言放在values目录其他语言放在对应的values-目录下比如中文是values-zh、日文是values-ja。系统会根据设备的语言设置自动选择对应的资源目录。Web前端的选择更多样。轻量级的可以用i18next搭配react-i18next或vue-i18n把文案放在JSON文件里需要工程化管理的也可以用FormatJS这类基于ICU MessageFormat的方案它天然支持复杂的复数规则和日期格式化。无论用哪种方案有一条原则是通用的绝对不要在代码里直接写“你好”或者“Hello”这样的字面量而是要用一个key来引用。比如home.greeting然后在资源文件里映射到对应语言的文案。这样做的好处是key是稳定的即使某一种语言的文案改了也不需要动代码而且key本身可以作为一种语义化的注释帮助翻译人员理解上下文。2.3 我把方案选型的思路理一下如果你还在技术选型阶段我给一个比较务实的建议小团队优先用平台原生方案别一上来就上重型框架。什么算重型框架就是那种需要搭建翻译管理平台、自动化流水线、多语言包构建系统的大型方案。对于只有两三种语言的产品来说这些基础设施带来的维护成本可能比翻译本身还高。原生方案iOS的strings Android的strings.xml Web的i18next已经能覆盖90%的需求而且上手快、出问题好排查。当然如果你的产品已经有十几个语言版本翻译团队多人协作文案量上万条那就值得引入专业的翻译管理平台比如Crowdin、Lokalise这类工具把翻译流程从“改代码提交”变成“翻译平台协作”产品人员和翻译人员在同一个平台上工作代码层面只负责拉取最新的语言包。我在实际项目里见过的最常见踩坑不是选错了框架而是选框架之前没想清楚“翻译由谁来维护”。如果你的翻译工作流是“开发自己翻译”那用什么框架都行简单就好如果是“有专职翻译但不会写代码”那你必须选一个能提供可视化编辑界面的方案否则翻译人员天天改JSON文件迟早会出格式错乱的问题。2.4 界面元素本地化的完整要素拆解在动手之前先建一张表把UI元素本地化的所有要素过一遍。这张表我每次做新项目都会贴到墙上当作验收清单用。元素类别本地化内容示例文本类按钮、标签、菜单、弹窗、Toast、表单校验提示“确认”、“Cancel”、“保存中…”格式类日期时间、数字、货币、百分数、排序规则01/02/2024还是2024-02-01还是1. Februar 2024方向类文本对齐、图标布局、阅读顺序阿拉伯语下的从右到左RTL适配内容类图片中的文字、音视频字幕、帮助文档截图里的中文界面需要重拍或处理交互类快捷键、手势、语音指令不同语言环境下键盘快捷键冲突问题合规类隐私条款、Cookie提示、年龄确认GDPR、CCPA等合规要求的本地化很多项目第一次做国际化时只盯着第一行“文本类”结果到了测试阶段才发现日期格式还是中文习惯、阿拉伯语用户看到的界面布局完全颠倒、截图素材里的中文没处理。这张表的价值在于它可以让你在规划阶段就把所有类别纳入范围而不是上线后被打补丁。3. 核心细节解析与实操要点3.1 字符串资源key的命名规范与组织——一个贯穿全文的示例key命名这件事表面上看起来只是风格问题但在大型项目中key的混乱程度直接决定你后续维护时想不想摔键盘。我见过几种典型的坏味道。第一种是把key直接命名为英文文案比如hello_world : 你好世界翻译成英文时value也是“Hello world”。这种方式在只有两种语言时问题还不大但一旦加入第三种语言你发现key本身变成了英文文案就无法做到“key与语言无关”将来要改英文措辞时key也得跟着变所有引用它的代码都要动。第二种是key没有层级和分组翻译文件几千行铺开搜索一个key要靠肉眼扫新增一条要担心是不是跟已有的重复。比较推荐的做法是把key当作代码变量来管理遵循“模块名.页面名.元素名”的分层结构。还是用前面那个工具App来举例假设我们要给设置页面里的“清除缓存”按钮加文案key可以命名为settings.data_management.clear_cache。这样翻译文件里按字母序排列后同一个页面的文案自然聚在一起查找和维护都方便。给翻译人员看的时候上下文也更清晰他们能从key的命名推断出这条文案出现在哪个位置、是什么用途。字符串资源组织上还有一个要注意的点不要把整句文案拼在一个key里。举个例子“你有3条新消息”这句话不要写成一个key为notification.message、value为“你有{count}条新消息”的字符串而是要把“条新消息”这种可复用的片段拆出来单独一个key再把数量部分作为参数传入。这样不同语言的语序差异才能被正确处理。中文说“你有3条新消息”日语说“新しいメッセージが3件あります”主语和数量的位置完全不一样参数化的方式能最大程度保留翻译的灵活性。3.2 占位符与格式化为什么“{count}”比“%”好用在iOS的.strings文件里字符串格式常见的是notification.message You have % new messages.;。这个%是Object-C时代遗留的格式符对应一个对象参数。在Swift里String(format:)依然支持这套。但Web和跨平台生态里现在更主流的是ICU MessageFormat其中最典型的语法就是{count}这种花括号占位符。比如notification_message: You have {count} new messages.然后通过格式化函数传入{count: 3}运行时就会替换成实际的数字。为什么我强烈建议用{count}而不是%d、%这种C风格占位符有三个原因第一可读性强。翻译人员看到一个{count}能直观理解这里会填入一个数字但看到%、%1$d这种符号非程序员完全不知道是什么极容易在翻译时误删或误改。第二支持命名参数。{count}和{name}是语义化的名字而不是位置序号。这在翻译成某些语序完全不同的语言时特别重要——英文的“You have {count} new messages”到了阿拉伯语里可能是“لديك {count} رسائل جديدة”参数的灵活移动不会出错但只要用的C风格的位置参数翻译人员一旦调整位置就可能导致格式化崩溃。第三能配合复数规则一起用。这一点我们下一篇详细讲但核心原因是{count}这种命名占位符天然适合交给ICU的复数选择器去处理。3.3 复数规则不只是“单数/复数”那么简单这是本地化UI元素里最容易被低估的一个环节。中文没有复数变化所以很多中国开发者在写代码时根本不会考虑“数量不同时文案是否需要变化”的问题。但只要你出海复数规则就一定会撞到你。英语里的复数规则还比较简单1个是单数0和大于1是复数。但俄语有四种复数形式、波兰语有五种、阿拉伯语有六种。举个例子阿拉伯语里数字1、2、3到10、11以上、0每一种对应的名词形式都不一样。好在大多数国际化框架已经内置了这些规则的实现比如ICU MessageFormat里的plural选择器。你的核心工作不是在代码里手动实现这些规则而是把文案按“选择器”的方式组织起来让框架去匹配当前语言的复数规则。实操上文案应该写成这样message_count: {count, plural, 0 {No new messages} 1 {You have one new message} other {You have # new messages}}这里other是兜底分支不同语言下框架会自动选择对应的分支逻辑。你不需要为每一种语言写不同的格式模板只需要提供“零、一、其他”这几个在多数语言里都有的分类ICU框架会把other映射到该语言所需的更多子规则上。这里有一个非常常见的坑很多人会把“0”“1”写死在英文模板里然后自以为所有语言都适用。实际上阿拉伯语里“一个”和“两个”用的都是不同且具体的变格不是简单“1”能覆盖的。更稳妥的策略是先用ICU的plural语法来表达所有语言共有的“零、一、多、其他”等类别具体分支的解析交给框架翻译人员只需要在CAT工具里看到语境并给出对应的译文即可。3.4 日期、数字、货币的格式化你在界面上看到的所有“数字类”元素文本之外UI元素里最容易出错的就是各种格式化的数字。先看日期。中英文环境下日期格式有本质差异中文习惯“年-月-日”美国习惯“月/日/年”欧洲很多国家用“日.月.年”或“日/月/年”。如果你在代码里写死YYYY-MM-DD美国用户会困惑欧洲用户会困惑。正确的做法是永远不要自己拼日期字符串而是用平台提供的DateFormatter或者国际化框架的日期格式化功能。在iOS里要给DateFormatter设置locale属性然后用.dateStyle和.timeStyle枚举在Web里用Intl.DateTimeFormat。这里有一个很多开发者在测试时才会发现的坑不要用DateFormatter默认的行为就完事了。不同地区的周起始日不同有的周日是一周的第一天有的周一。你写一个日历视图时第一列是周日还是周一取决于用户的地区而不是你的主观偏好。数字也一样。英文的千分位分隔符是逗号1,000,000德语里是句点1.000.000中文是逗号但标准不太一样。如果你在文案里用{count}直接拼接数字用户看到的一定是未格式化的一长串。规范的方案是给数字格式化指定locale让系统决定怎么加分隔符。货币更是重灾区。人民币符号显示为“¥”美元是“$”欧元是“€”。但符号放前面还是放后面不同语言也不同英文通常写“$100”中文写“100元”法文写“100 €”。所以处理金额时同样要把货币格式交给NumberFormatter或Intl.NumberFormat而不是程序里写死“$ 数字”。3.5 RTL从右到左适配阿拉伯语和希伯来语用户怎么看你的界面这一块是UI元素本地化和内容本地化差异最大的地方。阿拉伯语、希伯来语、波斯语这类从右向左书写的语言用户的使用习惯跟我们是镜像的。拿home页举例子中文用户从左往右扫视导航栏左上角是返回按钮、右上角是菜单按钮阿拉伯语用户则相反返回按钮在右上角菜单按钮在左上角文字也从右往左排列。在iOS上系统级的semanticContentAttribute提供了.forceLeftToRight和.forceRightToLeft控制UILayoutGuide也内置了RTL支持。只要你不手动指定leading和trailing时用绝对的left和right大部分约束可以自动镜像。在Android上官方推荐用android:layoutDirectionrtl配合start和end属性的约束来实现镜像。Web端则需要使用CSS的dir属性、逻辑属性margin-inline-start、padding-inline-end这些来适配。实际操作中最大的坑不在于“原理不知道”而在于测试不足。很多产品出海时只准备了中英双语阿拉伯语这个方向的适配直到最后一刻才想起来结果发现整个UI需要镜像翻转图标方向、文本对齐、图片的视觉引导方向全都要调整工作量等于一次小型的界面重构。我的建议是如果你的目标市场包含中东地区或者你希望产品在架构上保持多方向适配的能力从第一天设计UI时就用逻辑属性leading/trailing、start/end而不是物理属性left/right。这不算什么高级技巧只是在写第一行布局代码时就多想一步而已。3.6 图标与图片的本地化比文字更隐蔽的UI元素UI元素里还有一类经常被忽略图片和图标里的“文字”。一个典型的失误是在App引导页里放了一张截图截图里是中文界面。你做了多语言支持后这张图片不会变于是英文用户看到的引导页里出现了一张满是中文的截图违和感瞬间拉满。解决方案有三种层次。最简单粗暴的是在图片资源上做语言区分比如onboarding_zh.png和onboarding_en.png在资源加载时根据当前语言选择。更优雅的方案是用矢量图和图标字体替代位图文字部分用真正的文本元素叠加在图片上这样文本可以随语言切换。图标本身也有文化差异。举个我亲自踩过的例子我们给一个任务管理App设计了一个“垃圾箱”图标表示删除操作。这个图标在大部分市场都没问题但在某些地区用户可能对它感到陌生甚至反感。另一个常见例子是“手电筒”图标中文用户很熟悉“一个手电筒”代表打开手电功能但某些地区的用户可能根本不认识这个形状。做本地化的专业流程里针对目标市场做图标可用性测试不是可选项而是必选项。4. 实操过程从代码到交付的完整流程4.1 实施前检查清单在写任何代码之前先把这几件事确认清楚代码中是否还有硬编码的字符串全局搜索中文、英文等字母确保没有任何用户可见文本直接写在代码里。日期、数字、货币格式化是否全部走了框架方法有没有自己拼接字符串的情况布局约束是否已经使用逻辑属性在同一方向上有没有混用物理属性资源文件是否已经按目录或命名空间分好类翻译工作流是否确定工具、责任人、频次这个清单看起来基础但能帮你避免“做到一半推倒重来”的尴尬。我在给一些团队做代码评审时经常看到他们声称“做了国际化”但一搜代码硬编码的字符串还是能从犄角旮旯里翻出来。最隐蔽的地方是拼接消息的代码比如订单号 order.id这样的代码很容易漏网。4.2 具体操作步骤演示下面用一个简化版的“消息列表页”来做实操演示。这套流程在iOS、Android、Web上通用性都很强区别只在于具体API。第一步提取文案建立key清单。先扫描所有用户可见文案给它们配上语义化的key。我建议直接用表格维护列包含key、默认语言译文、后续语言译文、出现位置、备注。key中文英文备注message_list.title消息Messages导航栏标题message_list.empty暂无消息No messages yet空状态提示message_list.accept接受Accept消息操作按钮message_list.decline拒绝Decline消息操作按钮message_list.delete删除Delete上下文菜单第二步在代码中用key替换文案。iOS示例SwiftnavigationItem.title NSLocalizedString(message_list.title, comment: Messages list screen title) emptyLabel.text NSLocalizedString(message_list.empty, comment: Empty state message)Android示例KotlinsupportActionBar?.title getString(R.string.message_list_title) emptyLabel.text getString(R.string.message_list_empty)Web示例React i18nextconst { t } useTranslation(); return h1{t(message_list.title)}/h1;注意给每条key加上context注释比如iOS的comment参数这对翻译人员的帮助很大因为他们无法直接看到界面。第三步创建语言资源文件。英文的Localizable.stringsmessage_list.title Messages; message_list.empty No messages yet; message_list.accept Accept; message_list.decline Decline;中文的Localizable.strings在zh-Hans.lproj目录下message_list.title 消息; message_list.empty 暂无消息; message_list.accept 接受; message_list.decline 拒绝;Android的strings.xml同理在values-en和values-zh目录下分别建文件。第四步处理格式化与复数。把消息列表里可能出现的“你有3条新消息”改成参数化形式message_list.new_count {count, plural, 0 {You have no new messages} 1 {You have one new message} other {You have # new messages}};在代码里传参数let count 3 let message String.localizedStringWithFormat( NSLocalizedString(message_list.new_count, comment: ), count )Web / i18nextt(message_list.new_count, { count: 3 })第五步做RTL方向和布局适配检查。用iOS的semanticContentAttribute和UILayoutGuide检查约束Android用android:supportsRtltrue和start/end约束Web用CSS逻辑属性。这一步不需要写新代码但如果前面布局写死过left/right这里就要逐个修改。第六步把文案交给翻译。如果是自有翻译直接维护资源文件即可如果外包记得把key清单、上下文注释、界面截图一并交付。翻译质量的高低很大程度取决于你提供的信息是否足够充分。4.3 一个真实的踩坑记录之前做一个电商App的国际化时我犯过一个印象深刻的错误。当时要把结算页的“总计¥1,234.56”做国际化我以为只要把¥符号替换成对应货币符号就行所以写了个这样的逻辑根据货币代码在前面加符号或后面加符号。结果上线后德国用户反馈价格显示不对仔细查才发现德语环境下的欧元格式是“1.234,56 €”千分位是句点、小数位是逗号、符号在数字后面。我自己拼的格式完全错位了。后来改成用NumberFormatter设置好locale和currencyCode系统自动处理好了一切格式细节。这个坑给到我的教训是格式类的内容永远不要自己拼接永远把格式决定权交给系统或者框架因为你自己无法穷尽所有地区的显示规范。4.4 测试策略本地化的验收标准本地化测试我把它分成三个层次第一层是功能测试。切换语言后所有页面能正常打开没有崩溃、乱码、溢出按钮可点击表单可提交日期选择器可以正常使用。第二层是视觉测试。检查文本截断、按钮过宽、图标错位、长文本换行是否正常。这里的经验值是英文文案通常比中文长30%到50%德文可能长一倍所以UI设计时要预留足够的空间。第三层是文化测试。检查日期、数字、货币格式是否符当地习惯检查是否存在冒犯性图标或含义不当的文案检查RTL语言下布局是否镜像正确检查文案的语气和称呼是否适应该地区文化日语里的敬语差异、法语的“你/您”区分等。这个文化测试层面很多人觉得玄学但实际影响很大。我记得有个做健身App的朋友把“keep going”的激励语直接硬翻成中文“保持前进”用户反馈感觉像机器人说话。后来他们重写了中文文案改成“别停”效果立刻不一样。界面文案不是翻译是重写。5. 常见问题与排查技巧5.1 问题速查表现象可能原因排查思路与解决方案切语言后部分文案没变有硬编码字符串没抽出来全文搜索“中文”检查是否还有字面量用伪本地化测试来强制暴露未处理的字符串按钮文字被截断文案长度超出控件宽度给label换行、设置最小宽度、调整padding更根本的方式是用Auto Layout或Flex布局自适应宽度日期格式不对代码里手动拼了日期字符串改用框架的日期格式化功能确认locale传对了不要用系统默认而要用用户当前语言数字显示为“1,000.00”但当地是“1.000,00”没有做数字本地化使用NumberFormatter或Intl.NumberFormat并把locale设为用户当前语言RTL语言下布局错乱布局用了left/right而非leading/trailing全面替换逻辑属性检查scroll view的contentInset是否也需要镜像复数翻译错误直接用if/else写死了英文的复数规则改用ICU MessageFormat的plural选择器不自己实现规则翻译人员误删占位符导致崩溃占位符格式可读性差用{name}命名占位符在翻译平台中加校验规则禁止删除或修改占位符同一文案在两个页面含义不同一个key被多处复用导致歧义拆分key在不同位置使用不同key保证翻译语境清晰图片里的中文没处理位图资源没有按语言区分矢量图加文本叠加或按语言拆分图片资源某地区货币符号位置不对代码里手动拼接了货币符号用货币格式化API处理让系统决定符号位置和格式5.2 伪本地化一个被低估的排查利器伪本地化Pseudo-localization是很多大型国际化团队标配、但中小团队很少用的技术。它的原理很简单在开发阶段把源语言的所有字符串通过一种特殊规则“翻译”成一种看起来像外星语言的伪语言然后运行App。伪本地化的设计有几个目的。它会刻意把文本长度膨胀30%到50%把每个字符替换成带重音符号的字符比如a变成ä或å这样一来所有潜在的截断问题、硬编码字符串问题、字符编码问题都会在开发阶段被暴露出来。你不需要等真实的多语言包交付就能提前发现整体适配情况。有些框架已经内置了伪本地化支持。Android的Pseudolocales选项可以直接在开发者选项里启用iOS在Xcode的Scheme设置里也可以配置。Web端可以自己写一个简单的i18n拦截函数把所有返回的字符串做字符替换和长度扩展。我第一次用伪本地化测试时几乎是立刻就发现了3处硬编码中文和2处布局溢出问题效果立竿见影。现在我建议每个做国际化的团队在开发阶段就把伪本地化跑起来。5.3 排查工具链推荐除了伪本地化之外还有几个工具在实际排查中帮了大忙Transifex / Crowdin / Lokalise这三家的“翻译记忆”和“术语表”功能很好用。同一个词汇在项目里从头到尾保持一致靠人工很难但平台可以自动提示术语一致性。Languagetool用于检查译文语法问题的开源工具虽然不能完全替代人工审校但对粗心错误很有帮助。Screenshot testing截图比对测试给每个语言版本跑一套自动化截图然后做像素级对比。文本长度异常、布局溢出这类问题在截图对比中一目了然。工具不在多核心是让“人工检查”尽量被自动化替代。本地化测试如果全靠人工点、人工截图、人工比对基本做不完。我的经验是自动化截图对比至少能覆盖70%的视觉回归问题剩下30%的文化适配问题再靠人眼去检查。5.4 上线后的人工巡检清单产品上线后本地化工作并没有结束。我建议在每次发版前由懂当地语言的人做一轮人工巡检重点检查新功能的所有页面文案是否完整翻译系统弹窗、推送通知、邮件模板中的文案是否与App内保持一致强制更新的文案和跳转逻辑在不同语言下是否顺畅App Store或Google Play的商店截图、标题、描述是否也做了本地化。这最后一条很多人忽略。用户最先看到的不是App内部而是应用商店页面。商店页面的本地化质量直接影响下载转化率而很多团队的商店本地化是滞后于App本地化的导致用户下载后感觉“货不对板”。6. 一些更远的话题和我的真实体会界面元素的本地化做到一定程度后你会意识到它本质上不是“翻译”问题而是“产品心智”问题。我记得做那个工具App时中文版本的文案是我们自己写的语气比较正式。后来做英文版外包翻译社给了很地道的直译但读起来特别商业。我们又找了一个英文母语的产品顾问他把所有文案按“面向个人用户、工具属性、轻量级”的方向重写了一遍。改完之后用户留存和好评率都有明显提升。所以我的建议是如果你真的要认真做出海产品不要把本地化当成“发翻译公司做完了事”的工序。最理想的做法是在目标市场找一个懂产品、懂文化的母语者来“重写”文案而不是“翻译”文案。重写的字数和结构未必跟源语言一致但语用效果和用户感受是最贴合的。从技术架构上说这也意味着你的本地化体系要支持这种“重写”——文案长度可能完全不同需要适配长文本文案的重点信息位置可能不一样需要支持不同的语序按钮的文案措辞可能需要完全替换而不仅仅是逐词翻译。一个设计良好的本地化架构应该让这一切发生得自然而不需要返工。界面元素的本地化做得好是润物无声的用户觉得这个产品“本来就是为我的语言和文化设计的”。做得不好用户能感觉到“这东西是别人硬翻过来的”。差别在于你是否愿意把本地化当作产品体验的一部分来认真对待而不是发布前的最后一道杂务。如果这篇文章能帮你少踩几个坑、少走几步弯路那我觉得写这些字就值了。最后还是那句话项目编号再复杂落到界面上就是那一句文案、一个按钮、一个日期格式把它们一件件做对产品的全球化之路就会走得更稳。