Jak automatizovat překlad .po souborů ve vašem CI/CD pipeline

Váš tým merguje do větve main čtrnáctkrát denně. Každé takové sloučení může přidat nový řetězec viditelný pro uživatele – popisek tlačítka, chybovou zprávu, tooltip. A každý z těchto řetězců začíná existovat pouze v angličtině. Někde ve vašem procesu vydání musí člověk zaznamenat nové řetězce, exportovat je, nechat je přeložit, vložit je zpět a rekompilovat. Tento člověk je úzké hrdlo, a v rychle dodávajícím týmu toto úzké hrdlo znamená, že vaši němečtí uživatelé vidí anglické zástupné texty po dobu dvou sprintů.
Řešením je automatizovat překlad ve vašem CI/CD pipeline tak, aby se nové řetězce přeložily ve stejném merge, které je zavedlo – žádný člověk v kritické cestě pro rutinní případy. To je dnes zcela dosažitelné, ale pouze pokud se vyhnete pasti, do které většina týmů spadá: ručnímu vytváření nezpracovaných volání LLM, která tiše poškozují vaše zástupné znaky %s a strukturu .po. Tento průvodce prochází realistickým vzorem CI pipeline, funkčním skeletem GitHub Actions a rozhodnutími o designu – idempotence, překlad pouze nových položek, revizní brány – které oddělují pipeline, která pomáhá, od té, která dodává rozbité buildy.
Proč je manuální překlad úzkým hrdlem vydávání
Odpověď na otázku „proč nepřekládat před každým vydáním“ je, že načasování se nikdy neshoduje. Řetězce jsou neustále přidávány vývojáři, ale překlad probíhá v dávkách jinou osobou podle jiného plánu. Mezera mezi těmito dvěma kadencemi je místo, kde se hromadí váš lokalizační dluh.
Problém dvou kadencí
Představte si ruční postup. Vývojář přidá __( 'Export to CSV', 'mytextdomain' ) a provede merge. Nikdo neregneruje .pot soubor. O dva týdny později někdo spustí wp i18n make-pot, všimne si čtyřiceti nových nepřeložených řetězců (některé od vývojářů, kteří mezitím odešli na dovolenou), hádá záměr poloviny z nich a pošle .po soubor překladateli. Překlad se vrátí, vloží se a možná zástupné symboly přežily, a možná ne. Mezitím byly vydány tři verze s těmito řetězci v angličtině.
Každý krok je manuální, dávkový a náchylný k chybám. Cílem CI/CD automatizace je zjednodušit to na něco, co se automaticky spustí po merge, přeloží pouze to, co se skutečně změnilo, a hlasitě selže, když něco vypadá špatně – čímž se překlad z pravidelné rutiny stane neviditelnou součástí pipeline.
Vzor pipeline: Extrakce, Porovnání, Překlad, Potvrzení
Na vysoké úrovni automatizovaný překladový job provádí čtyři kroky po sloučení do main: regeneruje šablonu, detekuje, co je nové, přeloží pouze tyto řetězce a potvrdí výsledky zpět. Celá věc by měla být idempotentní – spuštění na sloučení bez změn řetězců musí produkovat nulový rozdíl a nulový šum.
Extrakce a porovnání
Prvním krokem je extrakce. Znovu vygenerujte .pot soubor z aktuálního zdroje, aby odrážel každý řetězec v kódové základně:
wp i18n make-pot . languages/myplugin.pot
Druhým krokem je porovnání (diff). Toto je nejdůležitější designové rozhodnutí v celé pipeline. Nechcete znovu překládat každý řetězec při každém sloučení – to plýtvá voláními API, riskuje opětovné překlady řetězců, které už člověk opravil, a produkuje obrovské revizní diffy. Místo toho sloučíte čerstvý .pot soubor do každého existujícího .po souboru a přeložíte pouze ty položky, které jsou nyní prázdné (skutečně nové řetězce):
# Merge new template into each locale, preserving existing translations.
# Newly-added strings appear with empty msgstr; --backup=none keeps the tree clean.
for po in languages/*.po; do
msgmerge --update --backup=none "$po" languages/myplugin.pot
done
Po msgmerge mají pouze zbrusu nové řetězce prázdný msgstr. Vše dříve přeložené zůstává nedotčené. Tato vlastnost je to, co činí pipeline idempotentní a co udržuje vaše revizní diffy malé a přezkoumatelné.
Překlad a potvrzení
Krok tři odesílá pouze tyto prázdné záznamy do kroku překladu. Krok čtyři potvrdí aktualizovaný .po soubor, zkompiluje .mo soubor a znovu vygeneruje jakékoli JSON soubory. Všechno to propojíme s GitHub Actions.
Skelet pro GitHub Actions
Zde je odpověď na otázku „jak to vlastně vypadá v souboru workflow“: job spuštěný při push do větve main, který provádí cyklus extrakce-porovnání-překlad-potvrzení a otevírá pull request s výsledky namísto přímého committování do main.
Soubor workflow
name: Translate on merge
on:
push:
branches: [ main ]
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install WP-CLI and gettext
run: |
sudo apt-get update && sudo apt-get install -y gettext
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp
- name: Regenerate template and merge into locales
run: |
wp i18n make-pot . languages/myplugin.pot
for po in languages/*.po; do
msgmerge --update --backup=none "$po" languages/myplugin.pot
done
- name: Translate only new (empty) strings
env:
TRANSLATE_API_KEY: ${{ secrets.TRANSLATE_API_KEY }}
run: ./scripts/translate-new-strings.sh languages/
- name: Compile .mo and JSON
run: |
wp i18n make-mo languages/
wp i18n make-json languages/ --no-purge
- name: Open pull request with translations
uses: peter-evans/create-pull-request@v6
with:
branch: chore/auto-translations
title: "chore: auto-translate new strings"
commit-message: "chore: auto-translate new strings"
Kde se skrývá skutečná práce
Krok translate-new-strings.sh je místo, kde probíhá skutečný překlad. Naivní verze tohoto skriptu čte každou prázdnou položku, odesílá ji do LLM API po jednom řetězci a vkládá odpověď zpět. Tato naivní verze je přesně ta past a stojí za to si vysvětlit proč.
Proč ručně psaná volání LLM ničí vaše soubory
Stručná odpověď: nezpracovaná volání LLM zachází s vašimi .po řetězci jako s prózou, ale vaše .po řetězce nejsou próza – jsou to strukturovaná data se zástupnými symboly, množnými tvary a kontextem, které volání pro dokončení chatu s radostí zničí.
Poškození zástupných symbolů, které neuvidíte v testech
Pošlete Deleted %d of %s files na obecný chatovací endpoint a můžete dostat zpět Supprimé %d des %s fichiers (v pořádku) nebo Supprimé %d de % s fichiers (mezera se vloudila do zástupného symbolu a nyní sprintf() selže za běhu). Pošlete položku s množným číslem a model může sloučit dvě formy do jedné, což rozbije jazyky s více než dvěma kategoriemi množného čísla. Pošlete řetězec s <a href="%s"> a model může přeložit URL nebo odstranit tag. Žádná z těchto selhání se neobjeví ve vašich testech, pokud konkrétně netestujete vykreslený výstup v každé lokalitě – objeví se jako runtime chyby v produkci pro uživatele, od kterých nemůžete číst hlášení o chybách.
Past údržby
Můžete se tomu pokusit bránit pomocí prompt engineeringu a post-processingu regulárních výrazů, a mnoho týmů to dělá. Problém je, že nyní udržujete křehký překladový engine jako vedlejší projekt, znovu objevujete každý hraniční případ zástupného symbolu, který již ekosystém Gettext vyřešil. Specifické způsoby, jakými se proměnné poškozují – a jak jim předcházet – katalogizujeme v článku překlad PO souborů bez porušení kódových proměnných. Tamní poučení platí přímo: kvalita modelu je zřídka problém; jde spíše o strukturální zpracování kolem něj.
Integrace cloudového překladače řízeného API do CI
Zde služba pro překlad řízená API nahrazuje vaše odhady v translate-new-strings.sh. Namísto ručního vytváření volání LLM a post-processingu regulárních výrazů váš CI krok nahrává změněný .po soubor do služby, která již rozumí struktuře Gettext a vrací čistý výstup. Tvar pipeline zůstává identický – extrakce, porovnání, překlad, potvrzení – ale křehký prostřední krok se stává jediným voláním API.
Volání API, které nahradí váš skript
SimplePoTranslate je postaven přesně pro toto. Poskytuje cloudové API vhodné pro automatizaci a CI, takže krok překladu vašeho workflow se stane požadavkem, který předá .po soubor a dostane zpět přeložený, bez smyčkování pro každý řetězec. Jeho Syntax Locking automaticky udržuje %s, %1$s, {count}, HTML a kódové tokeny na místě – celá třída chyb z předchozí sekce je zpracována enginem, nikoli regulárními výrazy, které byste museli udržovat. S plnou podporou Gettext množného čísla a msgctxt přežijí množné tvary a kontext zpáteční cestu, což volání pro dokončení chatu nemůže zaručit.
Idempotence a revizní brána zůstávají vaše
Dvě designová rozhodnutí stále náleží vám, bez ohledu na to, jaký engine používáte. Za prvé, idempotence: pokračujte v překladu pouze prázdných položek po msgmerge, aby merge bez operací neprodukovaly žádný diff. Za druhé, revizní brána: nechte job otevřít pull request, jak to dělá výše uvedený skelet, namísto přímého committování do main. Strojový překlad je vynikající pro rychlé nasazení řetězců, ale lidský pohled před sloučením zachytí vzácnou kontextovou chybu – a PR vám tento pohled poskytne, aniž by blokoval běžný případ. Týmy, které spravují mnoho lokalizací nebo mnoho klientských webů, poznají tento vzor z článku ideální lokalizační workflow pro agentury, kde se stejný vzor automatizace a následné revize škáluje napříč desítkami projektů.
Závěr
Pro automatizaci překladu v CI/CD bez dodávání rozbitých buildů je vzor konzistentní: regenerujte .pot soubor při merge, msgmerge ho do každé lokality, aby se objevily pouze nové řetězce, přeložte pouze tyto řetězce a potvrďte výsledek za revizní bránou pull requestu. Idempotence udržuje vaše diffy čisté; revizní brána drží vzácné špatné překlady mimo produkci.
Důležité je správně provést samotný překladový krok. Ručně vytvářená volání LLM poškodí zástupné symboly a množné tvary způsoby, které vaše testy nezachytí, a vy strávíte více času údržbou překladového lepidla než kódu funkcí, které obsluhuje. Engine řízený API se Syntax Lockingem odstraňuje celý tento režim selhání, takže vaše pipeline překládá nové řetězce ve stejném merge, které je zavedlo – a vaši neanglicky mluvící uživatelé přestanou vidět anglické zástupné symboly.
Jste připraveni automatizovat překlad ve své pipeline, aniž byste rozbili zástupné symboly? Vyzkoušejte SimplePoTranslate zdarma – není vyžadována kreditní karta. Začněte s bezplatnou úrovní, ověřte API proti svým vlastním
.posouborům a integrujte jej do CI, až budete připraveni.