Node.js 有很多特性可以让编写国际化程序变得更容易。 它们之中有一些是:
Intl 对象String.prototype.localeCompare() 和 Date.prototype.toLocaleString() 这样的区域敏感方法require('buffer').transcode()require('util').TextDecoderRegExp Unicode 属性转义Node.js 和底层 V8 引擎使用 Unicode 国际组件(ICU) 在原生 C/C++ 代码中实现这些特性。 默认情况下,Node.js 提供了完整的 ICU 数据集。 但是,由于 ICU 数据文件的大小,在构建或运行 Node.js 时提供了几个用于自定义 ICU 数据集的选项。
为了控制在 Node.js 中如何使用 ICU,在编译期间提供了四个 configure 选项。
BUILDING.md 中记录了有关如何编译 Node.js 的其他详细信息。
--with-intl=none/--without-intl--with-intl=system-icu--with-intl=small-icu--with-intl=full-icu(默认)每个 configure 选项的可用 Node.js 和 JavaScript 特性概述:
| 特性 | none | system-icu | small-icu | full-icu |
|---|---|---|---|---|
String.prototype.normalize() | 无(函数无操作) | 完整 | 完整 | 完整 |
String.prototype.to*Case() | 完整 | 完整 | 完整 | 完整 |
Intl | 无(对象不存在) | 部分/完整(取决于操作系统) | 部分(仅英文) | 完整 |
String.prototype.localeCompare() | 部分(不识别区域设置) | 完整 | 完整 | 完整 |
String.prototype.toLocale*Case() | 部分(不识别区域设置) | 完整 | 完整 | 完整 |
Number.prototype.toLocaleString() | 部分(不识别区域设置) | 部分/完整(取决于操作系统) | 部分(仅英文) | 完整 |
Date.prototype.toLocale*String() | 部分(不识别区域设置) | 部分/完整(取决于操作系统) | 部分(仅英文) | 完整 |
| Legacy URL Parser | 部分(不支持 IDN) | 完整 | 完整 | 完整 |
| WHATWG URL Parser | 部分(不支持 IDN) | 完整 | 完整 | 完整 |
require('buffer').transcode() | 无(函数不存在) | 完整 | 完整 | 完整 |
| REPL | 部分(不准确的行编辑) | 完整 | 完整 | 完整 |
require('util').TextDecoder | 部分(基本的编码支持) | 部分/完整(取决于操作系统) | 部分(仅限 Unicode) | 完整 |
RegExp Unicode Property Escapes | 无(无效的 RegExp 错误) | 完整 | 完整 | 完整 |
"(not locale-aware)" 表示该函数执行其操作就像函数的非 Locale 版本一样,如果存在的话。
比如在 none 模式下,Date.prototype.toLocaleString() 的操作和 Date.prototype.toString() 是一样的。
如果选择此选项,则 ICU 将被禁用,并且上述大多数国际化特性在生成的 node 二进制文件中将不可用。
Node.js 可以链接到系统上已安装的 ICU。 事实上,大多数 Linux 发行版已经安装了 ICU,这个选项可以复用操作系统中其他组件使用的相同数据集。
system-icu 完全支持仅需要 ICU 库本身的功能,例如 String.prototype.normalize() 和 WHATWG 网址解析器。
另外需要 ICU 语言环境数据的特性,例如 Intl.DateTimeFormat 可能完全或部分支持,具体取决于系统上安装的 ICU 数据的完整性。
此选项静态地生成针对 ICU 库的二进制链接,并在 node 可执行文件中包含 ICU 数据的子集(通常只有英文区域设置)。
small-icu 完全支持仅需要 ICU 库本身的功能,例如 String.prototype.normalize() 和 WHATWG 网址解析器。
另外需要 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"
// 应该打印 "enero"
此模式提供了特性和二进制大小之间的平衡。
如果使用 small-icu 选项,则仍然可以在运行时提供额外的语言环境数据,以便 JS 方法适用于所有 ICU 语言环境。
假设数据文件存储在 /some/directory,它可以通过以下任一方式提供给 ICU:
NODE_ICU_DATA 环境变量:
env NODE_ICU_DATA=/some/directory node
--icu-data-dir 命令行参数:
node --icu-data-dir=/some/directory
(如果两者都指定,则 --icu-data-dir 命令行参数优先。)
ICU 能够自动查找和加载多种数据格式,但数据必须适合 ICU 版本,并且文件命名正确。
数据文件最常见的名称是 icudt6X[bl].dat,其中 6X 表示预期的 ICU 版本,而 b 或 l 表示系统的字节序。
查看 ICU 用户指南中的 "ICU 数据"文章以了解其他支持的格式以及有关 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-icu、small-icu 或 full-icu),只需检查 Intl 是否存在就足够了:
const hasICU = typeof Intl === 'object';
或者,检查 process.versions.icu,一个仅在启用 ICU 时定义的属性,也可以工作:
const hasICU = typeof process.versions.icu === 'string';
要检查对非英语语言环境(即 full-icu 或 system-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 支持的更详细的测试,以下资源可能会有所帮助: