返回

gt-next@6.8.0

Ernest McCarter avatarErnest McCarter
gt-reactgt-nextgtx-cliv6.8.0statictranslationi18n

概述

我们经常会发现,代码库越成熟,内容往往越零散。 句子会分散在函数、工具、逻辑和服务的各处。

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(toy, gender) { 
  return toy === "ball" ? "ball" : getSubject(gender)
}

function Component({ gender, toy }) {
  return (
    <>
      <p>
        The beautiful {getSubject(gender)} plays with the {getObject(toy, gender)}.
      </p>
    </>
  )
}

当国际化终究提上日程时,开发者往往会发现自己已经把自己逼进了死角。 如果不做大规模重构,就无法在多个文件之间妥善处理一致性、词形变化和语序变化等问题。 传统上,这意味着必须手动提取每个句子的所有可能表达形式,并将它们加入翻译词典。

gt-next 6.8.0 中,我们进一步强化了这样一种理念:优秀的 i18n 库应该去适配代码库,而不是反过来。 虽然 gt-next 已经支持内联翻译内容,但它仍缺少这类库的两个核心能力: (1) 支持句子碎片化,以及 (2) 内容可复用,同时还能保留一致性、词形变化或语序变化。

我们引入了 <Static> 组件,使你可以直接在翻译中使用静态函数调用。

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(type, gender) { 
  return type === "ball" ? "ball" : getSubject(gender)
}

function Component({ gender, toy }) {
  return (
    <T>
      <p>
        The beautiful <Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy, gender)}</Static>.
      </p>
    </T>
  )
}

重要注意事项

话虽如此,我们仍强烈建议谨慎、适度地使用 <Static> 组件。 <Static> 组件虽然功能强大,但也可能导致翻译条目数量显著增加。 如果使用不当,可能会对应用的加载时间产生负面影响。

如何使用 <Static>

<T><Var> 组件一样,<Static> 组件也是一种标记,用来告诉 CLI 工具哪些位置需要查找可翻译内容,哪些位置不需要查找。 它会指示 CLI 工具对 <Static> 标签内的函数调用进行解引用,并收集该函数可能返回的所有内容。 将每条 return 语句都视为外层包裹了一个 <T> 组件。

当 CLI 工具找出某个函数调用的所有可能输出后,它会为每种可能的输出分别创建一条翻译条目。 例如,下面的代码会创建两条独立的翻译条目:"这个男孩很漂亮" 和 "这个女孩很漂亮"。 由于每种可能的输出都有各自独立的翻译条目,我们就可以在片段化句子中支持一致性、词形变化和语序调整:"El niño es hermoso" 和 "La niña es hermosa"。

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function Component({ gender }) {
  return (
    <T>
      The <Static>{getSubject(gender)}</Static> is beautiful.
    </T>
  )
}

局限性与后续改进

乘法效应

如前所述,<Static> 组件如果使用过多,可能会生成大量翻译条目,从而对加载时间产生不利的性能影响。 例如,假设某个组件中有两个 <Static> 组件,每个组件都包装了一个有两种可能结果的函数调用。 在这种情况下,会创建四个翻译条目。 每额外增加一个 <Static> 组件,翻译数量都会按每个函数调用的可能结果数成倍增长。

function getSubject(gender) { 
  return gender === "male" ? "boy" : "girl" 
}
function getObject(toy) { 
  return toy === "ball" ? "ball" : "crayon"
}
function Component({ gender, toy }) {
  return (
    <T>
      <Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy)}</Static>.
    </T>
  )
}

语法

请务必将每个 return 语句都视为由 <T> 组件包裹。 任何动态变量或函数调用仍必须包裹在 <Var> 组件中。

目前,<Static> 仅支持以函数调用作为子元素,但未来将支持更复杂的表达式。 从 gt-next 6.8.0 起,支持以下静态函数语法:

function getExamples(key) {
  switch (key) {
    case "string, number, and boolean literals":
      if (condition1) {
        return "The boy"
      } else if (condition2) {
        return 22
      } else {
        return true
      }
    case "jsx expressions":
      return (
        <>
          Hello, <Static>{getTitle(title)}</Static>. How are you, <Var>{name}</Var>?
        </>
      );
    case "ternary operators":
      return condition ? "The boy" : "The girl"      
    case "function calls":
      return otherStaticFunction();
  }
}

结论

gt-next 6.8.0 引入了 <Static> 组件,用于在不牺牲翻译覆盖率或一致性的前提下,解决句子碎片化问题。