Локализация

Статья обновлена 22 сентября 2026 г.

Команда yfm translate переводит документацию проекта с одного языка на другие. Текст извлекается из разметки, переводится выбранным способом и собирается обратно в файлы - структура проекта, разметка и код при этом сохраняются.

О том, как устроен проект с несколькими языковыми версиями, читайте в статье Многоязычные проекты.

Способы перевода

Машинный перевод

Перевод через Yandex Translate - способ по умолчанию, работает без опции --provider. Самый быстрый вариант, но результат обычно требует вычитки. Подробности - в статье Машинный перевод.

AI-перевод

Перевод большими языковыми моделями: провайдеры yandexgpt, openai, openrouter и anthropic. Поддерживает глоссарии, промпты, кэш переводов и оценку качества второй моделью. Подробности - в статье AI-перевод.

Обмен XLIFF с CAT-системами

Если перевод выполняют люди в системе автоматизированного перевода (Computer Assisted Translation, или CAT), подкоманда extract выгружает текст проекта в *.xliff файлы, а compose собирает переведенные файлы обратно в документацию. Подробности - в статье Обмен XLIFF с CAT-системами.

Как устроен перевод

Каждый документ разбивается на сегменты - предложения, заголовки, ячейки таблиц. Разметка YFM, HTML-теги, код и Liquid-конструкции на перевод не отправляются: они остаются в «скелете» документа, и после перевода сегменты подставляются обратно на свои места. Повторяющиеся сегменты переводятся один раз.

Файлы каждого языка лежат в своей языковой папке: исходные - например, в ru/, результат перевода - в папке целевого языка, например en/. Указывать языковую папку в путях не нужно - она добавляется автоматически по значениям --source и --target.

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

По умолчанию на перевод попадают файлы {lang}/**/*.@(md|yaml|json):

  • *.md - текст YFM-разметки;
  • *.yaml и *.json - только поля, описанные в схеме перевода.

Схемы перевода YAML и JSON

Схема определяет, какие поля структурированного файла содержат переводимый текст. Встроенные схемы есть для:

Блоки ::: page-constructor внутри .md тоже разбираются по схеме: на перевод уходят только текстовые поля блоков, YAML-структура блока остается в скелете документа и возвращается в файл без изменений.

Собственные схемы можно подключить опцией --schema подкоманды extract.

Общие параметры

Эти параметры работают во всех способах перевода. Специфичные параметры описаны в статьях про машинный перевод, AI-перевод и обмен XLIFF.

Параметр

Описание

--source, -sl

Язык оригинала в формате ISO 639-1: ru или ru-RU. Обязательный

--target, -tl

Язык перевода: en или en-US. Можно указать несколько раз - перевод выполнится на каждый язык

--input, -i

Путь до корня проекта или до конкретного файла в проекте. По умолчанию - директория запуска команды

--output, -o

Путь до корня проекта, в который нужно сохранить перевод. По умолчанию совпадает с input

--files

Пути к файлам для перевода (относительно input) или путь к файлу со списком. Можно повторять. Если параметр задан, --include и --exclude игнорируются

--include

Правило отбора файлов: путь, glob-шаблон или файл со списком. Можно повторять. Заданные правила заменяют правило по умолчанию; чтобы вернуть его, добавьте отдельное правило --include ...

--exclude

Правило исключения файлов: путь или glob-шаблон. Применяется после --include. Можно повторять

--config, -c

Путь к файлу конфигурации. По умолчанию - .yfm в корне проекта

Параметры перевода через провайдера

Работают при переводе через Yandex Translate и AI-провайдеров, но не в подкомандах extract и compose.

Параметр

Описание

--provider

Система перевода: yandex (по умолчанию), yandexgpt, openai, openrouter или anthropic

--include-vcs-diff

Добавляет к переводу файлы, измененные в рабочей копии git или arc. Директория input должна находиться внутри репозитория.

