В основе интернационализации интерфейсов часто лежит необходимость формировать строки на основе шаблонов, где часть текста динамически заменяется значениями из данных приложения. В библиотеке Globalize этот механизм реализован через систему сообщений, построенную поверх CLDR-данных и формата ICU MessageFormat.
Простейшая форма подстановки в Globalize представляет собой строку с именованными параметрами, которые заменяются значениями при форматировании. Такой подход решает задачу отделения текста интерфейса от бизнес-логики и позволяет централизованно управлять локализацией.
Сообщения описываются как строковые шаблоны, где параметры заключаются в фигурные скобки:
"Привет, {name}"
При обработке шаблона библиотека заменяет {name} на
соответствующее значение, переданное в момент форматирования. Такой
механизм обеспечивает:
Перед использованием механизма подстановки требуется загрузка CLDR-данных и инициализация локали. Globalize не содержит локализационных данных по умолчанию, что делает его полностью модульным.
Пример типичной подготовки:
import Globalize from "globalize";
import likelySubtags from "cldr-data/supplemental/likelySubtags.json";
import numberingSystems from "cldr-data/supplemental/numberingSystems.json";
import caGregorian from "cldr-data/main/ru/ca-gregorian.json";
import numbers from "cldr-data/main/ru/numbers.json";
import timeZoneNames from "cldr-data/main/ru/timeZoneNames.json";
import currencies from "cldr-data/main/ru/currencies.json";
import messages from "cldr-data/main/ru/messages.json";
Globalize.load(
likelySubtags,
numberingSystems,
caGregorian,
numbers,
timeZoneNames,
currencies,
messages
);
const globalize = new Globalize("ru");
После этого становится доступна работа с сообщениями, числами и датами в рамках выбранной локали.
Основной API для работы с подстановкой строк —
messageFormatter. Он компилирует шаблон в функцию, которая
затем многократно используется для генерации строк.
const greet = globalize.messageFormatter("greeting");
greet({ name: "Алексей" });
При наличии сообщения:
{
"greeting": "Привет, {name}"
}
результат будет:
Привет, Алексей
Важно, что форматтер создаётся один раз и затем используется повторно, что снижает накладные расходы при частых вызовах.
Подстановка в Globalize основана на именованных параметрах. Это означает, что порядок значений не имеет значения — важны только ключи.
Шаблон:
"Пользователь {name} вошёл в систему {system}"
Вызов:
formatter({ system: "CRM", name: "Ирина" });
Результат:
Пользователь Ирина вошёл в систему CRM
Если параметр отсутствует, поведение зависит от реализации шаблона: обычно подстановка остаётся пустой строкой или ключ сохраняется в исходном виде, что позволяет обнаруживать ошибки локализации на этапе тестирования.
Шаблоны поддерживают использование фигурных скобок только как
синтаксиса параметров. Для отображения символов { и
} в тексте требуется экранирование через двойные фигурные
скобки или использование ICU-совместимого синтаксиса.
Пример:
"Результат: {{value}}"
После обработки:
Результат: {value}
Такой механизм предотвращает конфликт между текстом и синтаксисом интерполяции.
Подстановка не ограничивается строками. Числовые значения автоматически приводятся к строковому виду с учётом локали, если применяется дополнительное форматирование.
Пример:
const formatter = globalize.messageFormatter("items");
formatter({ count: 5 });
Шаблон:
"У вас {count} сообщений"
Результат:
У вас 5 сообщений
При подключении дополнительных модулей возможно расширение логики форматирования, например, с учётом правил склонения.
Globalize позволяет комбинировать подстановку с форматированием чисел через отдельные API. Это особенно важно, когда значение должно быть представлено в локализованном виде.
const numberFormatter = globalize.numberFormatter();
const formatted = numberFormatter(12345.67);
Результат для русской локали:
12 345,67
Далее это значение может быть передано в сообщение:
greet({ amount: formatted });
Шаблон:
"Сумма операции: {amount}"
Такой подход разделяет ответственность: форматирование выполняется отдельно, а подстановка только собирает итоговую строку.
Одним из ключевых аспектов производительности является кэширование
форматтеров. Каждый вызов messageFormatter создаёт функцию,
которая может использоваться многократно.
const errorFormatter = globalize.messageFormatter("error");
function showError(code) {
return errorFormatter({ code });
}
При большом количестве операций это снижает нагрузку на парсер шаблонов и ускоряет генерацию интерфейсных сообщений.
Даже при простых шаблонах Globalize опирается на ICU MessageFormat, что позволяет расширять подстановку до более сложных конструкций без изменения базового API.
Пример с условной частью:
"{name} {gender, select, male {создал} female {создала} other {создал(а)}} запись"
Вызов:
formatter({ name: "Олег", gender: "male" });
Результат:
Олег создал запись
Хотя данный пример выходит за рамки простой подстановки, он демонстрирует совместимость базового механизма с расширенными правилами.
Если параметр не передан, библиотека не выполняет автоматическую генерацию ошибки. Вместо этого результат может содержать пустое место или исходный маркер.
Это поведение используется для выявления проблем локализации:
Шаблоны сообщений обычно группируются по доменам приложения:
{
"auth": {
"loginSuccess": "Добро пожаловать, {name}",
"loginError": "Ошибка входа для пользователя {name}"
}
}
Доступ к ним осуществляется через ключи:
globalize.messageFormatter("auth/loginSuccess");
Такой подход позволяет масштабировать локализацию без усложнения логики подстановки.
При интенсивной эксплуатации механизм подстановки значений становится частью критического пути рендеринга интерфейса. Поэтому важны следующие характеристики:
Эти принципы позволяют использовать Globalize в приложениях с высокой нагрузкой без деградации производительности при генерации текстовых сообщений.