Повернутися до блогу
A git diff view showing a locale file with three changed keys highlighted, and only those three keys being sent to the translation API below.

Вам не потрібно перекладати все заново: як працює дельта-переклад у CI

By Robert M

Вам не потрібно перекладати все заново: як працює дельта-переклад у CI

Коли ви підключаєте автоматичний переклад до вашого CI-процесу, природно виникає питання: чи перекладається весь локалізований файл щоразу, коли хтось робить зміни?

Без дельта-режиму — так. Кожен пуш, що торкається вашого вихідного локалізованого файлу, відправляє весь файл до API, кожен ключ, кожен рядок, незалежно від того, чи змінився він. Для невеликого проекту на початковому етапі це нормально. Для зрілого проекту з сотнями ключів перекладу на 10 або 20 мовах ви витрачаєте токени на рядки, які не змінилися з останнього запуску, і отримуєте однаковий результат без користі.

Дельта-переклад вирішує цю проблему. Замість того, щоб надсилати повний файл, Action порівнює ваш поточний вихідний файл з збереженим базовим файлом (baseline), визначає лише ключі, які були додані або змінені, і надсилає лише їх до API. Результат для незмінних ключів береться з існуючих перекладених файлів. Використання токенів знижується відповідно до фактичної роботи.


Як працює baseline

Коли дельта-режим запускається вперше або коли ви примусово оновлюєте повністю, Action перекладає повний вихідний файл і зберігає його у вигляді плоского JSON як baseline у вашому репозиторії. При наступних запусках Action завантажує цей baseline, порівнює його з поточним вихідним файлом і формує payload, що містить лише змінені ключі.

Для JSON локалізованих файлів baseline зберігається як .polylingo-baseline.json у вашій директорії messages. Для YAML локалізованих файлів — .polylingo-yaml-baseline.json у директорії locales. Для Laravel PHP lang файлів — .polylingo-laravel-php-baseline.json у директорії lang.

Baseline комітиться разом з вашими перекладеними файлами, тому він подорожує разом з репозиторієм. Будь-який розробник, який клонуватиме репозиторій, отримає той самий baseline, з яким працює pipeline.


Що вважається зміною

Diff працює на плоскому представленні ключів вашого вихідного файлу. Вкладені структури перетворюються у ключі з точковою нотацією перед порівнянням:

{
  "nav.home": "Головна",
  "nav.about": "Про нас",
  "hero.title": "Ласкаво просимо на нашу платформу",
  "hero.cta": "Почати"
}

Ключ включається у delta payload, якщо:

  • Він існує у поточному вихідному файлі, але відсутній у baseline (новий ключ)
  • Він є в обох, але значення змінилося (змінений ключ) Ключі, які є у baseline, але відсутні у поточному вихідному файлі (видалені ключі), автоматично видаляються з перекладених файлів. Ключі, які однакові в обох, повністю пропускаються, а їхні існуючі переклади залишаються на місці.

Як це виглядає на практиці

Припустимо, у вас є проект Next.js з 200 ключами перекладу у messages/en.json, які вже перекладені на 12 мов. Розробник оновлює текст у секції hero і додає два нові ключі для оголошення функції. Це 4 змінені ключі з 200.

Без дельта-режиму pipeline надсилає всі 200 ключів, помножені на 12 мов, при кожному пуші. З дельта-режимом надсилаються лише 4 ключі. Використання токенів для цього запуску становить приблизно 2% від вартості повного перекладу. Pipeline також працює швидше, бо менше даних потрібно відправляти і чекати.

За місяць регулярної розробки економія значно накопичується. Більшість пушів торкаються лише кількох рядків. Повний повторний переклад відбувається лише при додаванні нової мови або явному скиданні baseline.


Три PolyLingo GitHub Actions

Дельта-режим доступний у всіх трьох PolyLingo translation Actions. Кожен створений для певного типу контенту та структури проекту.

translateAction — JSON та Markdown

Оригінальний Action. Обробляє плоскі JSON локалізовані файли у стилі next-intl та i18next, з опціональним проходом Markdown документації через async jobs API для більших файлів.

- uses: UsePolyLingo/translate-action@v1
  with:
    api_key: ${{ secrets.POLYLINGO_API_KEY }}
    source_file: messages/en.json
    locales: fr,de,es,ja,zh
    delta: true
    commit: true
    commit_message: "chore(i18n): sync translations"

Delta baseline: messages/.polylingo-baseline.json

github.com/UsePolyLingo/translateActionПереглянути на Marketplace


translate-action-yaml — YAML локалізовані файли

Для проектів, що використовують вкладені YAML локалізовані файли: Rails i18n, Vue i18n та будь-який інший фреймворк, що використовує формат YAML. Action автоматично обробляє конвенцію Rails з кореневим ключем локалі — en.yml має кореневий ключ en:, і кожен вихідний файл отримує правильний цільовий ключ локалі (fr:, de: тощо).

