FonctionnalitésPluginTarifsRessources
Changer de langue
RessourcesComment automatiser la traduction de fichiers .po dans votre pipeline CI/CD

Comment automatiser la traduction de fichiers .po dans votre pipeline CI/CD

SimplePoTranslate Team9 juin 2026
Comment automatiser la traduction de fichiers .po dans votre pipeline CI/CD

Votre équipe effectue des fusions vers main quatorze fois par jour. Chacune de ces fusions peut ajouter une nouvelle chaîne visible par l'utilisateur – un libellé de bouton, un message d'erreur, une info-bulle. Et chacune de ces chaînes naît uniquement en anglais. À un moment donné de votre processus de publication, un humain doit remarquer les nouvelles chaînes, les exporter, les faire traduire, les coller à nouveau et recompiler. Cet humain est un goulot d'étranglement, et dans une équipe qui livre rapidement, ce goulot d'étranglement signifie que vos utilisateurs allemands voient des marqueurs de position en anglais pendant deux sprints.

La solution consiste à automatiser la traduction dans votre pipeline CI/CD afin que les nouvelles chaînes soient traduites lors de la même fusion qui les a introduites – sans intervention humaine dans le chemin critique pour le cas courant. C'est tout à fait réalisable aujourd'hui, mais seulement si vous évitez le piège dans lequel tombent la plupart des équipes : créer manuellement des appels LLM bruts qui corrompent silencieusement vos marqueurs de position %s et la structure de vos fichiers .po. Ce guide présente un modèle de pipeline CI réaliste, un squelette GitHub Actions fonctionnel et les décisions de conception – idempotence, traduction uniquement des nouveautés, portes de révision – qui séparent un pipeline utile d'un autre qui livre des builds cassés.

Pourquoi la traduction manuelle est un goulot d'étranglement pour la publication

La réponse à la question « pourquoi ne pas simplement traduire avant chaque publication » est que le calendrier ne correspond jamais. Les chaînes sont ajoutées en continu par les développeurs, mais la traduction est effectuée par lots par une autre personne, selon un calendrier différent. L'écart entre ces deux cadences est l'endroit où votre dette de localisation s'accumule.

Le problème des deux cadences

Imaginez le flux manuel. Un développeur ajoute __( 'Export to CSV', 'mytextdomain' ) et effectue une fusion. Personne ne régénère le .pot. Deux semaines plus tard, quelqu'un exécute wp i18n make-pot, remarque quarante nouvelles chaînes non traduites (certaines provenant de développeurs partis en vacances), devine l'intention de la moitié d'entre elles et envoie un fichier .po à un traducteur. La traduction revient, est collée, et peut-être que les marqueurs de position ont survécu, ou peut-être pas. Pendant ce temps, trois versions ont été publiées avec ces chaînes en anglais.

Chaque étape est manuelle, par lots et sujette aux erreurs. L'objectif de l'automatisation CI/CD est de transformer cela en quelque chose qui s'exécute automatiquement lors de la fusion, ne traduit que ce qui a réellement changé, et échoue bruyamment lorsque quelque chose ne va pas – transformant la traduction d'une tâche périodique en une partie invisible du pipeline.

Le modèle de pipeline : Extraire, Diff, Traduire, Commettre

À un niveau élevé, une tâche de traduction automatisée exécute quatre étapes lors de la fusion vers main : régénérer le modèle, détecter ce qui est nouveau, traduire uniquement ces chaînes et réintégrer les résultats. L'ensemble doit être idempotent – l'exécuter sur une fusion sans modification de chaîne doit produire un diff nul et zéro bruit.

Extraction et Diff

La première étape est l'extraction. Régénérez le .pot à partir de la source actuelle afin qu'il reflète chaque chaîne de la base de code :

wp i18n make-pot . languages/myplugin.pot

La deuxième étape est le diff. C'est la décision de conception la plus importante de tout le pipeline. Vous ne voulez pas retraduire chaque chaîne à chaque fusion – cela gaspille des appels API, risque de retraduire des chaînes déjà corrigées par un humain et produit d'énormes diffs de révision. Au lieu de cela, vous fusionnez le nouveau .pot dans chaque fichier .po existant et ne traduisez que les entrées qui sont maintenant vides (les chaînes véritablement nouvelles) :

# 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

Après msgmerge, seules les chaînes entièrement nouvelles ont une msgstr vide. Tout ce qui a été précédemment traduit reste inchangé. C'est cette propriété qui rend le pipeline idempotent et qui maintient vos diffs de révision petits et vérifiables.

Traduire et Commettre

La troisième étape envoie uniquement ces entrées vides à une étape de traduction. La quatrième étape commet le fichier .po mis à jour, compile le .mo et régénère tout fichier JSON. Nous allons ensuite intégrer tout cela dans GitHub Actions.

Un squelette GitHub Actions

Voici la réponse à la question « à quoi cela ressemble-t-il réellement dans un fichier de workflow » : une tâche déclenchée lors d'un push vers main qui exécute le cycle d'extraction-diff-traduction-commit et ouvre une pull request avec les résultats plutôt que de commettre directement vers main.

Le fichier de 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"

Là où le vrai travail se cache

L'étape translate-new-strings.sh est l'endroit où la traduction réelle a lieu. La version naïve de ce script lit chaque entrée vide, l'envoie à une API LLM une chaîne à la fois, et colle la réponse. Cette version naïve est précisément le piège, et il est utile d'expliquer pourquoi.

