Как это работает

@lingo.dev/compiler превращает ваше React-приложение в многоязычное на этапе сборки с помощью интеллектуального анализа кода и AI-перевода.

Трансформация на этапе сборки

Обычные i18n-библиотеки (i18next, react-intl) работают во время выполнения — они подгружают переводы, подставляют значения и форматируют сообщения прямо во время работы приложения. Это увеличивает размер бандла, добавляет нагрузку на выполнение и усложняет проект.

@lingo.dev/compiler работает иначе: он преобразует ваш код на этапе сборки. Ваши React-компоненты остаются чистыми, а переводы заранее компилируются в оптимизированные бандлы.

Результат: Нулевая нагрузка во время выполнения, меньший размер бандлов и отсутствие ручного управления ключами переводов.

Как это устроено

1. Анализ AST

Компилятор использует Babel для разбора вашего React-кода в абстрактное синтаксическое дерево (AST). Он проходит по вашему JSX и находит переводимый контент:

  • Текстовые узлы (<p>Hello</p>)
  • Строковые атрибуты (<img alt="Logo" />)
  • Текст в шаблонных выражениях (<p>Hello {name}</p>)

Компилятор понимает границы React-компонентов и сохраняет контекст для точных переводов. Технические идентификаторы, фрагменты кода и непереводимые элементы автоматически фильтруются.

2. Извлечение контента

Для каждой переводимой строки компилятор:

  • Генерирует стабильный идентификатор на основе хеша
  • Сохраняет контекст компонента (файл, местоположение, окружающие элементы)
  • Извлекает структуру rich text (обрабатывает вложенные элементы вроде <strong> и <em>)
  • Сохраняет плейсхолдеры для интерполяции

Эти метаданные хранятся в .lingo/metadata.json — версионном файле, который отслеживает весь переводимый контент вашего приложения.

3. Генерация переводов

Во время разработки сервер переводов обрабатывает переводы по запросу:

  • Режим псевдоперевода (по умолчанию): мгновенно создает фейковые переводы — удобно, чтобы увидеть, что переводится, без затрат на API
  • Режим реального перевода: обращается к вашему LLM-провайдеру (Lingo.dev Engine или напрямую к LLM)

Сервис перевода не хранит состояние и устойчив к частичным сбоям — если некоторые переводы не удались, всё равно используются кэшированные переводы.

4. Внедрение кода

Компилятор внедряет обращения к переводам прямо в ваш JSX:

// Your source code
<p>Hello {name}</p>

// Transformed code (simplified)
<p>{t('abc123', { name })}</p>

Функция t() оптимизирована и внедряется автоматически. Она выполняет поиск по хэшу в заранее загруженных словарях переводов.

5. Оптимизация бандла

Во время сборки:

  • Создаются бандлы для каждой локали
  • Включаются только используемые переводы
  • Неиспользуемые переводы удаляются (dead code elimination)
  • Словари оптимизируются для каждого компонента (tree-shaking)

Рабочий процесс разработки

Режим разработки

{
  dev: {
    usePseudotranslator: true,
  }
}

Когда вы запускаете npm run dev:

  1. Компилятор запускает сервер переводов (автоматически ищет порты 60000-60099)
  2. Ваше приложение отправляет запросы на сервер для получения переводов
  3. Псевдопереводчик мгновенно генерирует фейковые переводы
  4. Переводы кэшируются в .lingo/metadata.json
  5. HMR работает как обычно — состояние сохраняется

Виджет для разработки (если включён) позволяет редактировать переводы прямо в браузере и сразу видеть изменения.

Режим продакшена

{
  buildMode: "cache-only",
}

Когда вы запускаете npm run build:

  1. Сервер переводов не запускается
  2. Используются только кэшированные переводы из .lingo/metadata.json
  3. Если каких-то переводов не хватает, сборка падает с понятной ошибкой
  4. Нет API-запросов — API-ключи не нужны

Почему только кэш? В продакшене важна детерминированность сборки. Переводы должны генерироваться в CI (где есть API-ключи), а не во время финальной сборки.

Рекомендуемый рабочий процесс

Локальная разработка:

  • Используйте псевдопереводчик
  • Быстрая обратная связь
  • Нет затрат на API

CI/CD:

{
  buildMode: "translate",
  dev: {
    usePseudotranslator: false,
  }
}
  • Генерируйте настоящие переводы
  • Запускайте один раз на деплой
  • Коммитьте изменения в .lingo/

Продакшн-сборка:

{
  buildMode: "cache-only",
}
  • Используйте заранее сгенерированные переводы
  • API-ключи не требуются
  • Быстрая, детерминированная сборка

Архитектура

Компилятор построен на чётком разделении ответственности:

Менеджер метаданных

  • Операции CRUD для .lingo/metadata.json
  • Потокобезопасность с блокировкой файлов
  • Идентификаторы переводов на основе хэшей

Сервис переводов

  • Оркестрация процесса перевода
  • Управление стратегией кэширования
  • Обработка частичных сбоев
  • Возвращает как успешные переводы, так и ошибки

Трансляторы (без состояния)

  • Псевдопереводчик: мгновенные фейковые переводы
  • LCP Translator: интеграция с движком Lingo.dev
  • LLM Translators: прямая интеграция с провайдерами
  • Нет встроенного кэширования — этим занимается сервисный слой

Сервер переводов

  • HTTP-сервер для разработки
  • Поддержка WebSocket для обновления виджетов в реальном времени
  • Автоматическое управление портами
  • Обработка пакетных запросов

См. документацию по архитектуре исходного кода для подробностей реализации.

Интеграция с фреймворками

Next.js

Компилятор интегрируется через обёртку withLingo():

  • Поддержка Webpack и Turbopack
  • Работает с React Server Components
  • Асинхронная конфигурация для ленивой загрузки плагинов
  • Автоматическая маршрутизация по локали (если настроено)

Vite

Компилятор интегрируется через lingoCompilerPlugin:

  • На базе unplugin (работает с Vite, Webpack, Rollup)
  • Полная поддержка HMR
  • Эффективная интеграция с dev-сервером
  • Автоматическая генерация виртуальных модулей

Частые вопросы

Работает ли это с Server Components? Да. В Next.js компилятор преобразует и серверные, и клиентские компоненты. Поиск переводов работает изоморфно.

А как насчёт code splitting? Переводы автоматически разделяются вместе с вашими компонентами. Каждый чанк содержит только нужные ему переводы.

Как кэшируются переводы? Все переводы хранятся в .lingo/metadata.json. Этот файл находится под версионным контролем и служит кэшем переводов. Компилятор использует хэши содержимого — только новый или изменённый текст отправляется на повторный перевод.

Что делать, если перевод не удался? Сервис возвращает частичные результаты. Успешные переводы кэшируются и используются, а ошибки логируются с контекстом для отладки. Ваше приложение не ломается — оно использует кэшированные переводы или исходный текст.

Могу ли я увидеть преобразованный код? Да. В выходных файлах сборки ищите преобразованные файлы. Преобразования минимальны — это просто вызовы функций t() с поиском по хешу.

Дальнейшие шаги