返回

gt-react@10.12.0

Ernest McCarter avatarErnest McCarter
gt-reactgt-i18nv10.12.0tstring-translationbrowsersynchronousi18n

概述

gt-react 现在导出了一个 t() 函数,用于在浏览器中以同步方式进行模块级字符串翻译。

此前,在 gt-react 中翻译字符串需要使用基于 React 上下文的 Hook,例如 useGT。Hook 在组件内部效果很好,但无法覆盖一种常见场景:在模块级别翻译字符串——也就是在 React 组件之外、渲染前,或在普通工具文件中。

t() 正好填补了这一空白。它是一个同步函数,你可以在浏览器代码中的任何位置调用它:

import { t } from 'gt-react/browser';

const greeting = t('Hello, world!');

无需 Hooks、无需异步,也无需组件树。

为什么采用这种方式

这个 PR 的核心思路,是尝试脱离基于 React 上下文 的翻译方案。t() 在组件树之外运行,因此能支持一些更灵活的模式——尤其是模块级翻译。字符串可以在定义时就完成翻译,而不是等到渲染时再处理。

这也带来了一些权衡:

  • 仅限客户端。 t() 只适用于客户端 React 应用。它依赖浏览器执行模块,在应用渲染前加载翻译。
  • 切换语言需要整页重新加载。 由于翻译是在模块加载时解析的,切换区域设置需要重新执行这些模块——也就意味着必须整页刷新。无法在会话中途热切换语言。

不过,开发体验有了明显提升。无需用 hook 包装字符串,无需处理组件层面的样板代码,也没有异步边界——只需要一次函数调用。

现有的 React 上下文 方案 (useGT<T> 等) 不会消失。这只是为那些适合接受这些权衡的项目提供的一个额外选项。

工作原理

t() 会从预先加载的翻译中同步获取译文。这些翻译由 bootstrap() 注入;`bootstrap()`` 是一个新的异步初始化函数,会在应用渲染前加载当前区域设置的所有翻译。

你需要修改应用的入口点,先运行 bootstrap()。通常是 main.tsx,不过你也可以在 index.html 中更改入口点。

// bootstrap.tsx(新入口点)
import gtConfig from '../gt.config.json';
import { bootstrap } from 'gt-react/browser';

async function getTranslations(locale: string) {
  return import(`./_gt/${locale}.json`);
}

await bootstrap({
  ...gtConfig,
  getTranslations,
});

await import('./main.tsx');

getTranslations 函数是异步的——它会先加载翻译,再导入并执行 React 应用。这就是 t() 能在模块级访问翻译的原因:当任意模块调用 t() 时,翻译已经准备就绪。

这只适用于纯客户端 React 应用,因为模块级代码在浏览器中加载时会重新执行。而且由于要更新翻译后的内容,我们必须重新执行模块,所以切换区域设置时需要整页刷新。

**实验性:**此功能目前仅支持纯客户端 React 应用。

变量

t() 支持变量插值,用法与 msg() 相同:

import { t } from 'gt-react/browser';

t('Hello, {name}!', { name: 'John' });  // → "Hola, John!"

适用位置

当你需要在 React 组件树之外使用翻译时,t() 是合适的选择——比如常量文件、工具函数、配置对象、路由定义,或者任何在浏览器中运行于模块作用域的内容。

请注意:

  • 它目前还不能与 gt-react 系统的其余部分集成。 你需要按上文所述完成 bootstrap 设置。这是一种独立方案。
  • 仅支持客户端。 服务端翻译应使用基于 React 上下文的 Hook,例如 useGT

设计说明

t() 仅可在浏览器中使用。如果在服务器端调用 (此时 window 未定义) ,它会记录一条警告,并回退到源字符串。这是有意的——服务端翻译应使用现有的基于 React 上下文的 Hook。


API 参考

有关参数、返回类型和设置详细信息,请参阅完整的 t() API 参考