Skip to content

国际化

中文与英文在这里是平等的。任何一方都不是另一方的「翻译」,并且由 CI 强制保证。

校验规则

src/i18n/i18n.test.ts 会在以下情况让构建失败:

  1. 某个 key 只存在于一种语言中。
  2. 存在空值。
  3. zh-CN 的值与英文完全相同。
  4. zh-CN 的值包含拉丁字母且不含任何汉字。

第 4 条之所以存在,是因为第 3 条并不够。profile.technical 曾经是英文单词 "technical",而英文侧是 "Technical contact" —— 两者确实不同,但显然仍未翻译。

品牌名(Ant DesignReact)、技术缩写(CPUAPI)与文件名 (theme.tshero-dark.png)在白名单内,其余文案必须包含汉字。

排版不能共用

拉丁字母与汉字的度量并不相同。汉字字面饱满、等宽,且没有升降部形成的节奏, 因此拉丁文的行高会挤压汉字,拉丁文的字距又会把它们拉散。tokens.css 维护两套并行的 度量体系:

css
:root {
  --text-base: 14px;
  --leading-normal: 1.55;
  --tracking-tight: -0.011em;
}

:root:lang(zh), :root:lang(ja), :root:lang(ko) {
  --text-base: 15px;      /* 相同字号下汉字视觉更小 */
  --leading-normal: 1.75;
  --tracking-tight: 0;    /* 负字距在中文里是明显错误 */
  --weight-bold: 600;     /* 避免合成的伪粗体 */
}

<html> 上的 lang 属性并非只是语义标记,它就是这套切换的开关。 buildTheme() 会把同样的差异同步到 antd 的 ConfigProvider

按需加载

语言包按需拉取,这样身处上海的读者不会下载他们永远不会看到的英文文案:

ts
const LOADERS = {
  'en-US': () => import('./locales/en-US/common.json'),
  'zh-CN': () => import('./locales/zh-CN/common.json'),
};

请使用 changeLocale() 而不是 i18n.changeLanguage():前者会先加载语言包再切换。 直接调用 changeLanguage 会在文案就位之前切换语言,导致界面闪现一帧原始 key。

新增语言

  1. src/i18n/locales/ 下新增目录。
  2. 将其加入 SUPPORTED_LOCALESLOADERS
  3. 若属于 CJK,需同时加入 CJK_LOCALES 以及 tokens.css 中的 :lang() 选择器。 漏掉第二步,正是新增日语后排版总觉得别扭的原因。
  4. ThemeProvider 中映射到对应的 antd 语言包。

基于 MIT 协议发布