...
Back

十五种语言不等于十五份翻译

翻字符串是所有人都会给预算的那部分。真正会坏的是字符串**周围**的一切 —— 元数据、兜底、以及那个顽固地留在英文的链接。

十五种语言不等于十五份翻译

十五种语言不等于十五份翻译 🌍

计划书上写着:抽出字符串、发出去翻、放回来、上线十五种语言。这计划没错,只是它描述的只是这件事的一小部分。真正吃掉时间的,是字符串周围那圈表面积 —— 那些在旁边一切都在变的时候,悄悄守着某个默认值的地方。

下面是我们反复发现的东西,大致按它让我们难堪的顺序排列。


词典不等于整个表面

一份翻译文件覆盖的是组件渲染出来的文本。它不覆盖:

  • 页面元数据。 <title> 和描述常常是在某个 layout 或 generateMetadata 里拼出来的,而没人把它当成 UI。一个完全翻译过的页面,仍然可能在浏览器标签、搜索结果、以及任何人分享出去的链接预览里,用英文自报家门。这是最常见的遗漏,因为页面看上去是对的。
  • 导航和页脚条目,如果它们定义在配置文件而不是组件里。配置是数据,数据不会被"禁止硬编码字符串"的 lint 规则抓到,于是一个导航标签能在所有语言里以未翻译状态待上几个月。
  • alt 文本和 aria 标签。 对视觉评审不可见,对读屏软件完全可见。
  • 错误态和空态。 评审时很少被渲染到,这正是它们能存活的原因。
  • 任何服务端生成的东西 —— 邮件、收据、通知文案。用户的语言必须从请求一路传到模板,而通常总有一跳传丢了。

规律很一致:一个东西被翻译的概率,正比于有人盯着它看的频率,而不是用户遇到它的频率。


缺 key 在开发时该很吵,在生产时该看不见

两种失败模式,修法相反。

如果缺 key 时应用渲染出原始 key 路径,你就把 nav.products.subtitle 发给了真实用户。如果它静默渲染成空,你就发出去一片空白,而且一两个版本里没人会注意到。

管用的做法是:生产环境回落到默认语言的字符串,开发环境让它尖叫。 用户拿到英文 —— 不完美,但是一句真话。开发者拿到一条控制台错误,或者更好:一个构建期检查,确认每种语言都有默认语言拥有的每一个 key。这个检查二十行代码,是你能写的投入产出比最高的一块 i18n 基础设施。


文本有尺寸,而尺寸会变

同一句话的德语版本通常比英语长 30%。中文和日文往往短得多但更高,而且断行规则不一样。韩语介于中间,有自己的间距行为。

你不需要一套排版理论,你只需要别再造那些假设英文长度的布局:

  • 别按标签的宽度定死按钮;按内容加内边距,让它自己长。
  • 别把两个固定宽度的列并排放,然后指望中间那点空隙。
  • 别在用户必须读完才能做决定的内容上用省略号截断。
  • 检查布局时看最长的那种语言,不是最短的。德语过得去,其他都过得去。

一句翻译可以合乎语法,同时是错的

花掉我们最多评审时间的那个,不是误译。是一句韩语,在一次文案改动之后,出现了两个连续的连接词尾 —— 语法上能解析,但读起来像有人把两个半句用订书机钉在了一起。修法是拆成两句,而这是任何术语表或术语一致性检查都不会提出的建议。

这是"翻字符串而不是翻意思"的结构性上限。当你改英文文案时,另一种语言里对应的改动有时候不是同一个改动。把两个从句连起来在一种语法里成立,在另一种语法里读着像结巴。

实际的防线不是加流程,而是:当文案改动改变了句子结构时,标记它去做一次母语通读,而不是逐 key 替换。 加一个限定从句恰好就是这类编辑,而它同时也恰好是那种"太小了,不好意思麻烦别人"的编辑。


下一次我们会先建什么

按投入产出排序:

  1. 构建期的 key 完整性检查,覆盖所有语言。用最少的代码抓住最多的真实缺陷。
  2. 第一天就做元数据本地化,包括 <title> 和所有 Open Graph 字段。事后补等于要动每一条路由。
  3. 一条"配置文件也要翻译"的规则 —— 或者更好:用户可见的字符串永远不要住在配置里。
  4. 把"用最长语言过一遍布局"并入任何 UI 改动,而不是单独排一轮。

这些都和翻译质量无关。它们说的是另一件事:"加一种语言"是应用的架构属性,而字符串从来都是容易的那部分。