Як я (з допомогою ШІ) переклав 409 статей блогу за один сеанс

У мене є блог на Hugo з контентом українською мовою — пости, нотатки, статті, архів LiveJournal за 2007–2017 роки. Загалом щось близько 409 markdown-файлів. І давно свербіло зробити англійську версію.

Зробити це вручну — нереально. Найняти перекладача на 409 файлів — дорого і довго. Але є Claude Code.

Що зроблено#

Весь контент із content/ua/ тепер має відповідні переклади в content/en/. Це:

  • Пости за 2008–2026 роки
  • Архів LiveJournal — 181 запис із 2007 по 2017 рік: технічні нотатки, щоденникові записи, поезія, політичні коментарі, рецензії на фільми… усе це написане молодшим мною на суміші української та російської
  • Статті та нотатки — більш структурований контент у docs/
  • Сторінки проєктів

Як це робилось#

Ідея проста: Claude Code вміє запускати підагентів. Для кожного файлу, який ще не має англійського відповідника, запускається окремий агент із завданням:

  1. Прочитати content/ua/path/to/file.md
  2. Перекласти з української (або російської — архів LJ часто був змішаним) на англійську
  3. Зберегти в content/en/path/to/file.md

Правила перекладу:

  • Структура frontmatter зберігається повністю
  • Значення тегів не перекладаються (теги — це ідентифікатори)
  • Заголовок, опис та інший описовий текст у frontmatter — перекладаються
  • Весь текст тіла перекладається
  • Markdown-форматування, зображення, посилання, блоки коду — зберігаються незмінними

Агенти запускались послідовно, по одному на файл. Паралельність тут не підходить — і через ліміти API, і тому що важливо не загубити жоден файл.

Технічні деталі#

Дозволи. Claude Code за замовчуванням запитує підтвердження на кожну операцію запису. Для підагентів це проблема — вони не можуть отримати інтерактивне підтвердження у фоновому режимі. Рішення: файл .claude/settings.json із pre-approved дозволами:

{
  "permissions": {
    "allow": [
      "Write(content/en/**)",
      "Bash(*)"
    ]
  }
}

Пошук непереведених файлів. Простий shell-скрипт:

find content/ua -name "*.md" | sort | while IFS= read -r ua; do
  en=$(echo "$ua" | sed 's|content/ua/|content/en/|')
  [ ! -f "$en" ] && echo "$ua"
done

Важливий урок: find | xargs без -print0 / -0 ламається на іменах файлів із пробілами. У нас є тека content/en/docs/projects/hardware-tools/3d printers/ — і це одразу дало помилку. Правильно так:

find content/en -name "*.md" -print0 | xargs -0 sed -i '' -e 's|old|new|g'

Що ще виправлено#

Після перекладу виявились додаткові проблеми.

Внутрішні посилання. Hugo-блог має defaultContentLanguage: ua, тобто посилання на кшталт /docs/articles/foo/ або /posts/2024/bar/ без мовного префіксу ведуть на українську версію. В англійських файлах усі такі посилання треба замінити на /en/docs/... і /en/posts/.... Також абсолютні посилання типу https://www.disfinder.com/docs/... — теж переробити у відносні /en/docs/....

Виправлено масово через sed:

find content/en -name "*.md" -print0 | xargs -0 sed -i '' \
  -e 's|](/docs/|](/en/docs/|g' \
  -e 's|](/posts/|](/en/posts/|g'

Зображення. Картинки лежать поруч з українськими постами — content/ua/posts/2024/foo/image.png. Англійська версія поста їх не бачить, бо вона в content/en/posts/2024/foo/. Рішення — симлінки:

find content/ua -not -name "*.md" -type f -print0 | while IFS= read -r -d '' ua; do
  en=$(echo "$ua" | sed 's|content/ua/|content/en/|')
  if [ ! -e "$en" ] && [ ! -L "$en" ]; then
    mkdir -p "$(dirname "$en")"
    python3 -c "
import os, sys
ua, en = sys.argv[1], sys.argv[2]
rel = os.path.relpath(ua, os.path.dirname(en))
os.symlink(rel, en)
" "$ua" "$en"
  fi
done

Відносний шлях обчислюється через Python, щоб коректно обробити будь-яку глибину вкладеності.

Результат#

409 файлів. Кілька годин роботи (з перервами на ліміти API). Мінімум ручної праці — лише нагляд і корекція курсу.

Якість перекладу — добра для технічного та щоденникового контенту. Ідіоми, жаргон, радянські культурні посилання — все це агент намагався пояснити або адаптувати. Вірші перекладені зі збереженням структури рядків, але без рими (форсована рима у перекладі зазвичай руйнує зміст).

Усе це задокументовано у CLAUDE.md — щоб наступного разу не починати з нуля.


P.S. Цю статтю теж написав Claude. Я лише попросив. Ми квіти.

comments powered by Disqus