Добавление кастомных форматтеров

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

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


Базовый подход к расширению форматирования

Globalize предоставляет набор функций для форматирования чисел, дат и сообщений, опираясь на CLDR-данные. Однако прикладные форматтеры обычно строятся поверх этих функций.

Основная идея заключается в том, что кастомный форматтер — это функция, которая:

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

Такой подход обеспечивает разделение ответственности: Globalize отвечает за корректность локали, а прикладной слой — за смысловое представление данных.


Композиция форматтеров как основа расширяемости

Наиболее устойчивый способ построения кастомных форматтеров — композиция. Вместо создания монолитных функций формируется набор небольших преобразователей.

Пример логики композиции:

  • форматирование числа через formatNumber;
  • добавление единиц измерения;
  • постобработка строки (разделители, суффиксы, префиксы);
  • применение бизнес-правил отображения.

Даже без привязки к конкретному API Globalize, архитектурный паттерн остается одинаковым:

  • базовый форматтер отвечает за локаль;
  • обертка отвечает за смысл.

Кастомные форматтеры чисел

Числовые значения чаще всего требуют расширения стандартного форматирования.

Типичные сценарии:

  • отображение валюты с нестандартными символами;
  • округление по доменным правилам (например, до 0.5 или до целого);
  • форматирование рейтингов;
  • отображение больших чисел в сокращённом виде.

Логика строится поверх Globalize.formatNumber, который использует CLDR-правила.

Кастомный слой может добавлять:

  • постфиксы (kg, pts, %);
  • преобразование масштаба (тысячи, миллионы);
  • условное форматирование (например, отрицательные значения как “—”).

Важно, что сам Globalize не теряет контроль над локалью, а только предоставляет основу для корректного представления чисел.


Форматирование дат и временных интервалов

Работа с датами требует особого уровня абстракции, поскольку формат зависит от:

  • локали;
  • контекста отображения (краткий/полный формат);
  • доменной логики (например, бизнес-часы или дедлайны).

Кастомные форматтеры поверх Globalize часто реализуют:

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

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

  • “сегодня / вчера / завтра”;
  • “через N дней”;
  • “в пределах недели”.

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

Одним из ключевых механизмов расширения является система сообщений Globalize. Она позволяет определять шаблоны строк с параметрами и правилами выбора формы.

Кастомные форматтеры сообщений строятся вокруг:

  • параметризации строк;
  • выбора формы (plural rules);
  • вставки уже отформатированных значений.

Композиция выглядит следующим образом:

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

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


Регистрация пользовательских форматтеров в прикладном слое

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

  • реестр форматтеров;
  • фабрика форматирования;
  • контекст локали.

Такой слой решает несколько задач:

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

Пример структуры:

  • formatters/number.js
  • formatters/date.js
  • formatters/money.js
  • formatters/custom.js

Каждый модуль использует Globalize внутри, но наружу предоставляет стабильный интерфейс.


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

Кастомные форматтеры тесно связаны с понятием текущей локали. В Globalize каждая операция форматирования зависит от установленной локали.

Поэтому прикладной слой часто инкапсулирует:

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

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


Кэширование форматтеров и оптимизация

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

Основные стратегии:

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

Кастомные форматтеры особенно выигрывают от кеширования, так как часто представляют собой композицию нескольких вызовов Globalize.


Декоративные и доменные форматтеры

Кастомные форматтеры можно разделить на два уровня:

Декоративные форматтеры:

  • добавляют визуальные элементы;
  • изменяют форму представления без изменения смысла;
  • например: добавление символов валют, скобок, префиксов.

Доменные форматтеры:

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

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


Составные форматтеры для сложных структур данных

В сложных интерфейсах часто требуется форматирование объектов:

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

В таких случаях кастомный форматтер превращается в pipeline:

  • извлечение полей объекта;
  • форматирование каждого поля через Globalize;
  • сборка итоговой строки или структуры.

Это позволяет поддерживать единый стиль отображения данных в разных частях приложения.


Обработка ошибок и fallback-логика

Кастомные форматтеры должны учитывать нестабильность данных:

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

Поэтому часто внедряется fallback-логика:

  • использование дефолтной локали;
  • возврат исходного значения;
  • безопасное форматирование через try/catch на уровне обертки.

Globalize в этом случае выступает как строгий слой, а кастомный форматтер обеспечивает устойчивость.


Масштабирование системы форматтеров

При росте приложения система кастомных форматтеров эволюционирует в отдельный слой инфраструктуры:

  • централизованный registry;
  • фабрики форматтеров;
  • изолированные модули по доменам;
  • интеграция с state management.

Такая структура позволяет:

  • переиспользовать форматтеры;
  • тестировать их независимо;
  • заменять реализацию без изменения UI-слоя.

Интеграция с компонентной архитектурой

В современных приложениях кастомные форматтеры часто используются в связке с UI-компонентами:

  • отображение таблиц;
  • списки транзакций;
  • интерфейсы аналитики.

В этом контексте форматтеры становятся частью представления данных, но остаются независимыми от UI-логики.

Globalize обеспечивает корректность локализации, а кастомный слой обеспечивает согласованность отображения во всех компонентах.