Поддержка интернационализации
В Node.js есть множество возможностей, упрощающих написание интернационализированных программ. Вот некоторые из них:
- Функции, учитывающие локаль или поддерживающие Unicode, в Спецификации языка ECMAScript:
- Вся функциональность, описанная в Спецификации API интернационализации ECMAScript (также известной как ECMA-402):
-
объект
Intl - Методы, учитывающие локаль, например
String.prototype.localeCompare()иDate.prototype.toLocaleString()
-
объект
- Поддержка интернационализированных доменных имён (IDN) в парсере URL WHATWG
require('node:buffer').transcode()- Более точное редактирование строк в REPL
require('node:util').TextDecoderRegExpЭкранирование свойств 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 могут быть полезны следующие ресурсы:
© 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