Поддержка интернационализации¶
У Node.js есть множество возможностей, облегчающих написание интернационализированных программ. Вот некоторые из них:
- Функции, чувствительные к локали или осведомлённые об Unicode, из спецификации языка ECMAScript:
String.prototype.normalize()String.prototype.toLowerCase()String.prototype.toUpperCase()- Вся функциональность, описанная в спецификации ECMAScript Internationalization API (она же ECMA-402):
- объект
Intl - методы, чувствительные к локали, например
String.prototype.localeCompare()иDate.prototype.toLocaleString() - Поддержка интернационализированных доменных имён (IDN) в парсере URL WHATWG
require('node:buffer').transcode()- Более точное редактирование строк в REPL
require('node:util').TextDecoderRegExpUnicode Property Escapes
Node.js и лежащий в основе движок V8 используют International Components for Unicode (ICU) для реализации этих возможностей в нативном коде на C/C++. Полный набор данных ICU поставляется с Node.js по умолчанию. Однако из‑за размера файла данных ICU при сборке или запуске Node.js доступны несколько вариантов настройки набора данных ICU.
Опции сборки 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() | нет (функция — no-op) | полная | полная | полная |
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('node:buffer').transcode() | нет (функция отсутствует) | полная | полная | полная |
| REPL | частичная (неточное редактирование строк) | полная | полная | полная |
require('node:util').TextDecoder | частичная (базовые кодировки) | частичная/полная (зависит от ОС) | частичная (только Unicode) | полная |
RegExp Unicode Property Escapes | нет (ошибка недопустимого 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, как правило работают только с английской локалью:
1 2 3 4 5 6 7 8 9 | |
Этот режим компромисс между возможностями и размером бинарника.
Поставка данных ICU во время выполнения¶
Если используется опция small-icu, дополнительные локальные данные можно подключить во время выполнения, чтобы JS-методы работали для всех локалей ICU. Пусть файл данных лежит в /runtime/directory/with/dat/file, тогда ICU может получить к нему доступ одним из способов:
- Опция
configure--with-icu-default-data-dir:
1 | |
При этом в бинарник встраивается только путь к каталогу данных по умолчанию. Сам файл данных будет загружаться во время выполнения из этого каталога.
- Переменная окружения
NODE_ICU_DATA:
1 | |
- Параметр CLI
--icu-data-dir:
1 | |
Если указано несколько вариантов, наивысший приоритет у параметра CLI --icu-data-dir, затем переменная окружения NODE_ICU_DATA, затем опция configure --with-icu-default-data-dir.
ICU умеет автоматически находить и загружать разные форматы данных, но данные должны соответствовать версии ICU, а файл — иметь корректное имя. Чаще всего файл данных называется icudtX[bl].dat, где X — целевая версия ICU, а b или l — порядок байт системы. Node.js не загрузится, если ожидаемый файл данных нельзя прочитать из указанного каталога. Имя файла данных для текущей версии Node.js можно вычислить так:
1 | |
См. статью "ICU Data" в ICU User Guide про другие поддерживаемые форматы и подробности про данные 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. Такой бинарник не имеет внешних зависимостей по ICU и поддерживает все локали, но может быть довольно большим. Такое поведение по умолчанию, если не передавать флаг --with-intl. Официальные сборки тоже собираются в этом режиме.
Определение поддержки интернационализации¶
Чтобы убедиться, что ICU включён вообще (system-icu, small-icu или full-icu), достаточно проверить наличие Intl:
1 | |
Альтернатива — проверка process.versions.icu: это свойство есть только при включённом ICU:
1 | |
Чтобы проверить поддержку неанглийской локали (т.е. full-icu или system-icu), хорошо подходит Intl.DateTimeFormat:
1 2 3 4 5 6 7 8 9 | |
Для более подробных тестов поддержки Intl могут пригодиться:
- btest402: обычно используют, чтобы проверить, что Node.js с поддержкой
Intlсобран корректно. - Test262: официальный набор тестов соответствия ECMAScript включает раздел, посвящённый ECMA-402.