В реальных приложениях интернационализация редко ограничивается базовыми форматами чисел, дат и сообщений. Даже при использовании мощных библиотек, таких как Globalize, возникает необходимость в расширении стандартных средств форматирования под доменную логику: отображение финансовых значений в специфическом виде, локализованные идентификаторы, комбинированные строки, форматирование кодов, артикулов, рейтингов и других сущностей, которые не укладываются в стандартные CLDR-паттерны.
Кастомные форматтеры в такой архитектуре выступают прослойкой между универсальными механизмами Globalize и прикладной логикой приложения. Они не заменяют встроенные функции, а композиционно расширяют их, обеспечивая единый слой преобразования данных в локализованное представление.
Globalize предоставляет набор функций для форматирования чисел, дат и сообщений, опираясь на CLDR-данные. Однако прикладные форматтеры обычно строятся поверх этих функций.
Основная идея заключается в том, что кастомный форматтер — это функция, которая:
Такой подход обеспечивает разделение ответственности: Globalize отвечает за корректность локали, а прикладной слой — за смысловое представление данных.
Наиболее устойчивый способ построения кастомных форматтеров — композиция. Вместо создания монолитных функций формируется набор небольших преобразователей.
Пример логики композиции:
formatNumber;Даже без привязки к конкретному API Globalize, архитектурный паттерн остается одинаковым:
Числовые значения чаще всего требуют расширения стандартного форматирования.
Типичные сценарии:
Логика строится поверх Globalize.formatNumber, который
использует CLDR-правила.
Кастомный слой может добавлять:
kg, pts, %);Важно, что сам Globalize не теряет контроль над локалью, а только предоставляет основу для корректного представления чисел.
Работа с датами требует особого уровня абстракции, поскольку формат зависит от:
Кастомные форматтеры поверх Globalize часто реализуют:
В таких случаях Globalize.formatDate используется как
базовый слой, а поверх него добавляется логика интерпретации:
Одним из ключевых механизмов расширения является система сообщений Globalize. Она позволяет определять шаблоны строк с параметрами и правилами выбора формы.
Кастомные форматтеры сообщений строятся вокруг:
Композиция выглядит следующим образом:
Это позволяет отделить текстовую структуру от логики форматирования данных.
Хотя Globalize не требует формальной регистрации пользовательских форматтеров, в архитектуре приложения обычно создается слой абстракции:
Такой слой решает несколько задач:
Пример структуры:
formatters/number.jsformatters/date.jsformatters/money.jsformatters/custom.jsКаждый модуль использует Globalize внутри, но наружу предоставляет стабильный интерфейс.
Кастомные форматтеры тесно связаны с понятием текущей локали. В Globalize каждая операция форматирования зависит от установленной локали.
Поэтому прикладной слой часто инкапсулирует:
Это критически важно, поскольку создание форматтера может быть дорогостоящей операцией при частых вызовах.
При большом количестве вызовов кастомных форматтеров важную роль играет оптимизация.
Основные стратегии:
Кастомные форматтеры особенно выигрывают от кеширования, так как часто представляют собой композицию нескольких вызовов Globalize.
Кастомные форматтеры можно разделить на два уровня:
Декоративные форматтеры:
Доменные форматтеры:
Globalize используется как нижний уровень, а оба типа форматтеров строятся поверх него.
В сложных интерфейсах часто требуется форматирование объектов:
В таких случаях кастомный форматтер превращается в pipeline:
Это позволяет поддерживать единый стиль отображения данных в разных частях приложения.
Кастомные форматтеры должны учитывать нестабильность данных:
Поэтому часто внедряется fallback-логика:
Globalize в этом случае выступает как строгий слой, а кастомный форматтер обеспечивает устойчивость.
При росте приложения система кастомных форматтеров эволюционирует в отдельный слой инфраструктуры:
Такая структура позволяет:
В современных приложениях кастомные форматтеры часто используются в связке с UI-компонентами:
В этом контексте форматтеры становятся частью представления данных, но остаются независимыми от UI-логики.
Globalize обеспечивает корректность локализации, а кастомный слой обеспечивает согласованность отображения во всех компонентах.