Численные и текстовые варианты

Модель работы с числами в Globalize

Globalize строится на данных Unicode CLDR, где числовые представления зависят от локали: разделители, группировка, десятичные символы, система округления и отображение отрицательных значений. Базовая задача слоя числового форматирования — привести внутреннее числовое значение к строковому виду, соответствующему правилам конкретного языка и региона.

В основе лежат несколько ключевых аспектов:

  • символ десятичного разделителя (, или .)
  • символ группировки разрядов
  • правила округления
  • форматирование процентов и валют
  • локализованные шаблоны чисел

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

Globalize использует заранее загруженные CLDR-данные, чтобы корректно применять шаблоны формата.

Globalize.locale("en");

Globalize.formatNumber(1234567.89);
// "1,234,567.89"

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

Globalize.locale("de");

Globalize.formatNumber(1234567.89);
// "1.234.567,89"

Ключевое отличие заключается в том, что формат не «жёстко задан», а вычисляется на основе локализационных правил.

Пользовательские шаблоны чисел

Поддерживаются шаблоны, определяющие поведение округления и отображения дробной части:

Globalize.formatNumber(12.3, { minimumFractionDigits: 2 });
// "12.30"
Globalize.formatNumber(12.3456, { maximumFractionDigits: 2 });
// "12.35"

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


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

Обратное преобразование строки в число учитывает локаль, что критично для пользовательского ввода.

Globalize.parseNumber("1,234.56");
// 1234.56 (en)

В других локалях входной формат отличается:

Globalize.locale("de");

Globalize.parseNumber("1.234,56");
// 1234.56

Парсинг учитывает:

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

Валюты и числовые форматы высокой специфичности

Финансовое форматирование опирается на CLDR currency data.

Globalize.formatCurrency(1999.99, "USD");
// "$1,999.99"

В другой локали:

Globalize.locale("fr");

Globalize.formatCurrency(1999.99, "EUR");
// "1 999,99 €"

Особенности:

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

Текстовые варианты и множественные формы

Система plural rules

Одной из ключевых задач локализации является корректное согласование чисел с текстом. В разных языках количество форм множественного числа различается: от двух до шести и более.

Globalize использует CLDR plural rules для определения категории числа.

Globalize.locale("en");

Globalize.plural(1); // "one"
Globalize.plural(2); // "other"

Для языков с более сложной системой:

Globalize.locale("ru");

Globalize.plural(1);  // "one"
Globalize.plural(2);  // "few"
Globalize.plural(5);  // "many"

Эти категории не фиксированы в коде библиотеки, они приходят из CLDR.


Формирование текстовых сообщений

Механизм сообщений позволяет строить динамические строки с учётом числовых вариантов.

const messages = {
  itemCount: "{count, plural, one {# элемент} few {# элемента} many {# элементов} other {# элемента}}"
};

Регистрация сообщений:

Globalize.loadMessages(messages);

Использование:

Globalize.messageFormatter("itemCount")(1);
// "1 элемент"

Globalize.messageFormatter("itemCount")(3);
// "3 элемента"

Globalize.messageFormatter("itemCount")(5);
// "5 элементов"

Select-логика и условные текстовые варианты

Помимо plural существует более общий механизм select, который позволяет выбирать текст по произвольному ключу.

const messages = {
  status: "{state, select, success {Успешно} error {Ошибка} other {Неизвестно}}"
};

Использование:

Globalize.messageFormatter("status")({ state: "success" });
// "Успешно"

Globalize.messageFormatter("status")({ state: "error" });
// "Ошибка"

Select-выражения применяются для:

  • статусов системы
  • ролей пользователей
  • типов объектов
  • условных текстовых ветвлений

Комбинирование чисел и текстовых вариантов

Наиболее частый сценарий — объединение чисел и plural-логики в одном сообщении.

const messages = {
  cart: "В корзине {count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}"
};

Использование:

Globalize.messageFormatter("cart")({ count: 1 });
// "В корзине 1 товар"

Globalize.messageFormatter("cart")({ count: 4 });
// "В корзине 4 товара"

Механизм автоматически:

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

Поддержка вложенных выражений

MessageFormat позволяет комбинировать select и plural в одной структуре.

const messages = {
  inbox: "{gender, select, male {У него {count, plural, one {# письмо} other {# писем}}} female {У неё {count, plural, one {# письмо} other {# писем}}} other {Есть {count, plural, one {# письмо} other {# писем}}}}"
};

Пример использования:

Globalize.messageFormatter("inbox")({
  gender: "female",
  count: 2
});

Результат:

У неё 2 писем

Такие конструкции используются для сложных интерфейсов, где одновременно учитываются:

  • грамматический род
  • число
  • состояние объекта

Особенности работы с ICU MessageFormat

Система сообщений основана на синтаксисе ICU, где:

  • {variable} — подстановка значения
  • plural — выбор формы по числу
  • select — выбор по ключу
  • # — автоматическая подстановка числового значения

Синтаксис интерпретируется при компиляции message formatter, а не во время каждого вызова, что снижает накладные расходы при повторном использовании.


Производительность числовых и текстовых преобразований

Внутренняя архитектура Globalize оптимизирует:

  • кэширование форматтеров
  • предварительную компиляцию сообщений
  • повторное использование CLDR-данных

Форматтер создаётся один раз:

const formatter = Globalize.numberFormatter();
formatter(12345);
formatter(67890);

Это позволяет избегать повторного анализа локализационных правил при каждом вызове.


Ошибки локализации числовых и текстовых данных

Типовые проблемы возникают при несоответствии данных CLDR и входных значений:

  • отсутствие загруженных CLDR модулей
  • несоответствие локали сообщениям
  • использование неправильных категорий plural
  • попытка форматировать без установленной локали

Поведение в таких случаях зависит от конфигурации, но обычно происходит fallback к базовой локали или нейтральному формату.


Разделение числового и текстового слоёв

Архитектурно числовое форматирование и текстовые варианты разделены:

  • числовой слой: форматирование, парсинг, валюты, проценты
  • текстовый слой: plural, select, message composition

Оба слоя используют единый источник правил — CLDR, но работают независимо, что позволяет комбинировать их без взаимных ограничений.