Scribe

Перевод

Как работает перевод в Scribe: хэширование для отслеживания изменений, Gemini, проверка результатов, отчеты о стоимости и инструменты для ревью.

View as Markdown

Scribe переводит английский исходник на все остальные языки с помощью LLM (Gemini), а результаты сохраняет в SQLite. Вам не нужно редактировать файлы локализации, достаточно отредактировать английский текст, запустить scribe translate и закоммитить хранилище.

Что переводится

Для каждого документа переводчику отправляются ровно две вещи:

  1. Поля frontmatter, отмеченные как field.translatable(), в том числе вложенные в массивы и объекты.
  2. Тело MDX.

Всё остальное (field.structural(), связи, встроенные поля) копируется из английского документа при загрузке. Если включена опция slugStrategy: "localized", переводчик также генерирует URL (ASCII kebab-case, транслитерированный для нелатинских языков).

Язык, который вы еще не перевели, не вызывает ошибок при работе сайта: resolve() выдает наиболее подходящий перевод благодаря цепочке запасных вариантов (fallback) (например, pt-BR переключается на pt, а затем на язык по умолчанию). Это позволяет внедрять новые языки постепенно.

Отслеживание устаревших переводов

Каждый сохраненный перевод содержит SHA-256 хэш английского оригинала, на основе которого он был сделан. scribe translate переводит страницу заново, только если:

  • перевод для этого языка отсутствует (missing), или
  • английский оригинал изменился с момента последнего перевода (stale).

Редактирование структурного поля или записи _redirects.json не делает переводы устаревшими, так как эти поля не переводятся.

Проверка результатов

Перевод сохраняется только в том случае, если он проходит две проверки:

  1. Возвращенный MDX-код должен корректно парситься (после нормализации артефактов экранирования и кавычек в атрибутах JSX, с которыми модель иногда ошибается).
  2. Возвращенный frontmatter должен пройти валидацию по вашей полной схеме Zod.

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

Запуск

export GEMINI_API_KEY=...        # также читается из .env / .env.local

scribe status                     # покрытие по типам и языкам
scribe translate                  # интерактивное меню в терминале
scribe translate --locale fr de   # конкретные языки
scribe translate --preset active  # группа localePresets из конфигурации
scribe translate --type blog      # один тип контента (через запятую: --type blog,glossary)
scribe translate --slug my-post   # один документ
scribe translate --dry-run        # показать список задач + оценку токенов/стоимости, ничего не записывать
scribe translate --force          # перевести заново, даже если хэши совпадают
scribe translate --strategy missing-only   # пропустить устаревшие, заполнить только пропуски
scribe translate --batch          # принудительный пакетный режим (по умолчанию)
scribe translate --direct         # API-вызовы для каждой страницы, немедленный результат
scribe translate --resume         # возобновить ожидающие задачи, ничего нового не отправлять
scribe translate --concurrency 5  # параллельные запросы (только в режиме direct)
scribe translate --model gemini-3.1-pro

При запуске в терминале scribe translate отображает UI с прогрессом в реальном времени: статус пакетных задач, результаты по каждому элементу, количество токенов и ориентировочную стоимость в долларах США. Токены рассуждений (thinking tokens) включены в отчет, поэтому оценка совпадает с тем, что Google выставит в счете. Передайте --no-progress (или запустите в неинтерактивном режиме, например в CI) для простого построчного логирования.

--dry-run выводит список задач и ничего не записывает, сообщая примерное количество токенов и стоимость в долларах для каждого элемента и в целом. Расчет идет на основе реального промпта и объема английского текста. С флагом --batch учитывается пакетная скидка, так что вы можете заранее узнать стоимость реального запуска.

После этого закоммитьте .scribe/store.sqlite.

Пакетный режим и возобновление работы

По умолчанию весь список задач отправляется через Gemini Batch API, стоимость которого составляет 50% от стоимости прямых вызовов. Scribe заранее планирует каждый запрос (одна задача на модель, с разбивкой на части для очень больших списков), отправляет все задачи одновременно, затем опрашивает их вместе и сохраняет результаты по мере выполнения. Пакетные задачи обычно завершаются за несколько минут, но Google гарантирует выполнение в течение 24 часов, поэтому команда переходит в режим ожидания, а не транслирует результаты страница за страницей.

Каждая задача записывается в SQLite-хранилище до начала опроса вместе со снимком (снимок) английского оригинала. Это позволяет безопасно прерывать работу:

  • Выйдете во время опроса (Ctrl+C), и ничего не потеряется.
  • scribe translate --resume проверяет ожидающие задачи, принимает завершенные и не отправляет ничего нового.
  • Обычный запуск scribe translate также сначала подхватывает ожидающие задачи. Элементы, которые уже в работе, никогда не отправляются дважды.
  • Вы можете смело редактировать английскую страницу, пока её перевод находится в процессе. Результат будет сохранен для того снимка, с которого делался перевод, а при следующем запуске страница пометится как устаревшая.

Предпочитаете немедленные результаты для каждой страницы по полной цене? Используйте --direct, который выполняет отдельные API-запросы с параллелизмом --concurrency. В терминале интерактивное меню также предлагает этот выбор. Временные ошибки API (429, 5xx, обрывы сети) автоматически повторяются с экспоненциальной задержкой в обоих режимах.

Управление переводчиком

Встроенный промпт основан на транскреации, а не на дословном переводе. Модель пишет как местный копирайтер, создающий локализованную версию: она переосмысливает идиомы и игру слов, а не переводит их слово в слово, и применяет местные типографические правила (кавычки, апострофы, пробелы вокруг знаков препинания). Ваши context, rules и prompt накладываются поверх этой базы.

Настройки по умолчанию для всего проекта и переопределения для отдельных типов:

export default defineConfig({
  translate: {
    context: "MyBrand — это B2B SaaS. Никогда не переводите название бренда MyBrand.",
    rules: ["Сохраняйте точность чисел и статистики."],
  },
  types: [
    defineContentType({
      id: "blog",
      // ...
      translate: {
        rules: [
          "Сохраняйте все теги MDX/JSX-компонентов, пропсы и URL в точности.",
          "Переводите текст ссылок, никогда не меняйте пути href.",
        ],
      },
    }),
  ],
});
ОпцияОбласть примененияОписание
contextпроект + типКонтекст бренда/предметной области добавляется в начало каждого запроса (контексты проекта и типа объединяются).
rulesпроект + типДополнительные правила, добавляемые к значениям по умолчанию.
promptпроект или типДополнительные инструкции по локализации, добавляемые перед указанием целевого языка (название и код языка добавляются всегда).
defaultModel / modelпроект / типИдентификатор модели Gemini. По умолчанию: gemini-3.1-pro (также можно переопределить через переменную окружения PROSE_GEMINI_MODEL или --model).

Встроенные правила (применяются всегда) включают: не переводить названия брендов (если у них нет устоявшегося названия на целевом рынке), возвращать MDX с настоящими переносами строк (а не с экранированным \n) и исправлять кавычки в атрибутах JSX, когда значения содержат двойные кавычки.

Просмотр переводов

scribe history blog my-post fr    # история снимков (снимок) оригинала для одной страницы
scribe studio                     # веб-интерфейс (только для чтения) на порту :3600

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

Наборы языков

Для постепенного внедрения можно объединять языки в группы в конфигурации и запускать перевод с помощью --preset:

localePresets: {
  active: ["fr", "es", "ja"],
  ultraLight: ["fr"],
}
scribe translate --preset ultraLight
Перевод · Scribe