翻译 JSX:如何使用条件语句
简介
我在国际化实践中最常见到的错误之一,就是总想把简单的三元表达式拆成多次翻译调用。 通常会写成这样:
const gt = useGT()
return (
<>
<span>
<T> Dark Mode: </T>
</span>
<Button>{enabled ? gt('On') : gt('Off')}</Button>
</>
)大多数情况下,这样确实能按预期工作。在引入 i18n 之前,代码看起来很可能是这样的:{ enabled ? 'On' : 'Off' }。
为了支持 i18n 再加上 gt() 函数,大概也只是顺着现有代码结构自然扩展了一步。
但我每次看到这种写法,都会生理性地感到一阵难受。这完全不是这个库原本的设计用法。 为什么说这是个错误?有两个原因,尤其是在使用机器翻译时:(1) 上下文,以及 (2) 灵活性。
上下文
含义不仅存在于词语本身,也体现在词语的呈现方式上。 比如,单词 "back" 如果出现在返回箭头上,含义很可能和出现在脊椎按摩师简历上的 "back" 完全不同。 此外,如果缺少更大的上下文,译者 (即使是人工译者) 也可能难以正确翻译这个词。 有一个著名的例子:WhatsApp 的 i18n 团队曾把图片编辑工具里的 "crop",在德语中误译成农业语境里的 "crop"。
为了解决这个上下文问题,我们可以通过 <T> 和 <Branch> 组件传递有关内容呈现方式的信息。
在我们的示例中,这能让“译者”更准确地理解 "on" 和 "off" 的含义。
<T>
<span>Dark Mode:</span>
<Button>
<Branch branch={enabled.toString()} true="On" false="Off" />
</Button>
</T>灵活性
除了 上下文 之外,我们还能以另一种巧妙的方式利用 LLM 翻译:借助它对代码的理解。 来看一个例子:组件的顺序可能会因语言不同而变化:
<T>
I eat lunch at <Branch branch={atHome.toString()} true="home" false="work" />.
</T>所以我们有两个可能的句子:
- "我在家里吃午饭"
- "我在公司吃午饭"
在普通话里,我们会说:
- "我在家吃午餐"
- "我在公司吃午餐"
<T> 组件能识别这里需要调整语序,并相应地重新排列其子元素——而这一点用带字符串翻译的三元运算符很难实现。
<T>
我在
<Branch branch={atHome.toString()} true="家" false="公司" />
吃午餐。
</T>结论
如果你从这篇文章里只记住一件事,那就是要始终留意如何在代码中利用上下文和灵活性。
而使用 <Branch /> 组件,很可能就是实现这一点最简单的方法之一。
更多详情请参阅 <Branch /> 组件 文档。