翻译 JSX - 如何使用条件渲染
介绍
我在国际化实践中最常见到的错误之一,是倾向于 把本来很简单的三元表达式拆成多次翻译调用。 通常会是这样的:
const gt = useGT()
return (
<>
<span>
<T> 深色模式: </T>
</span>
<Button>{enabled ? gt('开启') : gt('关闭')}</Button>
</>
)在大多数情况下,这样“看起来”是按预期工作的。在实现 i18n 之前,代码大概是 { enabled ? 'On' : 'Off' } 这样的写法。
为 i18n 添加 gt() 函数,大概只是对现有代码结构的一种顺势扩展。
每次看到这种写法,我都会条件反射般地一阵不适。这完全不是这个库的设计用法。 之所以说这是一个错误,尤其是在使用机器翻译的场景下,有两个理由:(1)上下文,(2)灵活性。
上下文
含义不仅体现在词语本身,还体现在词语呈现的方式中。 单词 "back",如果出现在一个返回箭头上,含义很可能与出现在一份脊椎理疗师简历上的 "back" 完全不同。 另外,如果缺乏更大的上下文,即使是人工译者也可能很难正确翻译这个词。 有一个关于 WhatsApp 的 i18n 部门的著名故事:他们在图片编辑工具中把单词 "crop" 误翻成了德语中表示“农作物/耕作”的 "crop"。
为了解决这个上下文问题,我们可以通过 <T> 和 <Branch> 组件传递有关内容呈现方式的信息。
在我们的例子中,这会让我们的“译者”对 "on" 和 "off" 的含义有一个更完整的理解。
<T>
<span>深色模式:</span>
<Button>
<Branch branch={enabled.toString()} true="开启" false="关闭" />
</Button>
</T>灵活性
除了上下文之外,我们还可以利用 LLM 对代码的理解来实现更灵活的翻译。 来看一个示例:在不同语言下,组件的排列顺序可能会发生变化:
<T>
我在<Branch branch={atHome.toString()} true="家里" false="公司" />吃午饭。
</T>所以我们有两种可能的句子:
- "I eat lunch at home"
- "I eat lunch at work"
在中文里,我们会说:
- "我在家吃午餐"
- "我在公司吃午餐"
<T> 组件会识别这里需要改变语序,并相应地重新排列其子元素——这是仅使用结合字符串翻译的三元运算符很难做到的。
<T>
我在
<Branch branch={atHome.toString()} true="家" false="公司" />
吃午餐。
</T>结论
如果你只从这篇文章中带走一件事,那就是在编写代码时应始终思考如何更好地利用上下文和灵活性。
使用 <Branch /> 组件可能是实现这一点最简单的方法之一。
查看 <Branch /> 组件 文档了解更多详情。