FunktionenPluginPreiseRessourcen
Sprache ändern
RessourcenSo automatisieren Sie die .po-Übersetzung in Ihrer CI/CD-Pipeline

So automatisieren Sie die .po-Übersetzung in Ihrer CI/CD-Pipeline

SimplePoTranslate Team9. Juni 2026
So automatisieren Sie die .po-Übersetzung in Ihrer CI/CD-Pipeline

Ihr Team führt vierzehnmal täglich Merges nach main durch. Jeder dieser Merges kann einen neuen, dem Benutzer angezeigten String hinzufügen – ein Schaltflächentext, eine Fehlermeldung, ein Tooltip. Und jeder dieser Strings existiert zunächst nur auf Englisch. Irgendwo in Ihrem Release-Prozess muss ein Mensch die neuen Strings bemerken, exportieren, übersetzen lassen, wieder einfügen und neu kompilieren. Dieser Mensch ist ein Engpass, und in einem schnell liefernden Team bedeutet dieser Engpass, dass Ihre deutschen Benutzer zwei Sprints lang englische Platzhalter sehen.

Die Lösung besteht darin, die Übersetzung in Ihrer CI/CD-Pipeline zu automatisieren, sodass neue Strings mit demselben Merge übersetzt werden, der sie eingeführt hat – kein Mensch im kritischen Pfad für den Routinefall. Dies ist heute vollständig erreichbar, aber nur, wenn Sie die Falle vermeiden, in die die meisten Teams tappen: das manuelle Erstellen von rohen LLM-Aufrufen, die still und leise Ihre %s-Platzhalter und die .po-Struktur beschädigen. Dieser Leitfaden führt Sie durch ein realistisches CI-Pipeline-Muster, ein funktionierendes GitHub Actions-Skelett und die Designentscheidungen – Idempotenz, nur-neue-übersetzen, Review-Gates –, die eine hilfreiche Pipeline von einer unterscheiden, die fehlerhafte Builds ausliefert.

Warum manuelle Übersetzung ein Release-Engpass ist

Die Antwort auf die Frage „warum nicht einfach vor jedem Release übersetzen“ ist, dass der Zeitpunkt nie übereinstimmt. Strings werden kontinuierlich von Entwicklern hinzugefügt, aber die Übersetzung erfolgt in Batches durch eine andere Person nach einem anderen Zeitplan. Die Lücke zwischen diesen beiden Rhythmen ist der Ort, an dem sich Ihre Lokalisierungs-Schulden ansammeln.

Das Zwei-Rhythmen-Problem

Stellen Sie sich den manuellen Ablauf vor. Ein Entwickler fügt __( 'Export to CSV', 'mytextdomain' ) hinzu und merged. Niemand generiert die .pot neu. Zwei Wochen später führt jemand wp i18n make-pot aus, bemerkt vierzig neue, unübersetzte Strings (einige von Entwicklern, die inzwischen in den Urlaub gefahren sind), errät die Absicht der Hälfte davon und sendet eine .po an einen Übersetzer. Die Übersetzung kommt zurück, wird eingefügt, und vielleicht haben die Platzhalter überlebt und vielleicht auch nicht. In der Zwischenzeit wurden drei Releases mit diesen Strings auf Englisch ausgeliefert.

Jeder Schritt ist manuell, batch-basiert und fehleranfällig. Das Ziel der CI/CD-Automatisierung ist es, dies in etwas zu verwandeln, das automatisch beim Merge ausgeführt wird, nur das übersetzt, was tatsächlich geändert wurde, und laut fehlschlägt, wenn etwas falsch aussieht – wodurch die Übersetzung von einer periodischen Aufgabe zu einem unsichtbaren Teil der Pipeline wird.

Das Pipeline-Muster: Extrahieren, Diff, Übersetzen, Committen

Auf einer höheren Ebene führt ein automatisierter Übersetzungsjob vier Schritte beim Merge nach main aus: die Vorlage neu generieren, erkennen, was neu ist, nur diese Strings übersetzen und die Ergebnisse zurückcommitten. Das Ganze sollte idempotent sein – das Ausführen bei einem Merge ohne String-Änderungen darf keinen Diff und keine Störungen verursachen.

Extrahieren und Diff

