返回

翻译 JSX - 如何使用条件渲染

Ernest McCarter avatarErnest McCarter
gt-nextBranchternaryconditionaltranslationi18nTranslate 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 /> 组件 文档了解更多详情。