Перевод
Как работает перевод в Scribe: хэширование для отслеживания изменений, Gemini, проверка результатов, отчеты о стоимости и инструменты для ревью.
View as MarkdownScribe переводит английский исходник на все остальные языки с помощью LLM (Gemini), а результаты сохраняет в SQLite. Вам не нужно редактировать файлы локализации, достаточно отредактировать английский текст, запустить scribe translate и закоммитить хранилище.
Что переводится
Для каждого документа переводчику отправляются ровно две вещи:
- Поля frontmatter, отмеченные как
field.translatable(), в том числе вложенные в массивы и объекты. - Тело MDX.
Всё остальное (field.structural(), связи, встроенные поля) копируется из английского документа при загрузке. Если включена опция slugStrategy: "localized", переводчик также генерирует URL (ASCII kebab-case, транслитерированный для нелатинских языков).
Язык, который вы еще не перевели, не вызывает ошибок при работе сайта: resolve() выдает наиболее подходящий перевод благодаря цепочке запасных вариантов (fallback) (например, pt-BR переключается на pt, а затем на язык по умолчанию). Это позволяет внедрять новые языки постепенно.
Отслеживание устаревших переводов
Каждый сохраненный перевод содержит SHA-256 хэш английского оригинала, на основе которого он был сделан. scribe translate переводит страницу заново, только если:
- перевод для этого языка отсутствует (missing), или
- английский оригинал изменился с момента последнего перевода (stale).
Редактирование структурного поля или записи _redirects.json не делает переводы устаревшими, так как эти поля не переводятся.
Проверка результатов
Перевод сохраняется только в том случае, если он проходит две проверки:
- Возвращенный MDX-код должен корректно парситься (после нормализации артефактов экранирования и кавычек в атрибутах JSX, с которыми модель иногда ошибается).
- Возвращенный 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