Schritt eins ist die Extraktion. Generieren Sie die .pot aus der aktuellen Quelle neu, sodass sie jeden String in der Codebasis widerspiegelt:

wp i18n make-pot . languages/myplugin.pot

Schritt zwei ist der Diff. Dies ist die wichtigste Designentscheidung in der gesamten Pipeline. Sie möchten nicht bei jedem Merge jeden String neu übersetzen – das verschwendet API-Aufrufe, birgt das Risiko, Strings neu zu übersetzen, die ein Mensch bereits korrigiert hat, und erzeugt enorme Review-Diffe. Stattdessen mergen Sie die frische .pot in jede vorhandene .po und übersetzen nur die Einträge, die jetzt leer sind (die tatsächlich neuen Strings):

# 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

Nach msgmerge haben nur brandneue Strings einen leeren msgstr. Alles zuvor Übersetzte bleibt unberührt. Diese Eigenschaft macht die Pipeline idempotent und hält Ihre Review-Diffe klein und überprüfbar.

Übersetzen und Committen

Schritt drei sendet nur diese leeren Einträge an einen Übersetzungsschritt. Schritt vier committet die aktualisierte .po, kompiliert .mo und generiert jegliche JSON neu. Als Nächstes werden wir all dies in GitHub Actions integrieren.

Ein GitHub Actions Skelett

Hier ist die Antwort auf die Frage „wie sieht das eigentlich in einer Workflow-Datei aus“: ein Job, der bei einem Push nach main ausgelöst wird, den Zyklus aus Extrahieren-Diff-Übersetzen-Committen ausführt und einen Pull Request mit den Ergebnissen öffnet, anstatt direkt nach main zu committen.

Die Workflow-Datei

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"

Wo die eigentliche Arbeit steckt

Der Schritt translate-new-strings.sh ist der Ort, an dem die eigentliche Übersetzung stattfindet. Die naive Version dieses Skripts liest jeden leeren Eintrag, sendet ihn einzeln an eine LLM-API und fügt die Antwort zurück ein. Diese naive Version ist genau die Falle, und es lohnt sich, explizit zu sagen, warum.

Warum selbst geschriebene LLM-Aufrufe Ihre Dateien beschädigen

Die kurze Antwort: Rohe LLM-Aufrufe behandeln Ihre .po-Strings als Prosa, und Ihre .po-Strings sind keine Prosa – sie sind strukturierte Daten mit Platzhaltern, Pluralformen und Kontext, die ein Chat-Completion-Aufruf gerne zerstört.

Die Platzhalter-Beschädigung, die Sie in Tests nicht sehen werden

Senden Sie Deleted %d of %s files an einen allgemeinen Chat-Endpunkt und Sie könnten Supprimé %d des %s fichiers (gut) oder Supprimé %d de % s fichiers zurückerhalten (ein Leerzeichen ist in den Platzhalter gerutscht, und jetzt wirft sprintf() zur Laufzeit einen Fehler). Senden Sie einen Plural-Eintrag und das Modell kann zwei Formen zu einer zusammenfassen, was Sprachen mit mehr als zwei Pluralkategorien beschädigt. Senden Sie einen String mit <a href="%s"> und das Modell kann die URL übersetzen oder das Tag fallen lassen. Keiner dieser Fehler taucht in Ihren Tests auf, es sei denn, Sie testen explizit die gerenderte Ausgabe in jedem Locale – sie zeigen sich als Laufzeitfehler in der Produktion für Benutzer, deren Fehlerberichte Sie nicht lesen können.

Die Wartungsfalle

Sie können versuchen, sich dagegen mit Prompt Engineering und Regex-Nachbearbeitung zu wehren, und viele Teams tun dies auch. Das Problem ist, dass Sie nun als Nebenprojekt eine anfällige Übersetzungs-Engine warten und jeden Platzhalter-Randfall neu entdecken, den das Gettext-Ökosystem bereits gelöst hat. Wir katalogisieren die spezifischen Wege, wie Variablen verfälscht werden – und wie man sie verhindert – in PO-Dateien übersetzen, ohne Code-Variablen zu beschädigen. Die dortige Lehre gilt direkt: Die Modellqualität ist selten das Problem; die strukturelle Handhabung darum herum ist es.

