Перейти к содержанию

Поддержка интернационализации

v18.x.x

Node.js имеет множество функций, которые облегчают написание интернационализированных программ. Вот некоторые из них:

Node.js и лежащий в основе движок V8 используют International Components for Unicode (ICU) для реализации этих возможностей в родном коде на C/C++. Полный набор данных ICU предоставляется Node.js по умолчанию. Однако, из-за размера файла данных ICU, предоставляется несколько опций для настройки набора данных ICU при сборке или запуске Node.js.

Опции для сборки Node.js

Чтобы контролировать использование 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 (default)

Обзор доступных возможностей Node.js и JavaScript для каждой опции configure:

Feature none system-icu small-icu full-icu
String.prototype.normalize() none (function is no-op) full full full
String.prototype.to*Case() full full full full
Intl none (object does not exist) partial/full (depends on OS) partial (English-only) full
String.prototype.localeCompare() partial (not locale-aware) full full full
String.prototype.toLocale*Case() partial (not locale-aware) full full full
Number.prototype.toLocaleString() partial (not locale-aware) partial/full (depends on OS) partial (English-only) full
Date.prototype.toLocale*String() partial (not locale-aware) partial/full (depends on OS) partial (English-only) full
Legacy URL Parser partial (no IDN support) full full full
WHATWG URL Parser partial (no IDN support) full full full
require('node:buffer').transcode() none (function does not exist) full full full
REPL partial (inaccurate line editing) full full full
require('node:util').TextDecoder partial (basic encodings support) partial/full (depends on OS) partial (Unicode-only) full
RegExp Unicode Property Escapes none (invalid RegExp error) full full full

Обозначение "(not locale-aware)" означает, что функция выполняет свою работу так же, как и нелокальная версия функции, если таковая существует. Например, в режиме none работа Date.prototype.toLocaleString() идентична работе Date.prototype.toString().

Отключить все функции интернационализации (none)

Если выбрана эта опция, ICU отключается и большинство функций интернационализации, упомянутых выше, будут недоступны в результирующем бинарном файле node.

Сборка с предустановленным ICU (system-icu)

Node.js может ссылаться на сборку ICU, уже установленную в системе. На самом деле, большинство дистрибутивов Linux уже поставляются с установленным ICU, и эта опция позволит повторно использовать тот же набор данных, который используется другими компонентами ОС.

Функции, которые требуют только саму библиотеку ICU, такие как String.prototype.normalize() и парсер URL WHATWG, полностью поддерживаются под system-icu. Функции, требующие дополнительных данных локали ICU, такие как Intl.DateTimeFormat могут поддерживаться полностью или частично, в зависимости от полноты данных ICU, установленных в системе.

Встраивание ограниченного набора данных ICU (small-icu)

Эта опция делает результирующий двоичный файл статически связанным с библиотекой ICU и включает подмножество данных ICU (обычно только английскую локаль) в исполняемый файл node.

Функции, требующие только саму библиотеку ICU, такие как String.prototype.normalize() и парсер URL WHATWG, полностью поддерживаются в small-icu. Функции, которые дополнительно требуют данные локали ICU, такие как Intl.DateTimeFormat, обычно работают только с английской локалью:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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));
// Печатает "январь"
console.log(spanish.format(january));
// Выводит либо "M01", либо "January" на small-icu, в зависимости от локали пользователя по умолчанию.
// Должно выводиться "enero"

Этот режим обеспечивает баланс между возможностями и размером двоичного файла.

Предоставление данных ICU во время выполнения.

Если используется опция small-icu, можно предоставить дополнительные данные о локали во время выполнения, чтобы методы JS работали для всех локалей ICU. Предполагая, что файл данных хранится в /some/directory, его можно сделать доступным для ICU либо через:

  • NODE_ICU_DATA переменную окружения:

    1
    env NODE_ICU_DATA=/some/directory node
    
  • CLI-параметр --icu-data-dir:

    1
    node --icu-data-dir=/some/directory
    

(Если указаны оба параметра, приоритет имеет параметр CLI --icu-data-dir).

ICU может автоматически находить и загружать данные различных форматов, но данные должны соответствовать версии ICU, а файл должен быть правильно назван. Наиболее распространенное имя файла данных - icudt6X[bl].dat, где 6X обозначает предполагаемую версию ICU, а b или l - эндианальность системы. Смотрите статью "ICU Data" в Руководстве пользователя ICU для других поддерживаемых форматов и более подробную информацию о данных ICU в целом.

Модуль full-icu npm может значительно упростить установку данных ICU, определяя версию ICU запущенного исполняемого файла node и загружая соответствующий файл данных. После установки модуля через npm i full-icu, файл данных будет доступен по адресу ./node_modules/full-icu. Этот путь можно передать в NODE_ICU_DATA или --icu-data-dir, как показано выше, чтобы включить полную поддержку Intl.

Встраивание всего ICU (full-icu)

Эта опция заставляет результирующий двоичный файл статически связываться с ICU и включать полный набор данных ICU. Созданный таким образом двоичный файл не имеет дополнительных внешних зависимостей и поддерживает все локали, но может быть довольно большим. Это поведение по умолчанию, если не передан флаг --with-intl. Официальные двоичные файлы также собираются в этом режиме.

Обнаружение поддержки интернационализации

Чтобы убедиться, что ICU вообще включен (system-icu, small-icu или full-icu), достаточно просто проверить существование Intl:

1
const hasICU = typeof Intl === 'object';

Альтернативно, проверка на process.versions.icu, свойство, определяемое только при включенном ICU, тоже работает:

1
const hasICU = typeof process.versions.icu === 'string';

Для проверки поддержки неанглийской локали (т. е. full-icu или system-icu), Intl.DateTimeFormat может быть хорошим отличительным фактором:

1
2
3
4
5
6
7
8
9
const hasFullICU = (() => {
  попытка {
    const january = new Date(9e8);
    const spanish = new Intl.DateTimeFormat("es", { month: "long" });
    return spanish.format(january) === "enero";
  } catch (err) {
    return false;
  }
})();

Для более подробных тестов на поддержку Intl могут быть полезны следующие ресурсы:

  • btest402: Обычно используется для проверки правильности сборки Node.js с поддержкой Intl.
  • Test262: Официальный набор тестов соответствия ECMAScript включает раздел, посвященный ECMA-402.