CommunityCodierung & Entwicklunggithub.com

wp-plugin-i18n-release

Bereitet ein in plugins.svn.wordpress.org gehostetes WordPress-Plugin für die vollständige Internationalisierung vor und veröffentlicht das Release im SVN. Deckt ab: Umschreiben von hartcodierten spanischen Strings ins Englische (PHP und JS), Erstellung einer .pot-Datei mit wp-cli, Erstellung initialer Übersetzungen .po/.mo (z.B. neutrales Spanisch), synchronisiertes Versions-Bumping, Commit ins trunk und Erstellung eines Tags.

Was ist wp-plugin-i18n-release?

Diese Fähigkeit automatisiert den vollständigen Internationalisierungs- und Veröffentlichungs-Workflow für WordPress-Plugins, die auf plugins.svn.wordpress.org gehostet werden. Sie ist speziell für Situationen konzipiert, in denen übersetzbare Strings hartcodiert auf Spanisch sind, und sperrt so andere Locales wie Französisch, Deutsch oder Japanisch aus. Die Fähigkeit scannt PHP- und JS-Dateien, lokalisiert alle i18n-Funktionsaufrufe, schreibt hartcodierte spanische Strings gemäß einer bereitgestellten Übersetzungstabelle ins Englische um, generiert eine .pot-Vorlage mit wp-cli und erstellt initiale .po- und .mo-Dateien für neutrales Spanisch. Außerdem bumpt sie synchronisiert die Plugin-Version in Header, Konstanten, readme.txt und CHANGELOG, bereinigt das Build-Verzeichnis von Entwicklungsdateien und führt einen SVN-Commit ins trunk und einen SVN-Tag durch. Die Fähigkeit behandelt häufige Fallstricke wie PowerShell-UNC-Pfade, UTF-8-Kodierungsprobleme unter Windows und SVN-Working-Copy-Probleme nach einem Tag-Erstellung. Plattform: primär für Windows PowerShell, aber die Konzepte sind auf jedes Betriebssystem übertragbar. Komponenten: TortoiseSVN (svn.exe), PHP 8.x, wp-cli.phar und SVN-Zugangsdaten vom WP.org-Plugin-Team werden vorausgesetzt.

Funktioniert mit~Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/leoarayas/agent-skills/tree/main/wp-plugin-i18n-release

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

WordPress-Plugin: Vollständige i18n + Release ins .org-SVN

Wann verwenden

  • Neu genehmigtes Plugin auf WP.org, das für translate.wordpress.org bereit sein muss.
  • Übersetzbare Strings (__(), _e(), wp.i18n.__(), etc.) sind hartcodiert auf Spanisch und sperren andere Locales (fr, de, pt, ja, etc.) in GlotPress.
  • Eine initiale Übersetzung oder eine erste .pot-Datei muss hinzugefügt werden.
  • Jedes Release, das die Version erhöht und im SVN von plugins.svn.wordpress.org veröffentlicht wird.

Voraussetzungen

KomponenteÜberprüfungFehlt?
TortoiseSVN (svn.exe)Test-Path "C:\Program Files\TortoiseSVN\bin\svn.exe"Installieren von https://tortoisesvn.net/downloads.html (Haken bei "Command Line Tools" setzen)
PHP 8.x im PATHphp --version von einem Nicht-UNC-VerzeichnisHerd legacy ist okay; oder eigenständiges PHP
wp-cli.pharHerunterladen von https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.pharInvoke-WebRequest -Uri ... -OutFile wp-cli.phar
SVN-Zugriff auf das PluginE-Mail zur Genehmigung von [email protected] mit SVN-URL, Benutzername und PasswortBeim Team anfragen, falls nicht vorhanden

Kompletter Workflow

  1. Umgebung und Plugin überprüfen
  2. SVN-Checkout des Plugins
  3. Übersetzbare Strings im Code lokalisieren (PHP + JS)
  4. Strings ins Englische umschreiben unter Beibehaltung der technischen Semantik
  5. .pot-Datei neu generieren mit wp i18n make-pot
  6. .po + .mo erstellen der initialen Übersetzung (z.B. neutrales Spanisch)
  7. Synchronisierte Version erhöhen (Header Version, Konstante, readme stable tag, CHANGELOG)
  8. Sauberen Build neu generieren unter Ausschluss von Entwicklungsdateien (.distignore)
  9. Commit ins trunk + Tag im SVN erstellen
  10. (Optional) Lokales Verzeichnis synchronisieren unter Beibehaltung von Git-Dateien

1. Umgebung und Plugin überprüfen

# SVN unter Windows (normalerweise nicht im PATH; vollständigen Pfad verwenden oder hinzufügen)
$env:Path = "$env:ProgramFiles\TortoiseSVN\bin;$env:Path"
svn --version

# PHP
php --version

