Перевод документации ru/en без потери темпа разработки
Есть документация на русском. Хочется ещё на английском, чтобы продукт был доступнее. Команда переводит первую партию страниц, потом две минорные версии не успевает, потом начинают расходиться примеры, потом перевод устаревает на четверть, и его уже стыдно показывать.
Перевод документации провалится, если процесс не учитывает темп разработки. Нельзя один раз перевести 200 страниц и считать, что всё. Нужен механизм, при котором перевод не отстаёт от изменений в исходнике, или отстаёт предсказуемо. Разберу, как организовать перевод ru-en (и обратно), чтобы команда не выгорала и читатели не получали устаревшие страницы.
Какой язык — основной
Первое решение, от которого зависит всё дальше: какой язык — источник правды.
Варианты:
- Русский → английский. Команда пишет на русском, переводят на английский. Подходит, если основная аудитория — русскоговорящая, и команда удобнее пишет на русском.
- Английский → русский. Команда пишет на английском, переводят на русский. Подходит для продуктов с международной аудиторией, где английский — основной канал коммуникации.
- Параллельно оба. Каждая статья пишется и поддерживается на двух языках одновременно. Идеал в теории, в реальности проигрывает первому/второму варианту по затратам.
Я почти всегда советую один основной язык. Параллельная поддержка двух работает только в командах с двумя писателями, которые пишут одно и то же дважды. Для большинства команд это нерентабельно.
Структура папок
Самое жизнеспособное — отдельные папки на язык:
docs/
├── en/
│ ├── getting-started.md
│ ├── api/
│ │ └── users.md
│ └── ...
└── ru/
├── getting-started.md
├── api/
│ └── users.md
└── ...
Имена файлов одинаковые — ссылки между языками легко вычисляются. Структура — зеркальная.
Альтернатива «один файл с двумя языками через метку :::lang ru» работает плохо: при ревью diff раздувается, при автогенерации тяжело, при переводе через инструменты не понятно, что переводить.
Какие страницы переводить, какие нет
Не всё нужно переводить. Это самая частая ошибка — старт «переведём всё, что есть». Через два месяца перевод отстаёт, и читатель получает устаревший английский на трети страниц.
Что переводим:
- Getting Started, первый туториал. Самая частая точка входа.
- Reference, если он сгенерирован из кода — переводится автоматически или вообще не переводится (читать сигнатуры можно и на основном языке).
- Топ-10 страниц по трафику. Аналитика покажет, какие.
- Релизные ноты для major-версий.
Что не переводим (обычно):
- Внутренние ADR и design docs, если они не для внешних читателей.
- Edge case-страницы, к которым ходят 50 раз в год.
- FAQ по специфичным сценариям.
- Архивные страницы старых версий.
Лучше иметь 30 страниц с актуальным переводом, чем 200 с переводом полугодовой давности.
Процесс: что меняется в исходнике, что в переводе
Ключевая боль: разработчик меняет страницу на основном языке, но забывает или не может обновить перевод.
Подходы:
1. Translation lag tracking. На странице перевода в metadata указывается коммит исходника, с которого она переведена. Если исходник ушёл вперёд — на странице перевода появляется баннер «Перевод отстаёт на N коммитов, читайте основной».
---
title: Getting Started
translated_from: en/getting-started.md
translated_at_commit: a4f2b3c
---
В CI скрипт сравнивает текущий коммит исходника с указанным и ставит лейбл на страницу. Не идеально, но честно: читатель знает, что перевод может быть устаревшим.
2. PR-блокировка. Если PR меняет файл в docs/en/, проверка требует одного из:
- Соответствующее обновление в
docs/ru/. - Метку
translation: deferс обоснованием.
Это жёсткий подход, заставляет разработчика думать о переводе на каждом изменении. Работает, если в команде есть переводчик/писатель, готовый брать в работу. Если нет — превращается в блокер.
3. Отдельный поток перевода. Английский живёт своей жизнью, перевод догоняет с лагом 1-2 недели через отдельные PR. Самый честный вариант для команд без выделенного переводчика. Лаг публичный: на странице написано «Updated: 2026-04-01, English version updated 2026-04-15».
На моей практике вариант 3 работает чаще всего: реалистичный, не блокирует разработку, читатель информирован.
Где автоматический перевод ломается
Соблазн прогонять страницы через автопереводчик и публиковать. Качество стало приличным, но ошибки специфические:
- Технические термины переводятся слишком буквально. «Branch» в git-контексте автопереводчик может перевести как «ветка», но «pull request» — как «запрос на вытягивание». Глоссарий обязателен.
- Команды и код переводятся. Имена функций, флаги, JSON-ключи — должны остаться как есть. Без разметки автопереводчик может тронуть.
- Стиль и тон отлетают. Документация на английском чаще пишется в imperative («Run the command»), на русском — в инфинитиве («Запустить команду»). Прямой автоперевод даёт «Бегите команду».
- Идиомы и культурные референсы. «Out of the box» переводится буквально и теряет смысл.
Автопереводчик — для черновика, не для публикации. Использовать как первичный проход, потом редактор-человек проходит по тексту и правит. Это всё равно быстрее, чем переводить с нуля, но без редактуры публиковать нельзя.
Глоссарий: основной артефакт
Глоссарий — таблица «термин на исходном языке → перевод → пояснение». Без него каждый переводчик принимает решения по-своему, и в одной странице «branch» — это «ветка», в другой — «бранч».
| Original | Russian | Note |
|-------------------|---------------------|-------------------------------------|
| branch | ветка | git-context |
| pull request | пулл-реквест | оставлять кириллицей |
| commit | коммит | оставлять кириллицей |
| revert | откатить | не «реверт» |
| merge | слить | глагол; «merge commit» — мерж-коммит|
| rebase | rebase | оставлять как есть, не переводить |
Глоссарий живёт в репозитории, рядом с документацией. На каждый новый перевод сверяемся. На пуш в ветку перевода CI может прогонять простой grep и ругаться, если встретился термин с непривычным переводом.
Скриншоты
Скриншоты UI на разных языках — это отдельный поток работы. Если интерфейс переключается языком, нужно делать скриншоты на каждом. Для документации UI это обязательно: английский скриншот в русской документации к русскому интерфейсу выглядит сломано.
Что помогает:
- Скриншоты делает CI: автотест запускает приложение на нужном языке, делает screenshot, кладёт в репозиторий.
- Один скрипт — два прогона: один с
LANG=en, второй сLANG=ru. Скриншоты в подпапках по языку. - Имена файлов — одинаковые, путь — разный.
В коде документации:

Где {lang} — переменная, подставляется генератором документации.
SEO для двух языков
Google и другие поисковики хотят знать, какие страницы — переводы какой. Тег hreflang:
<link rel="alternate" hreflang="en" href="https://docs.example.com/en/getting-started">
<link rel="alternate" hreflang="ru" href="https://docs.example.com/ru/getting-started">
<link rel="alternate" hreflang="x-default" href="https://docs.example.com/en/getting-started">
Без него поисковик иногда показывает русскую версию англоязычному пользователю, потому что не понимает, что это перевод. Большинство генераторов документации (MkDocs Material, Docusaurus, VitePress) умеют ставить hreflang автоматически, если правильно настроен i18n.
Переключатель языка в UI
Маленькая деталь, на которой команды часто экономят. Переключатель должен:
- Быть в шапке, в очевидном месте.
- Показывать языки на их собственном языке: «English», «Русский», не «English», «Russian».
- Открывать ту же страницу на другом языке (а не главную), если перевод существует.
- Если перевода для текущей страницы нет — показывать заметку «Эта страница пока не переведена, открыта английская версия».
Последний пункт критичен. Когда переключатель ломается на отдельных страницах (открывает 404 или главную), пользователь теряет доверие к навигации.
Проверка качества перевода
Перевод — это редакторская работа, и её качество стоит проверять автоматически и вручную.
Автоматически:
- Vale с правилами на оба языка. Стиль, длина предложений, запрещённые слова.
- Проверка глоссария:
grepна термины из неутверждённых переводов. - Проверка broken links на переведённой версии: ссылки на несуществующие страницы.
- Проверка соответствия структуры: количество заголовков, кодовых блоков должно совпадать с оригиналом.
Вручную:
- Native speaker раз в квартал делает обзор страниц с самым высоким трафиком.
- Команда поддержки фиксирует, когда читатели жалуются на формулировки.
Темп и приоритизация
Что переводить первым, когда времени мало:
- Главная страница, навигация, заголовки — первое, что видит читатель.
- Getting Started, первый туториал.
- Топ-5 страниц по трафику.
- Release notes последней major-версии.
- Common errors / FAQ.
Дальше — по запросу. Если страница, на которую ходят 100 раз в месяц, не переведена, и никто не жалуется, не переводи. Если ходят 10000 раз — обязательно.
Чек-лист процесса перевода
- Один язык — основной, второй — производный.
- Папки
docs/en/иdocs/ru/с зеркальной структурой. - Метаданные с коммитом исходника на каждой странице перевода.
- CI ругается, если перевод сильно отстал.
- Глоссарий в репозитории, проверяется на CI.
- Скриншоты на двух языках, генерируются автоматически.
hreflangнастроен на всех страницах.- Переключатель языка работает на каждой странице.
- Список переводимых страниц приоритизирован по трафику.
- Автоперевод — для черновика, ручная редактура — обязательна.
Перевод документации — это процесс, а не разовая задача. Если относиться к нему как к «один раз перевели и забыли», результат гниёт быстрее, чем команда успевает заметить. Если встроить перевод в темп разработки, выбрать реалистичный лаг и расставить приоритеты, перевод становится живой документацией, а не музейным экспонатом, на который страшно смотреть.