В прикладной интернационализации редко встречаются одиночные значения. Интерфейсные строки почти всегда включают сочетания чисел, дат, валют, единиц измерения и текстовых фрагментов. Именно в таких сценариях возникает задача комбинированного отображения, где несколько локализованных значений должны быть объединены в единую грамматически корректную строку.
Библиотека Globalize решает эту задачу через механизм сообщений (Message Formatting), построенный поверх ICU MessageFormat и данных CLDR. Основной принцип заключается в том, что форматирование не ограничивается отдельными типами данных — числа, даты и единицы могут быть встроены в одну синтаксическую конструкцию.
Ключевая особенность заключается в разделении ответственности:
Комбинированное отображение в Globalize опирается на несколько уровней:
1. Форматтеры значений
formatNumberformatDateformatCurrencyformatUnitformatRelativeTime2. Слой сообщений
messageFormatter3. CLDR-данные
Именно слой сообщений связывает независимые форматтеры в единую строку.
Комбинирование строится вокруг шаблонов, где значения подставляются в заранее определённые позиции:
const formatter = Globalize.messageFormatter(
"{username} сделал покупку на сумму {amount} {currency}"
);
formatter({
username: "Иван",
amount: Globalize( "ru" ).formatNumber(1250),
currency: "RUB"
});
Несмотря на внешнюю простоту, ключевой момент заключается в том, что каждое значение уже локализовано до подстановки.
Наиболее распространённый сценарий комбинированного отображения — финансовые сообщения.
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"Баланс счета: {balance} {currency}"
);
message({
balance: cldr.formatNumber(15230.5),
currency: "RUB"
});
Однако корректная реализация предполагает, что валютное форматирование выполняется отдельно:
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"Баланс счета: {balance}"
);
message({
balance: cldr.formatCurrency(15230.5, "RUB")
});
Разделение валюты и числа позволяет учитывать локальные правила:
Даты редко используются изолированно. В интерфейсах они почти всегда связаны с числовыми параметрами.
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"Заказ оформлен {date}, общая сумма {amount}"
);
message({
date: cldr.formatDate(new Date(2026, 4, 27)),
amount: cldr.formatNumber(3200)
});
Здесь важно, что дата и число обрабатываются разными форматтерами, но объединяются единым шаблоном.
Одним из самых сложных аспектов является согласование множественных форм. ICU MessageFormat, используемый Globalize, позволяет встроить правила плюрализации прямо в шаблон.
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"{count, plural, one {# файл загружен} few {# файла загружено} many {# файлов загружено}}"
);
message({ count: 5 });
При комбинировании с другими значениями:
const message = cldr.messageFormatter(
"{name} загрузил {count, plural, one {# файл} few {# файла} many {# файлов}}"
);
message({
name: "Алексей",
count: 3
});
Каждая часть обрабатывается независимо, но итоговая строка формируется как единое грамматическое целое.
MessageFormat поддерживает вложенные конструкции, что позволяет строить сложные сообщения.
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"{user} совершил оплату: {amount} ({status})"
);
message({
user: "Мария",
amount: cldr.formatCurrency(499.99, "RUB"),
status: "успешно"
});
Более сложные случаи включают вложенные плюрализации внутри общей структуры сообщения:
const message = cldr.messageFormatter(
"{user} добавил {count, plural, one {# товар} few {# товара} many {# товаров}} на сумму {amount}"
);
Отдельного внимания требует комбинирование физических единиц с числовыми значениями.
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"Скорость соединения: {speed}"
);
message({
speed: cldr.formatUnit(50, "megabyte-per-second")
});
Такой подход обеспечивает:
Relative time часто используется вместе с другими параметрами:
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"Последняя активность: {time} ({diff})"
);
message({
time: cldr.formatDate(new Date(2026, 4, 27, 10, 30)),
diff: cldr.formatRelativeTime(-2, "hour")
});
Здесь соединяются абсолютное и относительное представление времени, что повышает информативность интерфейса.
При развитии интерфейса сообщения становятся многоуровневыми:
const cldr = Globalize( "ru" );
const message = cldr.messageFormatter(
"{user} оформил заказ {orderId} на {amount}. {items, plural, one {# позиция} few {# позиции} many {# позиций}} добавлено в корзину."
);
message({
user: "Олег",
orderId: "#A-1034",
amount: cldr.formatCurrency(7890, "RUB"),
items: 4
});
Такие конструкции требуют строгого разделения:
Комбинированное отображение опирается на единообразие локали. Все форматтеры Globalize используют одну и ту же локализацию:
const cldr = Globalize( "ru" );
cldr.formatNumber(1000);
cldr.formatDate(new Date());
cldr.formatCurrency(1000, "RUB");
При объединении этих значений в одном сообщении исключаются несоответствия:
При частом формировании сообщений важным становится кеширование форматтеров:
const cldr = Globalize( "ru" );
const formatOrderMessage = cldr.messageFormatter(
"{user} заказал {amount}"
);
Форматтер создаётся один раз и повторно используется, что снижает нагрузку при массовом рендеринге интерфейсов.
1. Предварительное объединение строк
Ошибочный подход — конкатенация до форматирования:
"Сумма: " + Globalize.formatNumber(1000)
Правильный подход — использование сообщений.
2. Игнорирование локали
Форматирование без единого контекста локали приводит к разнородному выводу.
3. Смешивание форматирования и логики
ICU-шаблоны должны содержать только правила представления, но не бизнес-логику.
В сложных интерфейсах комбинированное отображение может включать:
const message = cldr.messageFormatter(
"{product} вырос в цене на {percent}% ({diff})"
);
message({
product: "Товар",
percent: cldr.formatNumber(12.5),
diff: cldr.formatCurrency(150, "RUB")
});
CLDR обеспечивает основу для корректного комбинирования значений:
Без этих данных комбинированное отображение теряет языковую корректность и становится набором механических подстановок.