Vor dem Ändern von Code: Plugin lesen:

  • Plugin-Header (Name, Version, Text Domain, Domain Path)
  • readme.txt (Stable tag, Changelog)
  • CHANGELOG.md (falls vorhanden)
  • Liste der PHP/JS-Dateien in includes/ und assets/

2. SVN-Checkout

$svnUser = '<wp-org-user>'       # WP.org-Benutzername (Groß-/Kleinschreibung beachten)
$svnPass = 'svn_XXXXX...'     # Von "Account & Security" in profiles.wordpress.org
$slug    = 'mein-plugin'        # Der Plugin-Slug
$checkout = "C:\Temp\opencode\$slug-svn"

svn checkout --non-interactive --trust-server-cert `
  --username $svnUser --password $svnPass `
  "https://plugins.svn.wordpress.org/$slug" $checkout

SVN enthält bereits trunk/, tags/, assets/. Wenn Sie gerade das erste Release hochgeladen haben, ist tags/ leer und trunk/ ebenfalls (gerade mit dem initialen trunk erstellt).

3. Übersetzbare Strings lokalisieren

Identifizieren Sie ALLE Aufrufe von i18n-Funktionen. Verwenden Sie grep mit diesen Mustern:

# PHP
Select-String -Path 'includes/*.php' -Pattern '__\(|_e\(|_x\(|esc_html__\(|esc_attr__\(|esc_html_e\(|esc_attr_e\(|_n\(|_nx\('

# JS (wp.i18n oder hartcodierte Strings ohne Funktion)
Select-String -Path 'assets/js/*.js' -Pattern 'wp\.i18n|__\('
Select-String -Path 'assets/js/*.js' -Pattern '"[^"]{6,80}"'   # erkennt hartcodierte Strings

Häufiges Anti-Pattern: spanische Strings in HTML, das in JS konkateniert wird (z.B. html += '<option>Todas</option>';). Umschreiben ins Englische ist direkt gültig; die Verwendung von wp.i18n.__() ist besser, wenn sie zur Laufzeit übersetzbar sein sollen.

4. Strings ins Englische umschreiben

Strenge Regeln:

  1. Übersetzen Sie NUR das erste Argument der i18n-Funktionen. Berühren Sie NICHT die Text-Domain (zweites Argument).
  2. Berühren Sie NICHTS außerhalb eines i18n-Aufrufs.
  3. Ändern Sie NICHT das PHP-Format (Leerzeichen, Anführungszeichen, Klammern).
  4. Technische Begriffe wie ExampleStore, WooCommerce, API, Correlation ID, Premium, JSON, HTTP, URL, CLP bleiben auf Englisch (sie sind bereits Eigennamen / Akronyme).
  5. BEHALTEN Sie Platzhalter von sprintf/printf (%s, %d, %1$s, etc.) exakt gleich bei.
  6. Wenn ein String bereits auf Englisch ist, berühren Sie ihn NICHT.

Empfohlene Übersetzungstabelle (an den Kontext anpassen):

SpanischEnglisch
"Activo""Enabled"
"Título""Title"
"Configurar""Configure"
"Guardar""Save"
"Eliminar""Delete"
"Comuna""Commune"
"Región""Region"
"Selecciona una región""Select a region"
"Sin reglas guardadas""No saved rules"
"Configura la URL de API y el token""Configure API URL and token"
"Diagnóstico ejecutado correctamente""Diagnostic executed successfully"
"No se pudo {verbo}""Could not {verb}"
"Debes ingresar X""You must enter X"
"Cotización API recibida""API quote received"
"Tarifa por defecto (CLP)""Default rate (CLP)"

Bei großen Dateien: Delegieren Sie an einen Agenten mit genauen Anweisungen und der Übersetzungstabelle.

5. .pot mit wp-cli neu generieren

# Vom Plugin-Verzeichnis (lokaler Spiegel)
$wpCli = 'C:\Temp\opencode\wp-cli.phar'
php $wpCli i18n make-pot . "languages/mein-plugin.pot" --domain="mein-plugin"

Die .pot-Datei muss sich in /languages/ mit dem Namen <text-domain>.pot befinden.

6. Übersetzung .po + .mo erstellen

Entscheidende Frage: Welches Locale? Damit das Plugin automatisch für alle spanischsprachigen Nutzer ohne regionale Abweichungen übersetzt wird, verwenden Sie <text-domain>-es.po (Wurzel es). WordPress führt ein kaskadierendes Fallback durch: es_CL → es → Englisch.

Empfohlene Strategie:

  • es.po/.mo (Wurzel) → bedient es_CL, es_ES, es_MX, es_AR, es_PE, etc.
  • (Optional später) es_CL.po/.mo spezifisch für Chile mit lokalen Redewendungen.