Оскільки PolyLingo API працює з JSON нативно, Action спочатку перетворює вкладений YAML у JSON з точковою нотацією, потім перекладає, відновлює вкладену структуру і записує валідний YAML. Один нюанс v1: ключі, що містять крапки природно, не підтримуються, оскільки вони конфліктують з flatten dot-notation.

- uses: UsePolyLingo/translate-action-yaml@v1
  with:
    api_key: ${{ secrets.POLYLINGO_API_KEY }}
    locales_dir: config/locales
    source_file: config/locales/en.yml
    locales: fr,de,es,ja
    delta: true
    commit: true

Delta baseline: config/locales/.polylingo-yaml-baseline.json

github.com/UsePolyLingo/translate-action-yamlПереглянути на Marketplace


translate-action-laravel — Laravel lang файли

Для Laravel проектів, що використовують або JSON файли перекладу (lang/en.json, підтримуючи як вкладені, так і плоскі структури у стилі Laravel 9+), або PHP масивні lang файли (lang/en/*.php). Action автоматично визначає формат проекту через php_format: auto — спочатку перевіряє lang/en.json, якщо не знайдено, переходить до PHP масивних файлів.

Для PHP файлів виконує виклик PHP CLI для читання вихідних файлів і серіалізує перекладений вихід назад у валідний PHP масивний синтаксис у JavaScript без додаткових залежностей. GitHub-hosted ubuntu-latest раннери за замовчуванням мають PHP 8.x, тому додаткових налаштувань не потрібно. Потрібен PHP 7.4 або новіший.

Один нюанс v1: ключі, що містять крапки, не підтримуються у PHP режимі через стратегію flatten dot-notation.

- uses: UsePolyLingo/translate-action-laravel@v1
  with:
    api_key: ${{ secrets.POLYLINGO_API_KEY }}
    lang_dir: lang
    source_locale: en
    locales: fr,de,es,pt,nl
    php_format: auto
    delta: true
    open_pr: true

Delta baseline: lang/.polylingo-laravel-json-baseline.json або lang/.polylingo-laravel-php-baseline.json залежно від формату.

github.com/UsePolyLingo/translate-action-laravelПереглянути на Marketplace


Режим PR проти режиму commit

Всі три Action підтримують два режими виводу.

Режим commit (commit: true) записує перекладені файли і комітить їх безпосередньо у поточну гілку. Просте налаштування, підходить для команд, які розглядають переклад як автоматизований процес без потреби в рев’ю.

Режим PR (open_pr: true) створює нову гілку (polylingo/yaml-<sha>, polylingo/laravel-<sha> тощо), записує туди перекладені файли і відкриває pull request до вашої базової гілки. Краще для команд, які хочуть крок рев’ю людиною перед злиттям перекладеного контенту, або для проектів, де якість перекладу безпосередньо впливає на користувацький досвід.

Якщо обидва встановлені, перемагає режим PR.

Режим PR вимагає pull-requests: write у дозволах workflow:

permissions:
  contents: write
  pull-requests: write

Примусове повне оновлення

Дельта-режим порівнює з збереженим baseline. Якщо ви хочете перекласти все заново незалежно від того, що показує baseline, встановіть delta: false. Це також оновить baseline відповідно до поточного вихідного файлу, тому наступні дельта-запуски починатимуться з нового стану.

Повне оновлення корисне, коли ви додаєте нову цільову мову, хочете отримати покращення якості перекладу у новій версії моделі або коли baseline відхилився від реальності з будь-якої причини.

- uses: UsePolyLingo/translate-action-yaml@v1
  with:
    api_key: ${{ secrets.POLYLINGO_API_KEY }}
    locales_dir: config/locales
    locales: fr,de,es,ja,zh,ko,ar
    delta: false  # повне оновлення, оновлює baseline
    commit: true

Виводи для наступних кроків

Всі три Action надають однакові виводи, щоб ви могли використовувати їх у наступних кроках workflow:

- uses: UsePolyLingo/translate-action@v1
  id: translate
  with:
    api_key: ${{ secrets.POLYLINGO_API_KEY }}
    source_file: messages/en.json
    locales: fr,de,es
    delta: true
    commit: true

- name: Запис статистики перекладу
  run: |
    echo "Locales translated: ${{ steps.translate.outputs.locales_translated }}"
    echo "Files changed: ${{ steps.translate.outputs.files_changed }}"
    echo "Tokens used: ${{ steps.translate.outputs.tokens_used }}"

Кожен запуск також записує підсумкову таблицю у GitHub Actions step summary, щоб ви могли бачити використання токенів і результати перекладу без необхідності шукати у логах.


Початок роботи

Всі три Action доступні на GitHub Marketplace. Вам знадобиться ключ API PolyLingo, який можна отримати безкоштовно на usepolylingo.com. Безкоштовний рівень включає 50 000 токенів на місяць. З увімкненим дельта-режимом більшість проектів залишатимуться в межах цього ліміту при звичайних розробницьких пушах.

Додайте свій API ключ як секрет репозиторію (POLYLINGO_API_KEY) і додайте відповідний Action у ваш workflow. Перший запуск виконує повний переклад і встановлює baseline. Кожен наступний запуск перекладає лише те, що змінилося.