一个新发布的 Cache-Control 分析器在英文版本中显示了日语文本——其状态显示为“新鮮”而非“Fresh”。这个错误可以追溯到共享逻辑,该逻辑返回了硬编码的日语字符串,而页面仅提供了英文标签。
该开发者构建了一系列轻量级浏览器工具,每个工具都有英文页面和日语页面,并复用相同的解析函数和核心逻辑。只有可见的措辞应该有所不同。当 Cache-Control 分析器发布时,英文界面显示了正确的标签,但它渲染的值来自于逻辑层,而逻辑层中仍然包含日语字面量。控制台没有出现任何错误;页面看起来很正常,但向英语用户展示的信息却是错误的。
为什么共享逻辑会背叛翻译
这个 bug 源于一个设计选择:决定显示内容的内核函数返回了日语的字符串字面量。负责周围英文文本的页面层从未有机会替换这些值。由于逻辑层和 UI 层被清晰地分离,问题在测试期间一直处于隐形状态——从技术角度看,一切都“正常工作”,尽管面向用户的语言是不正确的。
缺点在于,共享模块内部使用的语言会成为所有调用它的前端的默认语言。如果需要另一种语言,这个默认值就会变成一个隐藏的 bug。
修复方案:键、包与安全网
作者重写了架构以实现关注点分离:
- 消息包 (Message packs) 现在保存每种语言的所有可读字符串。
- 共享逻辑 仅返回标识符键 (symbolic keys),从不返回原始文本。
- 页面 根据键从相关的包中查找适当的词汇。
当消息必须包含数字时,新代码使用一个小函数而不是模板字符串。这让每种语言都能决定数字的位置,从而适应语序的差异。
还增加了一个简单的静态分析步骤:构建过程会扫描共享文件中的日语字符。如果出现任何日语字符,开发者会立即收到警报,从而防止硬编码的外语文本再次混入。
这次经历教会了作者什么
- 翻译起到了审查的作用。 在编写英文消息时,作者注意到某些日语对应词比较模糊。翻译过程迫使两种语言都使用了更清晰的措辞。
- 返回字符串的共享函数会为所有人锁定一种语言。 如果一个函数决定了语言,那么任何期望不同语言的调用者都会继承这个错误。这个 bug 不是 UI 上的小瑕疵,而是逻辑上的缺陷。
给维护多语言工具者的建议
- 从核心函数返回键,而不是字符串。 让 UI 层处理本地化。
- 或者将所需的字符串作为参数传递给函数。 这能让逻辑与语言无关。
- 审计共享模块中是否存在硬编码的原生语言文本。 快速搜索非 ASCII 字符可以发现隐藏的问题。
- 为共享代码中的外语字符添加构建时检查。 早期检测优于发布后的混乱。
下一步需要注意什么
总结: 如果你的项目在不同语言版本之间共享代码,请确保共享部分永远不要决定措辞。让每个页面提供自己的词汇,这样你就能避免英文页面意外说出日语的尴尬局面。