Erstellen der .po-Datei: Verwenden Sie ein PHP-Skript, das die .pot-Datei einliest und ein Array von Übersetzungen EN→ES anwendet. Verwenden Sie mb_chr(0x00f3) für akzentuierte Zeichen (PHP unter Windows hat Probleme mit der Codepage bei UTF-8-Literalen).

// build-es.php
declare(encoding='UTF-8');
$pot = file_get_contents('languages/mein-plugin.pot');
$po_es = 'languages/mein-plugin-es.po';

// `mb_chr` für akzentuierte Zeichen vorladen
function A() { return mb_chr(0x00e1); } // á
function E() { return mb_chr(0x00e9); } // é
function O() { return mb_chr(0x00f3); } // ó
// usw.

$t = [
    "Configure API URL and token" => "Configura la URL de API y el token",
    // ...
];

$header = "msgid \"\"\nmsgstr \"\"\n"
        . "\"Project-Id-Version: Mi Plugin 1.0.0\\n\"\n"
        . "\"Language-Team: Español (neutro) <>\\n\"\n"
        . "\"Language: es\\n\"\n"
        . "\"Plural-Forms: nplurals=2; plural=(n != 1);\\n\"\n";

// .pot parsen, msgstr mit $t füllen, .po schreiben
// (vollständige Logik: siehe wp-plugin-i18n-release/build-es.php)

.mo kompilieren:

php $wpCli i18n make-mo languages/

Dies erstellt automatisch languages/<text-domain>-es.mo.

7. Synchronisierte Version erhöhen

Aktualisieren Sie vier Dateien:

// 1. my-plugin.php (Header)
 * Version: 1.1.0

// 2. my-plugin.php (Konstante)
define('PLUGIN_VERSION', '1.1.0');

// 3. readme.txt
Stable tag: 1.1.0
/* + neuer Eintrag in == Changelog == */

// 4. CHANGELOG.md
## [1.1.0] - 2026-09-14
### Changed
- ...

8. Sauberen Build neu generieren (Entwicklungsdateien ausschließen)

Die .distignore-Datei des Plugins definiert, was ausgeschlossen wird. Wenn sie nicht existiert, verwenden Sie diese Standardliste:

$exclude = @('.git','.github','.gitignore','.gitattributes','.distignore',
             '.idea','.DS_Store','.release-build','bin','node_modules',
             'tests','vendor/bin','phpcs.xml*','phpunit.xml*',
             '.phpunit.result.cache','*.lock','*.log','*.zip',
             'README.md','RELEASING.md','Makefile','.pr-body-*.md')

# Ziel bereinigen, alles kopieren, Ausgeschlossenes löschen
$src  = 'pfad/spiegel/plugin'
$dist = 'pfad/build/plugin'
Copy-Item -Path "$src\*" -Destination $dist -Recurse -Force
foreach ($pat in $exclude) {
  Get-ChildItem -Path $dist -Recurse -Force -Filter $pat -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force
}

9. Commit ins trunk + Tag erstellen

$env:Path = "$env:ProgramFiles\TortoiseSVN\bin;$env:Path"

# trunk mit sauberem Build ersetzen
$trunk = "C:\Temp\opencode\$slug-svn\trunk"
Get-ChildItem -Path $trunk -Force | Where-Object { $_.Name -ne '.svn' } | Remove-Item -Recurse -Force
Copy-Item -Path "$dist\*" -Destination $trunk -Recurse -Force

# svn add + commit
Set-Location $trunk
svn add --force --depth infinity .

svn commit --non-interactive --trust-server-cert `
  --username $svnUser --password $svnPass `
  -m "Release 1.1.0: English source strings, full i18n rewrite, initial Spanish (es) translation"

# Tag erstellen (remote svn copy)
svn copy --non-interactive --trust-server-cert `
  --username $svnUser --password $svnPass `
  -m "Tagging 1.1.0" `
  "https://plugins.svn.wordpress.org/$slug/trunk" `
  "https://plugins.svn.wordpress.org/$slug/tags/1.1.0"

Nach dem remote Tag: Lokales Update erzwingen (neue Tags werden in der Working Copy nicht vollständig materialisiert):