Необязательное значение - реф, относительно которого считается diff (по умолчанию HEAD). Диапазоны в git-синтаксисе (a..b, a...b) работают для обеих систем. Неотслеживаемые файлы включаются всегда.

Комбинируется с --include: переводятся файлы из обоих наборов. Если изменений нет, команда успешно завершается без перевода

--vars, -v

Переменные сборки в формате JSON. Команда translate игнорирует presets.yaml - переменные передаются только этой опцией

--dry-run

Не выполнять перевод, а только посчитать объем текста и количество запросов к провайдеру

--copy-assets

Скопировать непереводимые файлы (изображения и другие ассеты) из папки исходного языка в папки целевых языков, чтобы переведенная версия собиралась самостоятельно

--report

Путь к файлу, в который записывается машиночитаемый JSON-отчет о прогоне. По умолчанию отчет не пишется, короткая итоговая строка в логе выводится всегда. См. Отчет о прогоне

--timeout

Время ожидания одного запроса к API перевода в миллисекундах. По умолчанию - 5000

Фиксированный список файлов

Если нужно ограничить перевод заранее известным набором файлов, вместо glob-шаблонов удобнее файл со списком - например, translate.list. Он передается в параметр --files или --include:

yfm translate --files ./translate.list --source ru --target en
# Файл поддерживает комментарии и пустые строки

# Пути формируются относительно самого файла translate.list
./some/path/to/translated/file-1.md
./some/path/to/translated/file-2.md

# Пути не должны находиться выше, чем translate.list
# Пример неправильного пути:
../some/path/to/translated/file.md

Отчет о прогоне

Опция --report записывает машиночитаемый отчет о прогоне в JSON: тайминги, объем перевода, использование кэша и резервной модели, оценки качества и ошибки. Отчет предназначен для автоматизации вокруг перевода - пайплайнов CI, учета расхода, дашбордов. На сам перевод опция не влияет и по умолчанию выключена.

yfm translate -i . -o ./translated --provider openai --source ru --target en \
  --report ./translate-report.json

Путь из командной строки считается от текущей директории, путь из файла конфигурации (ключ report) - от расположения .yfm.

Короткая итоговая строка пишется в лог всегда, с опцией и без нее:

INFO PROCESSED run success in 12.4s; files: 12 translated, 0 failed; units: 340 (154 cached, 45.3% hit rate); chars: 15200 in / 16900 out; tokens: 5200 in / 4800 out; requests: 18 (2 fallback, 3 retries); errors: 0

Структура отчета

Схема отчета - публичный контракт. Поле schemaVersion увеличивается при любом несовместимом изменении формата, поэтому потребителю стоит проверять его и отклонять незнакомые версии, а не читать данные наугад. Текущая версия - 1.

Поля верхнего уровня:

Поле

Описание

schemaVersion

Версия схемы отчета

startedAt, finishedAt

Время начала и конца прогона в формате ISO 8601

durationMs

Длительность прогона в миллисекундах

status

success, partial (прогон завершился, но были ошибки) или failed (прогон прерван фатальной ошибкой)

provider

Провайдер перевода: yandex, yandexgpt, openai, openrouter или anthropic

model, fallbackModel

Модель и резервная модель. Только у AI-провайдеров

fallbackUsed

true, если хотя бы один запрос обслужила резервная модель

dryRun

true для прогона с --dry-run: объем и токены в таком отчете - оценка

sourceLanguage, targetLanguages

Языки прогона

files

selected - файлы, отобранные для перевода, skipped - отфильтрованные до перевода

totals

Счетчики, просуммированные по всем целевым языкам

targets

Счетчики по каждому целевому языку, плюс блок judge при включенной оценке качества

errors

Список ошибок: target, path, устойчивый код code и сообщение

Счетчики (totals и каждый элемент targets):

Поле

Описание

files

translated - обработанные файлы, failed - упавшие, retried - отправленные на повторный заход после временных ошибок