Pourquoi les appels LLM faits à la main cassent vos fichiers

La réponse courte : les appels LLM bruts traitent vos chaînes .po comme de la prose, et vos chaînes .po ne sont pas de la prose – ce sont des données structurées avec des marqueurs de position, des formes plurielles et un contexte qu'un appel de complétion de chat détruit allègrement.

La corruption des marqueurs de position que vous ne verrez pas dans les tests

Envoyez Deleted %d of %s files à un point de terminaison de chat général et vous pourriez obtenir Supprimé %d des %s fichiers (correct) ou Supprimé %d de % s fichiers (un espace s'est glissé dans le marqueur de position, et maintenant sprintf() lève une exception à l'exécution). Envoyez une entrée plurielle et le modèle peut fusionner deux formes en une seule, ce qui casse les langues ayant plus de deux catégories plurielles. Envoyez une chaîne avec <a href="%s"> et le modèle peut traduire l'URL ou supprimer la balise. Aucune de ces défaillances n'apparaît dans vos tests à moins que vous ne testiez spécifiquement la sortie rendue dans chaque locale – elles apparaissent comme des erreurs d'exécution en production pour des utilisateurs dont vous ne pouvez pas lire les rapports de bogues.

Le piège de la maintenance

Vous pouvez essayer de vous en défendre avec l'ingénierie des prompts et le post-traitement par expressions régulières, et de nombreuses équipes le font. Le problème est que vous maintenez désormais un moteur de traduction fragile comme projet annexe, redécouvrant chaque cas limite de marqueur de position que l'écosystème Gettext a déjà résolu. Nous répertorions les façons spécifiques dont les variables sont altérées – et comment les prévenir – dans traduire des fichiers PO sans casser les variables de code. La leçon s'applique directement : la qualité du modèle est rarement le problème ; c'est la gestion structurelle autour de celui-ci qui l'est.

Intégrer un traducteur cloud basé sur API dans la CI

C'est là qu'un service de traduction basé sur une API remplace vos approximations de translate-new-strings.sh. Au lieu de créer manuellement des appels LLM et de post-traiter avec des expressions régulières, votre étape CI télécharge le fichier .po modifié vers un service qui comprend déjà la structure Gettext et renvoie une sortie propre. La forme du pipeline reste identique – extraire, diff, traduire, commettre – mais l'étape intermédiaire fragile devient un simple appel API.

L'appel API qui remplace votre script

SimplePoTranslate est conçu exactement pour cela. Il expose une API cloud adaptée à l'automatisation et à la CI, de sorte que l'étape de traduction de votre workflow devient une requête qui transmet le fichier .po et en reçoit un traduit, sans boucle par chaîne. Son verrouillage syntaxique maintient automatiquement les %s, %1$s, {count}, HTML et les jetons de code en place – toute la classe de bogues de la section précédente est gérée par le moteur plutôt que par des expressions régulières que vous maintenez. Grâce à la prise en charge complète des formes plurielles Gettext et de msgctxt, les formes plurielles et le contexte survivent à l'aller-retour, ce qu'un appel de complétion de chat ne peut garantir.

L'idempotence et la porte de révision restent vôtres

Deux décisions de conception vous appartiennent toujours, quel que soit le moteur que vous utilisez. Premièrement, l'idempotence : continuez à ne traduire que les entrées vides après msgmerge, de sorte que les fusions sans opération ne produisent aucun diff. Deuxièmement, une porte de révision : faites en sorte que la tâche ouvre une pull request, comme le fait le squelette ci-dessus, plutôt que de commettre directement sur main. La traduction automatique est excellente pour mettre les chaînes en ligne rapidement, mais un coup d'œil humain avant la fusion détecte les rares erreurs de contexte – et une PR vous offre ce coup d'œil sans bloquer le cas courant. Les équipes gérant de nombreuses locales ou de nombreux sites clients reconnaîtront cette approche issue de le workflow de localisation idéal pour les agences, où le même modèle d'automatisation puis de révision s'applique à des dizaines de projets.

Conclusion

Pour automatiser la traduction en CI/CD sans livrer de builds cassés, le modèle est cohérent : régénérez le .pot lors de la fusion, fusionnez-le (msgmerge) dans chaque locale pour ne faire apparaître que les nouvelles chaînes, traduisez uniquement ces chaînes, et commettez le résultat derrière une porte de révision de pull request. L'idempotence maintient vos diffs propres ; la porte de révision empêche les rares mauvaises traductions d'atteindre la production.

La partie à bien faire est l'étape de traduction elle-même. Les appels LLM faits à la main corrompront les marqueurs de position et les formes plurielles d'une manière que vos tests ne détecteront pas, et vous passerez plus de temps à maintenir la 'colle' de traduction qu'au code de fonctionnalité qu'elle sert. Un moteur basé sur API avec verrouillage syntaxique élimine tout ce mode de défaillance, de sorte que votre pipeline traduit les nouvelles chaînes lors de la même fusion qui les a introduites – et vos utilisateurs non anglophones cessent de voir des marqueurs de position en anglais.

Prêt à automatiser la traduction dans votre pipeline sans casser les marqueurs de position ? Essayez SimplePoTranslate gratuitement — aucune carte de crédit requise. Commencez par le niveau gratuit, validez l'API avec vos propres fichiers .po et intégrez-la à votre CI lorsque vous êtes prêt.