svn cleanup
svn update --depth infinity --force --non-interactive --trust-server-cert `
  --username $svnUser --password $svnPass "$trunk/../"

10. (Optional) Lokales Verzeichnis synchronisieren

Behalten Sie Dateien bei, die NICHT im SVN-Export sind (.git/, .gitignore, tests/, bin/, etc.):

$local    = 'C:\Users\...\wp-content\plugins\mein-plugin'
$exportDir = 'C:\Users\...\export-1.1.0'

# Export des neu erstellten Tags
svn export "https://plugins.svn.wordpress.org/$slug/tags/1.1.0" $exportDir

# NUR die Release-Dateien aus dem lokalen Verzeichnis löschen, den Rest behalten
$releaseNames = (Get-ChildItem $exportDir -Force).Name
foreach ($name in $releaseNames) {
  $localPath = Join-Path $local $name
  if (Test-Path $localPath) { Remove-Item $localPath -Recurse -Force }
}

# Export über das lokale Verzeichnis kopieren
Copy-Item -Path "$exportDir\*" -Destination $local -Recurse -Force

11. Abschließende Überprüfung

# Versionen im lokalen Verzeichnis
Write-Host "header: " (Get-Content "$local\mein-plugin.php" | Select-String -Pattern 'Version:' | Select-Object -First 1).ToString().Trim()
Write-Host "readme: " (Get-Content "$local\readme.txt" | Select-String -Pattern 'Stable tag:' | Select-Object -First 1).ToString().Trim()

# Remote SVN überprüfen
svn ls --recursive "https://plugins.svn.wordpress.org/$slug/tags/1.1.0/"

Wichtige Konventionen von WordPress.org

KonzeptRegel
Text DomainMuss identisch mit dem Plugin-Slug sein (z.B. mein-plugin). Ändern Sie den Slug niemals ohne erneute Genehmigung des Plugins.
Domain Path/languages/ damit WP.org die .pot-Datei findet
Plugin Name HeaderKeine Marken Dritter am Anfang (WP.org-Prüfung lehnt ab)
readme.txtWP.org parst diese Datei (nicht README.md). Der Stable tag muss mit der Version übereinstimmen.
SVN-Layout/trunk/ (Entwicklung), /tags/X.Y.Z/ (Releases), /assets/ (Banner, Icons, Screenshots)
SVN als Release-System"Nur gebrauchsfertige Versionen pushen". Keine häufigen Entwicklungs-Commits in den trunk.
Fallback von ÜbersetzungenWP sucht kaskadierend: text-domain-locale.mo → text-domain.mo → text-domain-en_US.mo (Core). Das Wurzel-Locale es bedient ALLE Varianten es_XX.

Häufige Fallstricke und Fehler

PowerShell und UNC-Pfade

PHP und viele Binärdateien schlagen fehl, wenn das CWD ein UNC-Pfad ist (\\server\share). Vor dem Ausführen von Befehlen:

Set-Location C:\Users\<Benutzername>   # oder ein beliebiges lokales Verzeichnis
php $wpCli ...                # funktioniert jetzt

Kodierung akzentuierter Zeichen in PHP (Windows)

PHP unter Windows hat Probleme mit UTF-8-Literalen in Skripten. Lösung: Verwenden Sie mb_chr(0x00f3) für jedes akzentuierte Zeichen:

"Obtener pa" . mb_chr(0x00ed) . "s"  // "Obtener país"

PowerShell kann bei Get-Content ebenfalls ? anstelle von akzentuierten Zeichen anzeigen. Überprüfen Sie die Bytes der Datei, nicht die Darstellung:

$bytes = [System.IO.File]::ReadAllBytes('datei.po')
# Suche nach 0xC3 0xB3 (UTF-8 von 'ó')

SVN-Working-Copy scheint nach einem neuen Tag leer zu sein

SVN dedupliziert Dateien zwischen trunk und tag (gleicher "Blob"). Nach einem remote svn copy erscheinen die Dateien auf dem Server, aber die lokale Working Copy hat Platzhalter. Lösung: svn cleanup + svn update --depth infinity --force.

svn.exe ist nicht im PATH

TortoiseSVN wird in C:\Program Files\TortoiseSVN\bin\ installiert, fügt svn.exe aber standardmäßig nicht zum PATH hinzu. Temporäre Lösung:

$env:Path = "$env:ProgramFiles\TortoiseSVN\bin;$env:Path"

Oder dauerhaft zum PATH des Benutzers hinzufügen.

Das Plugin verwendet spanische Strings im Header

Die Strings des Plugin-Headers (Plugin Name, Description, etc.) sind NICHT übersetzbar. Wenn wp i18n sie jedoch in die .pot-Datei aufnimmt, lassen Sie sie mit msgstr "" (leer) stehen. WP.org und GlotPress wissen, dass sie nicht übersetzt werden.

Keine .po/.mo für von GlotPress verwaltete Locales einfügen

Sobald GlotPress Übersetzungen für Ihr Plugin hat (durch die Community), stellt WP.org automatisch die .mo-Dateien bereit. Ihre initialen .po/.mo sind nur der anfängliche Seed. Kämpfen Sie nicht gegen GlotPress.


Dateien, die durch das Release geändert wurden (Checkliste)

  • my-plugin.php — Header Version + PLUGIN_VERSION
  • readme.txt — Stable tag + Eintrag im Changelog
  • CHANGELOG.md — neuer Eintrag
  • languages/<text-domain>.p...

... (abgeschnitten für die Übersetzung

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Verwandte Skills