units

Сегменты: total - всего, translated - переведено в этом прогоне, fromCache - взято из кэша, untranslated - вернулись от модели непереведенными, oversized - пропущены как слишком большие для одного запроса

chars

Символы: source - в исходных сегментах, translated - в переводах этого прогона, request - фактически отправлено в запросах

tokens

Расход токенов по данным провайдера: input и output. null, если провайдер не сообщает расход

requests

Запросы: total - всего, fallback - обслужены резервной моделью, retries - дополнительные попытки после временных ошибок

cache

enabled - был ли включен кэш, hits и misses - обращения, hitRate - доля попаданий или null

fixes

Починка ответов модели, см. Починка ответов модели

Блок judge в элементе targets появляется при включенной оценке качества и содержит модель-судью (model), порог (threshold), число оцененных пар (scored), средний балл (averageScore), число пар ниже порога (belowThreshold), число пар, которые судья не смог оценить (unscored), и гистограмму баллов distribution с ключами 0-9 ... 90-99 и 100.

Все счетчики заполняют только AI-провайдеры. У машинного перевода нет ни расхода токенов, ни кэша, ни оценки качества, ни починки разметки: tokens в его отчете - null, cache.enabled - false, счетчики fixes нулевые, блока judge нет.

Пример отчета:

{
  "schemaVersion": 1,
  "startedAt": "2026-08-25T10:00:00.000Z",
  "finishedAt": "2026-08-25T10:00:12.400Z",
  "durationMs": 12400,
  "status": "success",
  "provider": "openai",
  "model": "gpt-4o-mini",
  "fallbackModel": "gpt-4o",
  "fallbackUsed": true,
  "dryRun": false,
  "sourceLanguage": "ru",
  "targetLanguages": ["en"],
  "files": {"selected": 12, "skipped": 3},
  "totals": {
    "files": {"translated": 12, "failed": 0, "retried": 1},
    "units": {"total": 340, "translated": 182, "fromCache": 154, "untranslated": 4, "oversized": 0},
    "chars": {"source": 15200, "translated": 16900, "request": 8300},
    "tokens": {"input": 5200, "output": 4800},
    "requests": {"total": 18, "fallback": 2, "retries": 3},
    "cache": {"enabled": true, "hits": 154, "misses": 186, "hitRate": 0.4529},
    "fixes": {
      "markupStripped": 2,
      "markupRetried": 1,
      "markupDamaged": 0,
      "untranslatedRetried": 1,
      "untranslatedKept": 0
    }
  },
  "targets": [
    {
      "language": "en",
      "files": {"translated": 12, "failed": 0, "retried": 1},
      "units": {"total": 340, "translated": 182, "fromCache": 154, "untranslated": 4, "oversized": 0},
      "chars": {"source": 15200, "translated": 16900, "request": 8300},
      "tokens": {"input": 5200, "output": 4800},
      "requests": {"total": 18, "fallback": 2, "retries": 3},
      "cache": {"enabled": true, "hits": 154, "misses": 186, "hitRate": 0.4529},
      "fixes": {
        "markupStripped": 2,
        "markupRetried": 1,
        "markupDamaged": 0,
        "untranslatedRetried": 1,
        "untranslatedKept": 0
      }
    }
  ],
  "errors": []
}

Отчет о прогоне и отчет оценки качества - разные файлы. В отчете о прогоне только агрегаты оценки, разбор по сегментам остается в translate-quality.<язык>.json.

Исключение контента из перевода

Части контента можно исключить из перевода прямо в разметке.

  • translate=no - для блоков кода:

    ```sql translate=no
    SELECT * FROM posts WHERE id=123 LIMIT 1
    ```
    
  • `` - для строковых фрагментов (работает в md- и yaml-файлах):

    Формат даты: ISO 8601 со смещением относительно UTC.
    
  • :::no-translate - для блоков контента:

    Весь этот блок не уйдет на перевод.