Node.js окружение

Библиотека Globalize строится вокруг стандарта CLDR (Unicode Common Locale Data Repository), что делает её мощным инструментом для локализации чисел, дат, валют, сообщений и единиц измерения. В Node.js окружении ключевым отличием становится отсутствие встроенных браузерных API для международализации в полном объёме и необходимость явной загрузки локализационных данных.

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


Архитектура Globalize в Node.js

Библиотека разделена на несколько слоёв:

  • CLDR data — набор JSON-файлов с локализационными данными
  • Globalize core — ядро форматирования и парсинга
  • Модули функциональности — числа, даты, сообщения, валюта
  • Runtime API — интерфейс, используемый в приложении

Node.js не предоставляет CLDR, поэтому данные подключаются вручную:

  • cldr-data
  • globalize
  • cldrjs (иногда используется косвенно через зависимости)

Установка зависимостей

Для Node.js проекта требуется установка базовых пакетов:

npm install globalize cldr-data

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

npm install cldr-data-number cldr-data-numbers-full

В большинстве случаев используется пакет cldr-data, содержащий готовую структуру каталогов.


Инициализация CLDR в Node.js

Globalize не работает без предварительной загрузки данных CLDR. Процесс включает несколько этапов: загрузка JSON, подключение к Globalize, определение локали.

const Globalize = require("globalize");
const cldrData = require("cldr-data");

// Загрузка базовых данных
Globalize.load(
  cldrData.entireSupplemental(),
  cldrData.entireMainFor("ru")
);

Ключевой момент — разделение данных:

  • supplemental — вспомогательные данные (календари, числа, регионы)
  • main — локаль (например, ru, en, de)

Настройка локали

После загрузки данных необходимо зафиксировать локаль:

const globalize = new Globalize("ru");

Экземпляр Globalize теперь работает в контексте русской локали.


Форматирование чисел

Node.js часто используется в backend-сервисах, где требуется унифицированное отображение чисел для API или логов.

const formatNumber = globalize.numberFormatter();

console.log(formatNumber(1234567.89));
// 1 234 567,89

Для процентов:

const formatPercent = globalize.numberFormatter({ style: "percent" });

console.log(formatPercent(0.25));
// 25%

Для компактного представления:

const formatCompact = globalize.numberFormatter({
  notation: "compact"
});

console.log(formatCompact(1500000));
// 1 млн

Парсинг чисел

Globalize поддерживает обратную операцию — разбор строки в число:

const parseNumber = globalize.numberParser();

console.log(parseNumber("1 234 567,89"));
// 1234567.89

Парсинг зависит от локали и учитывает:

  • разделители тысяч
  • десятичные символы
  • локальные особенности записи

Работа с валютами

Форматирование денежных значений требует загрузки дополнительного CLDR-модуля валют.

const formatCurrency = globalize.currencyFormatter("KZT");

console.log(formatCurrency(12345.67));
// 12 345,67 ₸

В Node.js важно учитывать, что валютные символы и правила округления берутся из CLDR.


Форматирование дат и времени

Для дат требуется загрузка календарных данных:

const formatDate = globalize.dateFormatter({
  datetime: "medium"
});

console.log(formatDate(new Date()));

Пример вывода зависит от локали:

  • формат дня недели
  • порядок компонентов даты
  • разделители

Разбор дат

const parseDate = globalize.dateParser({ skeleton: "yMd" });

console.log(parseDate("28.05.2026"));

Парсинг дат в Node.js особенно полезен при обработке пользовательского ввода в API.


Сообщения и ICU-шаблоны

Globalize поддерживает ICU MessageFormat, что позволяет создавать локализованные строки с условиями и множественными формами.

Globalize.loadMessages({
  ru: {
    items: "У вас {count, plural, one {# элемент} few {# элемента} many {# элементов} other {# элемента}}"
  }
});

const messageFormatter = globalize.messageFormatter("items");

console.log(messageFormatter({ count: 5 }));
// У вас 5 элементов

Node.js серверы часто используют это для генерации текстов API-ответов.


Работа с единицами измерения

CLDR содержит данные для форматирования единиц:

const formatUnit = globalize.unitFormatter("kilometer-per-hour");

console.log(formatUnit(90));
// 90 км/ч

Поддерживаются:

  • скорость
  • длина
  • масса
  • температура

Особенности загрузки CLDR в Node.js

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

  • загрузка всех локалей увеличивает память
  • загрузка одной локали ускоряет старт
  • ленивый импорт снижает overhead

Пример оптимизированного подхода:

Globalize.load(
  cldrData.entireSupplemental(),
  cldrData.entireMainFor("ru"),
  cldrData.entireMainFor("en")
);

При необходимости масштабирования рекомендуется ограничивать набор локалей.


Использование в модульной архитектуре

В Node.js проектах Globalize часто интегрируется в сервисный слой:

class LocalizationService {
  constructor(locale) {
    this.globalize = new Globalize(locale);
  }

  formatPrice(value) {
    const formatter = this.globalize.currencyFormatter("KZT");
    return formatter(value);
  }

  formatDate(date) {
    const formatter = this.globalize.dateFormatter({ datetime: "short" });
    return formatter(date);
  }
}

Такой подход позволяет:

  • изолировать локализацию
  • тестировать форматирование
  • переключать языки динамически

Интеграция с backend API

В API-слоях Node.js Globalize используется для подготовки ответов:

app.get("/invoice", (req, res) => {
  const g = new Globalize(req.headers["accept-language"] || "ru");

  const format = g.currencyFormatter("KZT");

  res.json({
    total: format(25000)
  });
});

Типичные ошибки в Node.js окружении

  • отсутствие Globalize.load() перед использованием
  • загрузка только main без supplemental
  • смешивание локалей без создания отдельных экземпляров
  • повторная загрузка CLDR в каждом запросе
  • игнорирование размера bundle при SSR

Производительные практики

  • инициализация Globalize один раз на процесс
  • кэширование форматтеров
  • минимизация CLDR данных
  • разделение локалей по регионам
  • использование singleton-сервисов
const g = new Globalize("ru");

const formatNumber = g.numberFormatter();
const formatDate = g.dateFormatter();

Поведение в многопоточном окружении Node.js

При использовании worker_threads или cluster:

  • CLDR загружается в каждом воркере отдельно
  • форматтеры не разделяются между процессами
  • рекомендуется инициализировать локализацию внутри каждого worker

Совместимость с современным Node.js

Globalize корректно работает с современными версиями Node.js, однако:

  • не использует Intl как основной механизм
  • полагается на собственную реализацию ICU через CLDR
  • требует явного контроля данных

Это делает библиотеку более предсказуемой в кросс-платформенных системах, где важно единообразие вывода независимо от окружения.