Come Automatizzare la Traduzione .po nella Tua Pipeline CI/CD

Il tuo team effettua merge su main quattordici volte al giorno. Ognuno di questi merge potrebbe aggiungere una nuova stringa visibile all'utente – un'etichetta per un pulsante, un messaggio di errore, un tooltip. E ognuna di queste stringhe nasce solo in inglese. Da qualche parte nel tuo processo di rilascio, un essere umano deve notare le nuove stringhe, esportarle, farle tradurre, incollarle di nuovo e ricompilare. Quell'essere umano è un collo di bottiglia, e in un team che rilascia rapidamente, questo collo di bottiglia significa che i tuoi utenti tedeschi vedono segnaposto in inglese per due sprint.
La soluzione è automatizzare la traduzione nella tua pipeline CI/CD in modo che le nuove stringhe vengano tradotte sullo stesso merge che le ha introdotte – senza alcun intervento umano nel percorso critico per i casi di routine. Questo è completamente realizzabile oggi, ma solo se eviti la trappola in cui cadono la maggior parte dei team: creare manualmente chiamate LLM grezze che corrompono silenziosamente i tuoi segnaposto %s e la struttura del .po. Questa guida illustra un modello realistico di pipeline CI, uno scheletro funzionante per GitHub Actions e le decisioni di progettazione – idempotenza, traduzione solo delle novità, gate di revisione – che distinguono una pipeline utile da una che rilascia build rotte.
Perché la Traduzione Manuale è un Collo di Bottiglia nel Rilascio
La risposta a "perché non tradurre semplicemente prima di ogni rilascio" è che i tempi non si allineano mai. Le stringhe vengono aggiunte continuamente dagli sviluppatori, ma la traduzione avviene a lotti da una persona diversa con una pianificazione diversa. Il divario tra queste due cadenze è dove si accumula il tuo debito di localizzazione.
Il Problema delle Due Cadenze
Immagina il flusso manuale. Uno sviluppatore aggiunge __( 'Export to CSV', 'mytextdomain' ) ed effettua il merge. Nessuno rigenera il .pot. Due settimane dopo, qualcuno esegue wp i18n make-pot, nota quaranta nuove stringhe non tradotte (alcune da sviluppatori che nel frattempo sono andati in vacanza), ne indovina l'intento per metà e invia un .po a un traduttore. La traduzione torna, viene incollata, e forse i segnaposto sono sopravvissuti e forse no. Nel frattempo, tre rilasci sono stati distribuiti con quelle stringhe in inglese.
Ogni passo è manuale, a lotti e soggetto a errori. L'obiettivo dell'automazione CI/CD è ridurre tutto questo a qualcosa che si esegue automaticamente al merge, traduce solo ciò che è effettivamente cambiato e fallisce rumorosamente quando qualcosa sembra sbagliato – trasformando la traduzione da una seccatura periodica a una parte invisibile della pipeline.
Il Modello della Pipeline: Estrai, Differenzia, Traduci, Committa
A un livello più alto, un lavoro di traduzione automatizzato esegue quattro passaggi al merge su main: rigenera il template, rileva le novità, traduce solo quelle stringhe e committa i risultati. L'intero processo dovrebbe essere idempotente – eseguirlo su un merge senza modifiche alle stringhe deve produrre zero diff e zero rumore.
Estrai e Differenzia
Il primo passo è l'estrazione. Rigenera il .pot dalla sorgente corrente in modo che rifletta ogni stringa nel codice:
wp i18n make-pot . languages/myplugin.pot
Il secondo passo è la differenziazione. Questa è la decisione di progettazione più importante dell'intera pipeline. Non vuoi ritradurre ogni stringa ad ogni merge – questo spreca chiamate API, rischia di ritradurre stringhe che un umano ha già corretto e produce enormi diff di revisione. Invece, unisci il .pot fresco in ogni .po esistente e traduci solo le voci che ora sono vuote (le stringhe veramente nuove):
# 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
Dopo msgmerge, solo le stringhe nuove di zecca hanno un msgstr vuoto. Tutto ciò che era stato precedentemente tradotto rimane intatto. Questa proprietà è ciò che rende la pipeline idempotente e ciò che mantiene i tuoi diff di revisione piccoli e revisionabili.
Traduci e Committa
Il terzo passo invia solo quelle voci vuote a un passaggio di traduzione. Il quarto passo committa il .po aggiornato, compila .mo e rigenera qualsiasi JSON. Integreremo tutto questo in GitHub Actions successivamente.
Uno Scheletro di GitHub Actions
Ecco la risposta a "come appare effettivamente in un file di workflow": un job attivato al push su main che esegue il ciclo estrai-differenzia-traduci-committa e apre una pull request con i risultati invece di committare direttamente su main.
Il File del 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"
Dove si Nasconde il Vero Lavoro
Il passaggio translate-new-strings.sh è dove avviene la traduzione effettiva. La versione ingenua di quello script legge ogni voce vuota, la invia a un'API LLM una stringa alla volta e incolla la risposta. Quella versione ingenua è esattamente la trappola, ed è utile essere espliciti sul perché.
Perché le Chiamate LLM Manuali Rompono i Tuoi File
La risposta breve: le chiamate LLM grezze trattano le tue stringhe .po come prosa, e le tue stringhe .po non sono prosa – sono dati strutturati con segnaposto, forme plurali e contesto che una chiamata di completamento chat distrugge allegramente.
La Corruzione dei Segnaposto Che Non Vedrai nei Test
Invia Deleted %d of %s files a un endpoint di chat generico e potresti ottenere Supprimé %d des %s fichiers (va bene) o Supprimé %d de % s fichiers (uno spazio si è insinuato nel segnaposto, e ora sprintf() genera un errore a runtime). Invia una voce plurale e il modello potrebbe collassare due forme in una, rompendo le lingue con più di due categorie plurali. Invia una stringa con <a href="%s"> e il modello potrebbe tradurre l'URL o eliminare il tag. Nessuna di queste fallisce nei tuoi test a meno che tu non testi specificamente l'output renderizzato in ogni locale – si manifestano come errori di runtime in produzione per utenti di cui non puoi leggere le segnalazioni di bug.
La Trappola della Manutenzione
Puoi provare a difenderti da questo con prompt engineering e post-elaborazione regex, e molti team lo fanno. Il problema è che stai ora mantenendo un motore di traduzione fragile come progetto secondario, riscoprendo ogni caso limite di segnaposto che l'ecosistema Gettext ha già risolto. Abbiamo catalogato i modi specifici in cui le variabili vengono alterate – e come prevenirli – in tradurre i file PO senza rompere le variabili di codice. La lezione qui si applica direttamente: la qualità del modello raramente è il problema; lo è la gestione strutturale attorno ad esso.
Integrare un Traduttore Cloud Basato su API nel CI
È qui che un servizio di traduzione basato su API sostituisce le tue congetture di translate-new-strings.sh. Invece di creare manualmente chiamate LLM e post-elaborazione regex, il tuo passaggio CI carica il .po modificato a un servizio che comprende già la struttura Gettext e restituisce un output pulito. La forma della pipeline rimane identica – estrai, differenzia, traduci, committa – ma il fragile passaggio intermedio diventa una singola chiamata API.
La Chiamata API Che Sostituisce il Tuo Script
SimplePoTranslate è costruito esattamente per questo. Espone un'API cloud adatta all'automazione e al CI, quindi il passaggio di traduzione del tuo workflow diventa una richiesta che consegna il .po e ne riceve uno tradotto, senza cicli per stringa. Il suo Syntax Locking mantiene %s, %1$s, {count}, HTML e i token di codice in posizione automaticamente – l'intera classe di bug della sezione precedente è gestita dal motore anziché da regex che mantieni tu. Con il pieno supporto Gettext per plurali e msgctxt, le forme plurali e il contesto sopravvivono al ciclo di andata e ritorno, cosa che una chiamata di completamento chat non può garantire.
Idempotenza e il Gate di Revisione Rimangono Tuoi
Due decisioni di progettazione rimangono tue, indipendentemente dal motore che utilizzi. Primo, l'idempotenza: continua a tradurre solo le voci vuote dopo msgmerge, in modo che i merge no-op non producano alcun diff. Secondo, un gate di revisione: fai in modo che il job apra una pull request, come fa lo scheletro qui sopra, piuttosto che committare direttamente su main. La traduzione automatica è eccellente per rendere le stringhe rapidamente disponibili, ma un'occhiata umana prima del merge cattura la rara mancanza di contesto – e una PR ti offre quell'occhiata senza bloccare il caso comune. I team che gestiscono molte lingue o molti siti client riconosceranno questo schema da il workflow di localizzazione ideale per le agenzie, dove lo stesso modello di automazione e poi revisione si adatta a decine di progetti.
Conclusione
Per automatizzare la traduzione in CI/CD senza rilasciare build rotte, il modello è coerente: rigenera il .pot al merge, msgmerge in ogni locale per far emergere solo le nuove stringhe, traduci solo quelle stringhe e committa il risultato dietro un gate di revisione di pull request. L'idempotenza mantiene i tuoi diff puliti; il gate di revisione tiene la rara traduzione errata fuori dalla produzione.
La parte da fare bene è il passaggio di traduzione stesso. Le chiamate LLM create manualmente corromperanno i segnaposto e le forme plurali in modi che i tuoi test non cattureranno, e spenderai più tempo a mantenere il 'collante' di traduzione che il codice della funzionalità che serve. Un motore basato su API con Syntax Locking rimuove completamente questa modalità di fallimento, così la tua pipeline traduce nuove stringhe sullo stesso merge che le ha introdotte – e i tuoi utenti non-inglesi smetteranno di vedere segnaposto in inglese.
Pronto ad automatizzare la traduzione nella tua pipeline senza rompere i segnaposto? Prova SimplePoTranslate gratuitamente — nessuna carta di credito richiesta. Inizia con il livello gratuito, convalida l'API con i tuoi file
.poe collegala al CI quando sei pronto.