Форматирование в шаблонах

В шаблонах интернационализации Globalize форматирование данных строится вокруг двух ключевых механизмов: форматирования примитивных значений (числа, даты, валюты) и интерполяции сложных сообщений через ICU MessageFormat. Оба подхода опираются на CLDR-данные и позволяют отделить локаль-зависимое представление данных от бизнес-логики приложения.


Роль форматирования в шаблонах сообщений

Шаблон в Globalize представляет собой строку с плейсхолдерами, которые заменяются значениями в момент выполнения. В отличие от простой конкатенации строк, система учитывает:

  • правила склонения и множественных форм;
  • локализацию чисел и дат;
  • форматирование валют и процентов;
  • контекст языка (локаль).

Базовый принцип заключается в том, что шаблон не содержит «готового текста», а описывает структуру сообщения.


ICU MessageFormat как основа шаблонов

Globalize использует синтаксис ICU MessageFormat для описания сложных шаблонов.

Базовая подстановка значений

Самая простая форма — интерполяция переменных:

Globalize.formatMessage("Привет, {name}!", { name: "Алексей" });

Результат:

Привет, Алексей!

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


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

Числа в шаблонах могут форматироваться с учётом локали через встроенные форматы ICU.

Использование числового формата

Globalize.formatMessage(
  "У вас {count, number} новых сообщений",
  { count: 1250 }
);

В зависимости от локали результат может отличаться:

  • en: You have 1,250 new messages
  • ru: У вас 1 250 новых сообщений

Управление типами чисел

ICU поддерживает несколько типов числового форматирования:

  • number — стандартное локализованное число
  • percent — проценты
  • integer — целые значения

Пример процентов:

Globalize.formatMessage(
  "Завершено на {progress, percent}",
  { progress: 0.42 }
);

Форматирование валют в шаблонах

Для денежных значений используется тип currency, который учитывает код валюты и локаль.

Globalize.formatMessage(
  "Стоимость: {price, number, currency}",
  { price: 1999.99 }
);

Однако сам код валюты обычно задаётся через параметры форматирования числа:

Globalize.numberFormatter({ style: "currency", currency: "USD" })(1999.99);

В шаблонах чаще используется предварительно сконфигурированный форматтер:

const formatUSD = Globalize.currencyFormatter("USD");

Globalize.formatMessage(
  "Цена: {price}",
  { price: formatUSD(1999.99) }
);

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

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

Форматирование даты перед подстановкой

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

Globalize.formatMessage(
  "Последнее обновление: {date}",
  { date: dateFormatter(new Date()) }
);

Результат зависит от локали:

  • en: Last update: May 27, 2026, 3:15 PM
  • ru: Последнее обновление: 27 мая 2026 г., 15:15

Разделение уровней форматирования

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

  1. форматтер даты;
  2. подстановка готового значения в шаблон.

Условные выражения и множественные формы

Одним из наиболее мощных механизмов ICU является поддержка plural rules.

Базовая форма множественности

Globalize.formatMessage(
  "{count, plural, one {# файл} few {# файла} many {# файлов} other {# файлов}}",
  { count: 5 }
);

Каждая форма соответствует правилам локали. Для русского языка важно различие между:

  • one (1)
  • few (2–4)
  • many (5 и более)
  • other (служебная форма)

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

Символ # автоматически заменяется на значение переменной:

5 файлов

Вложенные шаблоны и комбинирование форматирования

Шаблоны могут включать несколько типов форматирования одновременно.

Globalize.formatMessage(
  "{name} загрузил {count, plural, one {# файл} few {# файла} many {# файлов}} на сумму {amount}",
  {
    name: "Ирина",
    count: 3,
    amount: Globalize.currencyFormatter("EUR")(1200)
  }
);

Такой подход позволяет комбинировать:

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

Экранирование и специальные символы

При работе с ICU-шаблонами необходимо учитывать специальные символы:

  • {} — границы плейсхолдеров;
  • ' — экранирование текста;
  • # — замена числа в plural.

Экранирование фигурных скобок

Globalize.formatMessage(
  "Символы '{{' и '}}' используются как скобки"
);

Результат:

Символы { и } используются как скобки

Форматирование вложенных объектов данных

Globalize поддерживает доступ к вложенным структурам через точечную нотацию.

Globalize.formatMessage(
  "Пользователь {user.name} имеет {user.stats.messages} сообщений",
  {
    user: {
      name: "Дмитрий",
      stats: {
        messages: 42
      }
    }
  }
);

Использование форматтеров внутри сообщений

Одной из особенностей архитектуры Globalize является разделение:

  • форматтеров (числа, даты, валюты);
  • шаблонов сообщений.

Пример композиции

const numberFormatter = Globalize.numberFormatter();
const messageFormatter = Globalize.messageFormatter(
  "{value} обработано"
);

messageFormatter({
  value: numberFormatter(1000)
});

Такой подход позволяет заранее кэшировать форматтеры и снижать накладные расходы при рендеринге интерфейса.


Повторное использование форматтеров в шаблонах

В производительных приложениях форматтеры создаются один раз и используются многократно.

const msg = Globalize.messageFormatter(
  "{count, plural, one {# элемент} other {# элементов}}"
);

msg({ count: 1 });
msg({ count: 10 });

Шаблон компилируется в функцию, что делает вызовы быстрыми даже при большом количестве данных.


Локализационная зависимость форматирования

Форматирование в шаблонах строго зависит от текущей локали Globalize.

Globalize.locale("ru");

Globalize.formatMessage(
  "Баланс: {amount}",
  { amount: Globalize.currencyFormatter("RUB")(1500) }
);

Переключение локали изменяет:

  • разделители чисел;
  • порядок дат;
  • правила множественных форм;
  • отображение валют.

Ограничения шаблонного форматирования

Несмотря на гибкость, шаблонный механизм имеет ряд ограничений:

  • невозможность сложной логики внутри шаблона;
  • отсутствие циклов;
  • ограниченность арифметических операций;
  • необходимость предварительной подготовки данных.

Все вычисления выполняются вне шаблона, а внутрь передаются уже подготовленные значения.


Типовые ошибки при использовании шаблонов

Передача неформатированных значений

Globalize.formatMessage(
  "Цена: {price}",
  { price: 1999.99 }
);

Ошибка: число не локализовано.

Правильный вариант:

{ price: Globalize.currencyFormatter("USD")(1999.99) }

Неправильные plural-формы

"{count, plural, one {# item} other {# items}}"

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


Попытка логики внутри шаблона

"{count > 5 ? 'много' : 'мало'}"

ICU MessageFormat не поддерживает JavaScript-выражения.


Структурный подход к проектированию шаблонов

Корректное использование форматирования в Globalize предполагает разделение ответственности:

  • шаблон описывает структуру сообщения;
  • форматтеры обрабатывают локализацию значений;
  • бизнес-логика подготавливает данные.

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