Spec-Zone.ru › Node.js 22 LTS

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

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

  • Функции, учитывающие локаль или поддерживающие Unicode, в Спецификации языка ECMAScript:
    • String.prototype.normalize()
    • String.prototype.toLowerCase()
    • String.prototype.toUpperCase()
  • Вся функциональность, описанная в Спецификации API интернационализации ECMAScript (также известной как ECMA-402):
    • объект Intl
    • Методы, учитывающие локаль, например String.prototype.localeCompare() и Date.prototype.toLocaleString()
  • Поддержка интернационализированных доменных имён (IDN) в парсере URL WHATWG
  • require('node:buffer').transcode()
  • Более точное редактирование строк в REPL
  • require('node:util').TextDecoder
  • RegExp Экранирование свойств Unicode

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

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

Возможность 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() частичная (не учитывает локаль) частичная/полная (зависит от ОС) частичная (только английский) полная
Устаревший парсер URL частичная (без поддержки IDN) полная полная полная
Парсер URL WHATWG частичная (без поддержки IDN) полная полная полная
require('node:buffer').transcode() отсутствует (функция не существует) полная полная полная
REPL частичная (неточное редактирование строк) полная полная полная
require('node:util').TextDecoder частичная (поддержка основных кодировок) частичная/полная (зависит от ОС) частичная (только Unicode) полная
RegExp Экранирование свойств Unicode отсутствует (ошибка недопустимого RegExp) полная полная полная

Пометка «не учитывает локаль» означает, что функция выполняет свою операцию так же, как версия функции без Locale, если такая версия существует. Например, в режиме 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, как правило, работают только с английской локалью:

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));
// Prints "January"
console.log(spanish.format(january));
// Prints either "M01" or "January" on small-icu, depending on the user’s default locale
// Should print "enero" copy

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

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

Если используется вариант small-icu, дополнительные данные локалей всё ещё можно предоставить во время выполнения, чтобы методы JS работали для всех локалей ICU. Если файл данных хранится в /runtime/directory/with/dat/file, его можно сделать доступным для ICU одним из следующих способов:

  • С помощью параметра конфигурации --with-icu-default-data-dir:

    ./configure --with-icu-default-data-dir=/runtime/directory/with/dat/file --with-intl=small-icu copy

    При этом в двоичный файл добавляется только путь к каталогу данных по умолчанию. Сам файл данных будет загружен во время выполнения из указанного каталога.

  • С помощью переменной окружения NODE_ICU_DATA:

    env NODE_ICU_DATA=/runtime/directory/with/dat/file node copy
  • С помощью параметра командной строки --icu-data-dir:

    node --icu-data-dir=/runtime/directory/with/dat/file copy

Если указано несколько таких параметров, наивысший приоритет имеет параметр командной строки --icu-data-dir, за ним следует переменная окружения NODE_ICU_DATA, а затем параметр конфигурации --with-icu-default-data-dir.

ICU может автоматически находить и загружать данные в разных форматах, однако данные должны соответствовать версии ICU, а имя файла должно быть указано правильно. Самое распространённое имя файла данных — icudtX[bl].dat, где X обозначает целевую версию ICU, а b или l указывает порядок байтов системы. Node.js не запустится, если не удастся прочитать ожидаемый файл данных из указанного каталога. Имя файла данных для текущей версии Node.js можно вычислить с помощью:

`icudt${process.versions.icu.split('.')[0]}${os.endianness()[0].toLowerCase()}.dat`; copy

Другие поддерживаемые форматы и дополнительные сведения о данных ICU в целом описаны в статье «Данные ICU» в руководстве пользователя ICU.

Модуль npm full-icu значительно упрощает установку данных 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:

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

Также можно проверить наличие process.versions.icu — свойства, определённого только при включённой ICU:

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

Чтобы проверить поддержку локали, отличной от английской (то есть 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;
  }
})(); copy

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

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

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v22.x/docs/api/intl.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API