On this page

国际化支持

History

Node.js 拥有许多功能,使编写国际化程序变得更加容易。其中一些功能包括:

Node.js 和底层的 V8 引擎使用 International Components for Unicode (ICU) 在原生 C/C++ 代码中实现这些功能。Node.js 默认提供完整的 ICU 数据集。但是,由于 ICU 数据文件的大小,在构建或运行 Node.js 时提供了几个选项来自定义 ICU 数据集。

为了控制 ICU 在 Node.js 中的使用方式,编译期间有四个 configure 选项可用。有关如何编译 Node.js 的更多详细信息记录在 BUILDING.md 中。

  • --with-intl=none/--without-intl
  • --with-intl=system-icu
  • --with-intl=small-icu
  • --with-intl=full-icu(默认)

每个 configure 选项可用的 Node.js 和 JavaScript 功能概述:

功能nonesystem-icusmall-icufull-icu
String.prototype.normalize()无(函数为空操作)完整完整完整
String.prototype.to*Case()完整完整完整完整
Intl无(对象不存在)部分/完整(取决于操作系统)部分(仅英语)完整
String.prototype.localeCompare()部分(非区域感知)完整完整完整
String.prototype.toLocale*Case()部分(非区域感知)完整完整完整
Number.prototype.toLocaleString()部分(非区域感知)部分/完整(取决于操作系统)部分(仅英语)完整
Date.prototype.toLocale*String()部分(非区域感知)部分/完整(取决于操作系统)部分(仅英语)完整
旧版 URL 解析器部分(无 IDN 支持)完整完整完整
WHATWG URL 解析器部分(无 IDN 支持)完整完整完整
require('node:buffer').transcode()无(函数不存在)完整完整完整
REPL部分(行编辑不准确)完整完整完整
require('node:util').TextDecoder部分(支持基本编码)部分/完整(取决于操作系统)部分(仅 Unicode)完整
RegExp Unicode 属性转义无(无效的 RegExp 错误)完整完整完整

"(非区域感知)" 标识表示该函数执行的操作与其非 Locale 版本的操作相同(如果存在的话)。例如,在 none 模式下,Date.prototype.toLocaleString() 的操作与 Date.prototype.toString() 的操作相同。

如果选择了此选项,ICU 将被禁用,并且上述大多数国际化功能在生成的 node 二进制文件中将不可用

Node.js 可以链接到系统上已安装的 ICU 构建。事实上,大多数 Linux 发行版已经安装了 ICU,此选项将使得重用操作系统中其他组件使用的同一数据集成为可能。

仅需要 ICU 库本身的功能,如 String.prototype.normalize()WHATWG URL 解析器,在 system-icu 下得到完全支持。需要 ICU 区域数据的功能,如 Intl.DateTimeFormat,可能得到完全或部分支持,这取决于系统上安装的 ICU 数据的完整性。

此选项使生成的二进制文件静态链接到 ICU 库,并在 node 可执行文件中包含 ICU 数据的子集(通常仅包含英语区域设置)。

仅需要 ICU 库本身的功能,如 String.prototype.normalize()WHATWG URL 解析器,在 small-icu 下得到完全支持。需要 ICU 区域数据的功能,如 Intl.DateTimeFormat,通常仅适用于英语区域设置:

const january = new Date(9e8);
const english = new Intl.DateTimeFormat('en', { month: 'long' });
const spanish = new Intl.DateTimeFormat('es', { month: 'long' });

console.log(english.format(january));
// 输出 "January"
console.log(spanish.format(january));
// 在 small-icu 上输出 "M01" 或 "January",取决于用户的默认区域设置
// 应该输出 "enero"

此模式在功能和二进制大小之间提供了平衡。

如果使用了 small-icu 选项,仍然可以在运行时提供额外的区域数据,以便 JavaScript 方法适用于所有 ICU 区域设置。假设数据文件存储在 /runtime/directory/with/dat/file,可以通过以下方式使其对 ICU 可用:

  • --with-icu-default-data-dir configure 选项:

    这仅将默认数据目录路径嵌入到二进制文件中。 实际的数据文件将在运行时从此目录路径加载。

  • NODE_ICU_DATA 环境变量:

  • --icu-data-dir CLI 参数:

当指定了多个选项时,--icu-data-dir CLI 参数具有最高优先级,其次是 NODE_ICU_DATA 环境变量,然后是 --with-icu-default-data-dir configure 选项。

ICU 能够自动查找并加载各种数据格式,但数据必须适用于 ICU 版本,且文件命名正确。数据文件最常见的名称是 icudtX[bl].dat,其中 X 表示预期的 ICU 版本,bl 表示系统的字节序。如果无法从指定目录读取预期的数据文件,Node.js 将加载失败。与当前 Node.js 版本对应的数据文件名称可以通过以下方式计算:

查看 ICU 用户指南中的 "ICU Data" 文章,了解其他支持的格式以及有关 ICU 数据的一般详细信息。

full-icu npm 模块可以通过检测运行中的 node 可执行文件的 ICU 版本并下载适当的数据文件,从而大大简化 ICU 数据的安装。通过 npm i full-icu 安装模块后,数据文件将位于 ./node_modules/full-icu。然后可以将此路径传递给 NODE_ICU_DATA--icu-data-dir,如上所示,以启用完整的 Intl 支持。

此选项使生成的二进制文件静态链接到 ICU 并包含完整的 ICU 数据集。以此方式创建的二进制文件没有进一步的外部依赖项,并支持所有区域设置,但可能相当大。如果没有传递 --with-intl 标志,这是默认行为。官方二进制文件也是以此模式构建的。

要验证是否启用了 ICU(system-icusmall-icufull-icu),只需检查 Intl 的存在性就足够了:

或者,检查 process.versions.icu(仅在启用 ICU 时定义的属性)也可以:

要检查对非英语区域设置的支持(即 full-icusystem-icu),Intl.DateTimeFormat 可以作为一个很好的区分因素:

const hasFullICU = (() => {
  try {
    const january = new Date(9e8);
    const spanish = new Intl.DateTimeFormat('es', { month: 'long' });
    return spanish.format(january) === 'enero';
  } catch (err) {
    return false;
  }
})();

对于更详细的 Intl 支持测试,以下资源可能会有所帮助:

  • btest402:通常用于检查带有 Intl 支持的 Node.js 是否构建正确。
  • Test262:ECMAScript 的官方一致性测试套件包含一个专门针对 ECMA-402 的部分。