Процессы и статусы

В экосистеме FormatJS процесс интернационализации представляет собой последовательную цепочку этапов, в которой текстовые сообщения проходят путь от исходного кода до локализованного представления в интерфейсе. Каждый этап сопровождается собственным состоянием (статусом), влияющим на поведение системы во время сборки и выполнения.


Статусы сообщений на этапе разработки

На уровне исходного кода сообщения в FormatJS представлены через MessageDescriptor. Это абстракция, описывающая текст, который будет локализован.

{
  id: "user.greeting",
  defaultMessage: "Hello, {name}",
  description: "Greeting message on dashboard"
}

На этом этапе сообщения находятся в состоянии необработанного описания. Они ещё не участвуют в локализации, но уже могут быть:

  • извлечены инструментами
  • валидированы
  • помечены как отсутствующие переводы

Основные статусы на уровне исходников

1. Определено (Defined) Сообщение существует в коде как MessageDescriptor.

2. Извлекается (Extracted) Сообщение обнаружено Babel-плагином babel-plugin-formatjs или CLI-инструментом @formatjs/cli.

3. Отсутствует перевод (Missing Translation) Сообщение присутствует в коде, но отсутствует в наборе локализованных сообщений.

4. Неиспользуемое (Unused) Перевод присутствует в словаре, но не встречается в исходном коде.


Процесс извлечения сообщений

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

Основной инструмент — Babel-плагин:

npm install babel-plugin-formatjs

Пример конфигурации:

{
  "plugins": [
    ["formatjs", {
      "idInterpolationPattern": "[sha512:contenthash:base64:6]"
    }]
  ]
}

Статусы на этапе извлечения

Во время анализа кода каждое сообщение проходит состояния:

  • Найдено AST-анализом
  • Преобразовано в MessageDescriptor
  • Сериализовано в JSON
  • Добавлено в каталог сообщений

Пример результата извлечения:

{
  "user.greeting": {
    "defaultMessage": "Hello, {name}",
    "description": "Greeting message on dashboard"
  }
}

Статус компиляции сообщений

После извлечения сообщения проходят этап компиляции. В FormatJS используется intl-messageformat, который преобразует ICU-строки в исполняемые функции форматирования.

import { createIntl, createIntlCache } from 'react-intl';

const cache = createIntlCache();

const intl = createIntl({
  locale: 'en',
  messages: {
    "user.greeting": "Hello, {name}"
  }
}, cache);

На этом этапе формируется промежуточное состояние:

Статусы компиляции

1. Не скомпилировано (Raw Message) Строка хранится как текст ICU-сообщения.

2. Скомпилировано (Compiled Message) ICU-синтаксис преобразован в функцию форматирования.

3. Оптимизировано (Optimized AST) Сообщение представлено в виде AST-дерева для быстрого вычисления.


Статусы выполнения (runtime)

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

intl.formatMessage(
  { id: "user.greeting", defaultMessage: "Hello, {name}" },
  { name: "Alex" }
);

Основные runtime-статусы

1. Разрешено (Resolved) Сообщение найдено в текущей локали.

2. Фолбэк (Fallback) Сообщение отсутствует в текущей локали, используется defaultMessage или fallback locale.

3. Не найдено (Missing Message) Нет ни перевода, ни defaultMessage. Может быть выброшено предупреждение.

4. Отформатировано (Formatted) ICU-строка успешно преобразована в итоговый текст.


Статусы локали и переключения языка

FormatJS поддерживает динамическую смену локали. Это влияет на весь процесс форматирования.

Состояния локали

1. Инициализирована (Initialized Locale) Установлена начальная локаль приложения.

2. Загружается (Loading Locale Data) Асинхронная загрузка переводов.

3. Активна (Active Locale) Локаль используется для форматирования сообщений.

4. Частично загружена (Partially Loaded) Доступны не все сообщения или не все сегменты ICU данных (числа, даты, плурализация).

Пример загрузки:

async function loadLocale(locale) {
  const messages = await fetch(`/i18n/${locale}.json`).then(r => r.json());

  return {
    locale,
    messages
  };
}

Статусы ICU-форматирования

FormatJS использует ICU Message Syntax, которая поддерживает сложные конструкции: множественное число, выбор, вложенные параметры.

Статусы ICU-обработки

1. Парсинг (Parsing) Строка преобразуется в AST.

2. Валидация (Validation) Проверка корректности ICU-синтаксиса.

3. Интерполяция (Interpolation) Подстановка переменных.

4. Выбор ветки (Selection) Определение plural/sel ect формы.

Пример:

intl.formatMessage(
  {
    id: "cart.items",
    defaultMessage: "You have {count, plural, one {# item} other {# items}}"
  },
  { count: 3 }
);

Статусы pluralization и селекторов

Plural и select выражения формируют отдельный слой состояний внутри ICU.

Plural-статусы

  • one
  • few
  • many
  • other
  • zero (в некоторых локалях)

Система выбирает активную ветку на основе правил CLDR.

Select-статусы

{ gender, select,
  male {He}
  female {She}
  other {They}
}

Состояния:

  • ключ найден
  • ключ не найден → fallback на other
  • некорректный тип → ошибка форматирования

Статусы React-слоя (react-intl)

В react-intl сообщения проходят через React lifecycle.

Основные состояния

1. Provider не инициализирован IntlProvider отсутствует, форматирование невозможно.

2. Provider активен Контекст доступен через useIntl().

3. Перерендер при смене локали Все компоненты, использующие форматирование, обновляются.

import { IntlProvider, useIntl } fr om 'react-intl';

function App() {
  return (
    <IntlProvider locale="en" messages={{}}>
      <Page />
    </IntlProvider>
  );
}

Статусы кеширования

FormatJS использует кеширование для ускорения форматирования.

Состояния кеша

1. Пустой кеш Первый запуск форматирования.

2. Частично заполненный кеш Часть сообщений уже скомпилирована.

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


Статусы ошибок и деградации

Система обработки ошибок в FormatJS определяет несколько уровней деградации.

Типовые состояния ошибок

1. Invalid ICU Syntax Ошибка парсинга сообщения.

2. Missing Variable Не передан параметр форматирования.

3. Unknown Locale Data Отсутствуют данные CLDR.

4. Fallback Activation Система переключается на резервную локаль.


Статусы сериализации и сборки

При использовании CI/CD и @formatjs/cli сообщения проходят этап сборки.

npx formatjs compile

Статусы сборки

  • исходный каталог сообщений
  • нормализованный JSON
  • минифицированные ключи
  • hashed id (опционально)

Пример трансформации:

"user.greeting" -> "a1b2c3"

Статусы совместимости локалей

FormatJS зависит от данных CLDR, и локали могут находиться в разных состояниях готовности.

Возможные состояния

  • полностью поддерживается
  • частично поддерживается (нет plural rules)
  • отсутствует (fallback на en)

Итоговая модель состояний

В рамках FormatJS можно выделить многослойную модель статусов:

  • статусы исходного кода (MessageDescriptor)
  • статусы извлечения (AST → JSON)
  • статусы компиляции (ICU → function)
  • runtime-статусы (resolve/fallback/error)
  • статусы локалей (loading/active/fallback)
  • статусы ICU-выражений (parse/select/interpolate)
  • статусы кеша и оптимизации

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