CLI инструменты formatjs

CLI-инструменты экосистемы FormatJS представляют собой набор утилит для автоматизации интернационализации приложений: извлечения сообщений, подготовки переводов, валидации ICU-строк и сборки локализационных артефактов. Основной пакет CLI — @formatjs/cli, который объединяет команды для работы с сообщениями в исходном коде и JSON-файлах переводов.


Архитектура CLI и назначение компонентов

CLI-инструменты построены вокруг принципа обработки ICU Message Format строк и статического анализа кода.

Ключевые задачи:

  • извлечение строк локализации из исходников;
  • нормализация и дедупликация сообщений;
  • проверка корректности ICU-синтаксиса;
  • генерация JSON-файлов переводов;
  • компиляция сообщений в оптимизированный формат для runtime.

CLI работает поверх AST (Abstract Syntax Tree), анализируя JavaScript/TypeScript код и JSX.


Основной пакет @formatjs/cli

Пакет предоставляет единый бинарный интерфейс formatjs, включающий несколько команд.

Установка:

npm install -D @formatjs/cli

После установки доступна команда:

npx formatjs

Команда extract

Команда extract используется для извлечения сообщений из исходного кода.

Базовый сценарий:

npx formatjs extract "src/**/*.{js,jsx,ts,tsx}" --out-file messages.json

Принцип работы

  • анализируются вызовы defineMessages, formatMessage, <FormattedMessage>;
  • извлекаются id, defaultMessage, description;
  • формируется единый JSON-каталог сообщений.

Пример входного кода

import { defineMessages } from 'react-intl';

const messages = defineMessages({
  title: {
    id: 'app.title',
    defaultMessage: 'Главная страница',
    description: 'Заголовок главного экрана'
  }
});

Результат extract

{
  "app.title": {
    "defaultMessage": "Главная страница",
    "description": "Заголовок главного экрана"
  }
}

Поддержка glob-паттернов и фильтрации

CLI поддерживает glob-выражения для точного контроля над областями анализа:

npx formatjs extract "src/components/**/*.{ts,tsx}" --out-file out.json

Возможна фильтрация:

  • исключение директорий node_modules
  • ограничение по расширениям
  • обработка monorepo-структур

Команда compile

Команда compile преобразует JSON переводов в оптимизированный формат, пригодный для быстрого выполнения в runtime.

npx formatjs compile messages.json --out-file compiled.json

Назначение компиляции

На этапе компиляции:

  • ICU-строки парсятся в AST;
  • удаляются избыточные метаданные;
  • формируется структура, оптимизированная для IntlMessageFormat;
  • ускоряется интерпретация сообщений в браузере.

ICU Message Format и роль CLI

CLI тесно связан с ICU Message Format, который является стандартом для интернационализации.

Пример ICU строки:

У вас {count, plural, one {# сообщение} few {# сообщения} many {# сообщений}}

CLI проверяет:

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

Валидация сообщений

CLI включает режим проверки, предотвращающий ошибки локализации до runtime.

Пример проверки:

npx formatjs compile messages.json --ast --strict

Проверяются:

  • отсутствующие переменные;
  • несовпадение ICU-синтаксиса;
  • некорректные plural категории;
  • дублирующиеся ID.

Babel-интеграция и связка с CLI

Хотя CLI и Babel-плагин решают разные задачи, они часто используются совместно.

  • Babel-плагин извлекает сообщения на уровне трансформации кода;
  • CLI выполняет batch-операции над уже собранными данными.

Типичный pipeline:

  1. Babel обрабатывает код;
  2. CLI извлекает сообщения;
  3. переводы обновляются;
  4. CLI компилирует результаты.

Работа в monorepo

CLI поддерживает масштабные репозитории с несколькими пакетами.

Особенности:

  • объединение сообщений из разных пакетов;
  • единый messages.json;
  • раздельная компиляция по namespace.

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

packages/
  app/
  ui/
  shared/

Команда:

npx formatjs extract "packages/*/src/**/*.{ts,tsx}" --out-file messages.json

Сортировка и дедупликация

CLI автоматически обрабатывает:

  • повторяющиеся id;
  • одинаковые defaultMessage;
  • конфликтующие описания.

При необходимости используется ручная стратегия нормализации через pre/post-processing скрипты.


JSON-структуры и формат вывода

CLI поддерживает несколько форматов вывода:

  • flat JSON
  • nested JSON
  • grouped by namespace

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

{
  "home.title": "Главная",
  "home.subtitle": "Добро пожаловать"
}

Пример nested:

{
  "home": {
    "title": "Главная",
    "subtitle": "Добро пожаловать"
  }
}

Производительность CLI

CLI оптимизирован для больших кодовых баз:

  • потоковая обработка файлов;
  • параллельный разбор AST;
  • кэширование результатов парсинга;
  • минимизация повторного обхода дерева.

В проектах с десятками тысяч сообщений основная нагрузка приходится на:

  • парсинг TypeScript AST;
  • обработку JSX-структур;
  • ICU-анализ сложных plural-форм.

Интеграция с CI/CD

CLI используется в пайплайнах автоматизации локализации.

Типовые сценарии:

  • проверка новых сообщений при pull request;
  • генерация обновлённых файлов переводов;
  • валидация ICU-форматов перед деплоем.

Пример CI-команды:

npx formatjs extract "src/**/*.{ts,tsx}" --out-file messages.json
npx formatjs compile messages.json --out-file compiled.json

Работа с ошибками CLI

CLI возвращает структурированные ошибки:

  • синтаксические ошибки ICU;
  • отсутствующие ключи интерполяции;
  • некорректные plural формы;
  • проблемы AST-парсинга.

Пример ошибки:

Error: Missing value for placeholder "count"
at message "app.items"

Расширяемость CLI

CLI может быть расширен через:

  • кастомные парсеры;
  • плагины трансформации AST;
  • внешние скрипты обработки JSON;
  • интеграцию с i18n backend-системами.

Расширения позволяют адаптировать инструмент под:

  • специфические форматы переводов;
  • внутренние стандарты сообщений;
  • нестандартные ICU-диалекты.

Использование в TypeScript-проектах

CLI корректно обрабатывает TypeScript:

  • типизированные сообщения;
  • интерфейсы MessageDescriptor;
  • enum-идентификаторы сообщений.

Пример:

const messages: Record<string, MessageDescriptor> = {
  welcome: {
    id: 'welcome',
    defaultMessage: 'Привет'
  }
};

Обработка JSX-компонентов

CLI извлекает сообщения из React JSX:

<FormattedMessage
  id="button.save"
  defaultMessage="Сохранить"
/>

и преобразует их в единый каталог сообщений.


Стратегии организации переводов

CLI поддерживает различные подходы:

  • ключ-значение (id → string);
  • ICU-объекты;
  • namespace-based структура;
  • feature-based локализация.

Каждая стратегия влияет на формат output и способ компиляции.


Совместимость с runtime

CLI-результаты используются вместе с:

  • react-intl;
  • intl-messageformat;
  • браузерным Intl API.

Компиляция снижает overhead при выполнении форматирования строк, особенно при множественных plural и select-конструкциях.


Масштабирование локализационной системы

CLI-инструменты становятся центральным звеном при росте приложения:

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