Einen API-gesteuerten Cloud-Übersetzer in CI integrieren

Hier ersetzt ein API-gesteuerter Übersetzungsdienst Ihr translate-new-strings.sh-Ratespiel. Anstatt manuelle LLM-Aufrufe und Regex-Nachbearbeitung zu betreiben, lädt Ihr CI-Schritt die geänderte .po an einen Dienst hoch, der die Gettext-Struktur bereits versteht und eine saubere Ausgabe zurückgibt. Die Pipeline-Form bleibt identisch – Extrahieren, Diff, Übersetzen, Committen – aber der anfällige Zwischenschritt wird zu einem einzigen API-Aufruf.

Der API-Aufruf, der Ihr Skript ersetzt

SimplePoTranslate ist genau dafür gemacht. Es bietet eine Cloud-API, die für Automatisierung und CI geeignet ist, sodass der Übersetzungsschritt Ihres Workflows zu einer Anfrage wird, die die .po übergibt und eine übersetzte zurückerhält, ohne Schleifen pro String. Sein Syntax Locking hält %s, %1$s, {count}, HTML und Code-Tokens automatisch an ihrem Platz – die gesamte Fehlerklasse aus dem vorherigen Abschnitt wird von der Engine und nicht von selbst verwalteten Regex-Ausdrücken behandelt. Mit vollständiger Gettext Plural- und msgctxt-Unterstützung überleben Pluralformen und Kontext den Roundtrip, was ein Chat-Completion-Aufruf nicht garantieren kann.

Idempotenz und das Review-Gate bleiben Ihnen erhalten

Zwei Designentscheidungen liegen immer noch bei Ihnen, unabhängig davon, welche Engine Sie verwenden. Erstens, Idempotenz: Übersetzen Sie weiterhin nur die leeren Einträge nach msgmerge, damit No-Op-Merges keinen Diff erzeugen. Zweitens, ein Review-Gate: Lassen Sie den Job einen Pull Request öffnen, wie es das obige Skelett tut, anstatt direkt nach main zu committen. Maschinelle Übersetzung ist hervorragend, um Strings schnell live zu schalten, aber ein menschlicher Blick vor dem Merge fängt die seltene Kontextverfehlung ab – und ein PR ermöglicht Ihnen diesen Blick, ohne den häufigen Fall zu blockieren. Teams, die viele Locales oder viele Kunden-Websites verwalten, werden diese Form aus dem idealen Lokalisierungs-Workflow für Agenturen wiedererkennen, wo dasselbe Automatisieren-und-dann-Review-Muster über Dutzende von Projekten skaliert.

Fazit

Um die Übersetzung in CI/CD zu automatisieren, ohne fehlerhafte Builds auszuliefern, ist das Muster konsistent: die .pot beim Merge neu generieren, sie mit msgmerge in jedes Locale mergen, um nur neue Strings anzuzeigen, nur diese Strings übersetzen und das Ergebnis hinter einem Pull-Request-Review-Gate committen. Idempotenz hält Ihre Diffe sauber; das Review-Gate hält die seltene schlechte Übersetzung aus der Produktion fern.

Der Teil, der richtig gemacht werden muss, ist der Übersetzungsschritt selbst. Selbst geschriebene LLM-Aufrufe werden Platzhalter und Pluralformen auf eine Weise beschädigen, die Ihre Tests nicht erkennen werden, und Sie werden mehr Zeit mit der Wartung der Übersetzungs-„Klebstoffe“ verbringen als mit dem Feature-Code, dem sie dienen. Eine API-gesteuerte Engine mit Syntax Locking beseitigt diesen gesamten Fehlermodus, sodass Ihre Pipeline neue Strings mit demselben Merge übersetzt, der sie eingeführt hat – und Ihre nicht-englischen Benutzer keine englischen Platzhalter mehr sehen.

Bereit, die Übersetzung in Ihrer Pipeline zu automatisieren, ohne Platzhalter zu beschädigen? Testen Sie SimplePoTranslate kostenlos – keine Kreditkarte erforderlich. Beginnen Sie mit dem kostenlosen Tarif, validieren Sie die API anhand Ihrer eigenen .po-Dateien und integrieren Sie sie in Ihre CI, wenn Sie bereit sind.