Barrierefreiheit ist kein Feature

Der jährliche Global Accessibility Awareness Day ist erst in ein paar Wochen – dieses Jahr feiern wir ihn am 20. Mai 2021 – aber einige neuerliche Diskussionen haben mich dazu gebracht heute zu diesem Thema zu schreiben.

Es ist nicht nur eine Zahl, es sind Menschen!

In einer Diskussion ging es vor Kurzem um die Luca App zur Corona-Kontaktnachverfolgung und mal wieder darum wie wichtig es ist, dass eine solche App barrierefrei sein muss. Ich kann euch gar nicht sagen, wie oft ich Aussagen wie diese schon lesen musste:

Weiterlesen →

WordPress Datenbank reparieren

Anfang der Woche konnte eine Website nicht mehr aufgerufen werden. Der Fehler wies darauf hin, dass die Verbindung zur Datenbank nicht möglich war. Dieser Fehler tritt eigentlich auf, wenn die Zugangsdaten falsch sind. Aber diese wurden nicht verändert und auch in der Konfiguration waren sie noch immer korrekt. Nach der Aktivierung des WPD_EBUG Modus konnte ich dann den Fehler finden. Die Datenbank war korrupt/defekt.

Reparieren der Datenbank mit der WP-CLI

Mein erster Ansatz war die Verwendung der WP-CLI. Hier gibt es eine Option, mit der man die Tabellen einer Datenbank optimieren kann. Hierdurch können auch manchmal Fehler behoben werden:

wp db optimize

Dieses Kommando wird vor allem dann verwendet, wenn sehr viele Zeilen gelöscht wurden, sich dir Größe der Tabelle aber nicht verringert. Es korrigiert aber nicht immer Fehler in Tabellen. Glücklicherweise gibt es ein anderes Kommando für diese Aufgabe:

Weiterlesen →

Kommentare von privaten Beiträgen im Kommentare Widget anzeigen

Im September 2017 hatte ich einen Blogbeitrag dazu geschrieben, wie man Schlagwörter von privaten Beiträgen in der Tag-Cloud anzeigen lassen kann. Vor drei Wochen wurde in einem Kommentar gefragt ob etwas ähnliches auch für Kommentare aus privaten Beiträgen im Kommentare-Widget möglich sei. In diesem Beitrag möchte ich euch zu dieser Fragestellung eine kleine Lösung präsentieren.

Argumente für die Kommentare-Query filtern

Standardmäßig zeigt das Kommentare-Widget nur die letzten fünf Kommentare von öffentlichen Beiträgen an. Die Argumente der Query sehen wie folgt aus:

Weiterlesen →

Detailliert Download-Statistiken für Plugins abrufen

Vor kurzem habe ich die Download-Zahlen für ein Plugin im offiziellen WordPress.org Plugin-Directory nachgeschlagen. Unter „Erweiterte Ansicht“ eines jeden Plugins findet man eine Grafik mit den „Downloads pro Tag“ und den Zahlen aus den letzten 267 Tagen. Sehen wir uns diesen Graphen für das beliebte Antispam Bee Plugin an:

Downloads pro Tag für Antispam Bee

Wenn ihr mit der Maus über den Graphen fahrt, dann findet ihr zu jedem Tag die entsprechenden Downloads von diesem Tag. Ich wollte aber die Summe der Downloads aus den letzten paar Wochen nach der letzten Veröffentlichung wissen (die Spitze im Graphen) und diese manuell niederzuschreiben und zusammenzurechnen wäre dann doch ein wenig zu viel Arbeit gewesen. Wie komme ich also leichter an diese Zahlen heran?

Weiterlesen →

Bessere Sicherheit für WordPress mit sicheren Server-Headern

Es gibt viele Möglichkeiten eine WordPress Website sicherer zu machen. Für manches davon würdet ihr vermutlich zusätzliche Plugins verwenden. Aber es gibt auch einfache Wege zur Erhöhung der Sicherheit, bei denen ihr nur ein paar Server-Einstellungen ändern müsst. Aber bevor ich ins Detail gehe möchte ich erst einmal zeigen, wie man den aktuellen Stand der Sicherheit eurer Seite herausfinden kann.

Mozilla Observatory

Ein hervorragendes Tool zum Testen der Sicherheit einer Website ist das Mozilla Observatory Tool. Dieses Tool scannt nicht nur die Header, die der Server sendet, es analysiert auch TLS und SSH Einstellungen und verwendet einige dritte Tools für einen guten Überblick. Ein Ergebnis eines solchen Scan, bevor Anpassungen gemacht werden, könnte wie folgt aussehen:

Weiterlesen →

Speicherverbrauch debuggen

Letzte Woche wurde ein Problem mit einer Seite berichtet. Dort wurde manchmal auf einer Seite ein 500er Fehler angezeigt, aber leider nicht immer. Nach der Aktivierung des WP_DEBUG Modus konnte ich sehr schnell feststellen, dass das Speicherlimit überschritten wurde. Die einzige Lösung war es, das Speicherlimit zu erhöhen, da die Funktionalität auf dieser Seite viel Speicher brauchte und es keine schnelle Optimierung gab.

In solchen Fällen wäre es dann schön, wenn man rausfinden könnte, wie hoch das Limit erhöht werden muss. Wie viel Speicher verbraucht also eine Seite normalerweise. Es gibt mehre Wege, dies herauszufinden.

Der gefährliche Weg

Eine sehr einfache Lösung wäre es das Speicherlimit erst einmal zu verringern, bis der Fehler jedes Mal auftritt. Dann erhöht man das Limit schrittweise, bis der Fehler nur noch selten auftritt. Dies ist der Wert, um den herum sich der eigentliche Verbrauch bewegen wird. Zu diesem Wert fügt man noch etwas Puffer hinzu, und prüft, ob der Fehler nun nicht mehr auftritt.

Weiterlesen →

Das Debug-Level mit error_reporting setzen

Jeder von euch kennt vermutlich das Problem. Ihr arbeitet an einer Website und es gibt Fehler. Manchmal ist es sogar ein kritischer und ihr seht das hier:

Aber in manchen Fällen tritt der Fehler nicht in jedem Request auf. Dann solltet ihr den Debug-Modus aktivieren und alle Fehler protokollieren lassen.

Den Debug-Modus aktivieren

Um den Debug-Modus von WordPress zu aktivieren, müsst ihr lediglich ein paar Konstanten in der wp-config.php setzen. Das hier sind die Standardwerte:

Weiterlesen →

Das Löschen von eingebundenen Post-Type-Einträgen verhindern

Dies ist sicher ein Problem, in das einige von euch auch bereits gerannt sind. Ihr habt einen Post-Type-Eintrag in eine Seite oder einen Beitrag eingefügt und diesen dann später gelöscht, ohne zu wissen, dass dieser noch irgendwo eingebunden war. In diesen Beitrag will ich am beliebten Kontakt-Formular-Plugin „Contact Form 7“ demonstrieren, wie das verhindert werden kann. Es funktioniert aber natürlich auch mit jedem anderen Inhaltstyp.

Vorbereitung

Wir installieren das Contact Form 7 Plugin, erstellen ein Formular und fügen dieses in eine Seite mit dem mitgelieferten Gutenberg Block ein. Der Inhalt der Seite sieht dann in etwa wie folgt aus:

<!-- wp:contact-form-7/contact-form-selector {"id":39,"title":"Contact form 1"} -->
<div class="wp-block-contact-form-7-contact-form-selector">[contact-form-7 id="39" title="Contact form 1"]</div>
<!-- /wp:contact-form-7/contact-form-selector -->

Wir sehen hier die ID des Post-Types wpcf7_contact_form, die einmal in den Block-Attributen und einmal im inneren Shortcode verwendet wird, den das Plugin noch immer verwendet.

Löschen eines Post-Type-Eintrags

Wenn wir nun zu „Formulare -> Kontaktformulare“ navigieren können wir über die „Mehrfachaktionen“ das Kontaktformular löschen. Öffnen wir im Anschluss die Seite, auf der wir das Formular eingebunden haben im Frontend, erhalten wir folgendes, ziemlich witzige, Resultat:

[contact-form-7 404 "Nicht gefunden"]

Anstelle des Kontakformulars wird also ein „defekter Shortcode“ angezeigt. Für andere Post-Types wird die „Fehlerbehandlung“ eventuell anders aussehen oder im schlimmsten falsche eure Seite zerschießen.

Post-Type-Einträge vor einer Löschung schützen

Wie können wir also nun vermeiden, dass ein Eintrag gelöscht wird, der noch wo anders eingebunden ist? Nun, hierzu müssten wir alle andern Post-Types nach einem solchen Eintrag durchsuchen. Wenn wir hierzu den „Post-Content“ nach Markup durchsuchen, wird das eine recht teure Operation sein. Für manche Einbindungen wird es wohl auch nicht so einfach funktionieren. Wir holen uns daher ein wenig Hilfe, um die Operation schneller und zuverlässiger zu machen.

Verwendung einer „Hilfstaxonomy“

Wir führen eine Taxonomie ein, die uns beim Verhindern einer Löschung hilft. Diese Taxonomie benötigt kein UI und muss auch nicht öffentlich sein. Daher reichen wenige Zeilen aus, um sie zu registrieren:

function deletion_prevention_register_taxonomy() {
	register_taxonomy(
		'deletion_prevention_tax',
		array( 'post' ),
		array(
			'hierarchical' => false,
			'public'       => false,
		)
	);
}
add_action( 'init', 'deletion_prevention_register_taxonomy' );

Wie müssen sie auch nicht für jeden Post-Type registrieren, mit dem wir sei verwenden wollen, die Registrierung für Beiträge reicht aus. Nun können wir diese Taxonomie hinzufügen.

Hilfstaxonomie zu Seiten und Beiträgen hinzufügen

Für unser Beispiel parsen wir jedes Mal, wenn ein Post-Type gespeichert wird alle Blöcke. Finden wir hierbei einen Kontaktformular Block, dann verwenden wir dessen ID als der Namen des Terms:

function deletion_prevention_save_post( $post_ID, $post, $update ) {
	if ( ! in_array( $post->post_type, array( 'post', 'page', true ) ) ) {
		return;
	}

	$blocks = parse_blocks( $post->post_content );

	$forms = array();
	foreach ( $blocks as $block ) {
		if ( 'contact-form-7/contact-form-selector' === $block['blockName'] ) {
			$forms[] = (string) $block['attrs']['id'];
		}
	}

	wp_set_object_terms( $post_ID, $forms, 'deletion_prevention_tax' );
}
add_action( 'save_post', 'deletion_prevention_save_post', 10, 3 );

In der Callback-Funktion limitieren wir die Überprüfung auf Beiträge und Seiten und suchen nach dem contact-form-7/contact-form-selector Block. Wenn ihr das Löschen mehrerer eingebundener Post-Types verhindern wollt, könnten ihr zusätzliche Taxonomien verwenden, einen anderen Namen für den Term oder Metadaten.

Indem wir nun diese Taxonomie speichern, können wir sehr einfach und genau feststellen, wo Kontaktformulare eingebunden wurden. Wollen wir ein solches Formular löschen, können wir dann diese Seiten und Beiträge sehr schnell finden.

Verhinderung der Löschung

Jedes Mal, wenn ein Post-Type-Eintrag gelöscht wird, werden eine Reihe von Actions ausgelöst. Eine davon wird kurz vor der eigentlichen Löschung ausgeführt und hier können wir uns einhängen:

function deletion_prevention_delete_check( $delete, $post, $force_delete ) {
	deletion_prevention_check( $post );
}
add_action( 'pre_delete_post', 'deletion_prevention_delete_check', 10, 3 );

Einige Inhaltstypen unterstützen das Verschieben von Einträgen in den Papierkorb (Contact Form 7 unterstützt dies nicht), es kann also hilfreich sein, auch dies abzufangen:

function deletion_prevention_trash_check( $trash, $post ) {
	deletion_prevention_check( $post );
}
add_action( 'pre_trash_post', 'deletion_prevention_trash_check', 10, 2 );

Jetzt seht ihr auch, weshalb ich eine weiter Funktion für die Überprüfung verwendet habe.

Überprüfung auch aktuelle Einbindungen eines Eintrags

Jetzt sind wir im letzten Schritt. Wir suchen mit Hilfe einer Taxonomy-Query nach Einbettungen des zu löschenden Eintrags in Seiten und Beiträgen, indem wir dessen ID als Term-Slug verwenden:

function deletion_prevention_check( $post ) {
	$args = array(
		'post_type'      => array( 'post', 'page' ),
		'post_status'    => array(
			'publish',
			'pending',
			'draft',
			'future',
			'private',
		),
		'tax_query'      => array(
			array(
				'taxonomy' => 'deletion_prevention_tax',
				'field'    => 'slug',
				'terms'    => (string) $post->ID,
			),
		),
		'posts_per_page' => 1,
		'fields'         => 'ids',

	);
	$posts = get_posts( $args );

	if ( ! empty( $posts ) ) {
		wp_die(
			wp_kses_post(
				sprintf(
					__(
						/* translators: %1$s: link to a filtered posts list, %2$s: link to a filtered pages list */
						'This item as it is still used in <a href="%1$s">posts</a> or <a href="%2$s">pages</a>.',
						'deletion-prevention'
					),
					admin_url( 'edit.php?post_type=post&taxonomy=deletion_prevention_tax&term=' . $post->ID ),
					admin_url( 'edit.php?taxonomy=deletion_prevention_tax&term=' . $post->ID )
				)
			)
		);
	}
}

Wenn diese Query mindestens einen Beitrag oder eine Seite zurück liefert, dann wissen wird, dass der Post-Type-Eintrag noch immer verwendet wird. In diesem Fall unterbrechen wir den aktuellen Request mit einem wp_die, was auch die Löschung unterbindet. In der Nachricht sind zwei Links enthalten, die auf die Listen von Beiträgen bzw. Seiten verweisen, in denen der Eintrag eingebunden ist. Hiermit kann man ihn dann schnell dort entfernen und anschließend gefahrlos löschen.

Fazit

Es passiert sehr leicht, dass man aus Versehen einen Eintrag eines Post-Types löscht, der noch an anderer Stelle verwendet wird. Im Core gibt es leider keine Möglichkeit, so etwas einfach zu verhindern. Durch unsere Hilfstaxonomie können wir dies nun sehr einfach absichern. Der gleiche Ansatz würde auch funktionieren, um das Ändern des Status eines Eintrags in einen „nicht öffentlichen“ Status zu verhindern. Das Löschen von Medieninhalten lässt sich hiermit leider nicht direkt abfangen (obwohl diese auch ein Post-Type sind). Ich hoffe dieser letzte Beitrag für 2020 hilft euch ebenfalls in einem Projekt weiter. Den Quellcode dieses Beitrags findet ihr als Plugin in einem GIST, welches ihr gerne ausprobieren oder für eure Anforderungen anpassen könnt.

Strings zur Übersetzung aus Gutenberg-Blöcken extrahieren

Während der Entwicklung meiner ersten komplexeren Blöcke bin ich in verschiedene Probleme gelaufen. Eines davon war das Extrahieren meiner Strings für Übersetzungen. In meinem vorherigen Beitrag habe ich beschrieben, wie man solche Strings aus PHP-Dateien extrahieren kann. Diese Methoden funktionieren grundsätzlich auch für JavaScript-Dateien, da sie „die gleichen Funktionen“ verwenden, bzw. Funktionen mit einem gleichlautenden Alias.

Strings in einem Gutenberg-Block übersetzen

Schauen wir uns zuerst einmal an wie Strings in einem Block übersetzt werden. Dieses Beispiel stammt aus dem Create a Block Tutorial und zeigt die „Edit“ Komponente:

import { TextControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
 
export default function Edit( { attributes, className, setAttributes } ) {
    return (
        <div className={ className }>
            <TextControl
                label={ __( 'Message', 'gutenpride' ) }
                value={ attributes.message }
                onChange={ ( val ) => setAttributes( { message: val } ) }
            />
        </div>
    );
}

Die __ Funktion wird von der @wordpress/i18n Komponente importiert. Diese Code funktioniert problemlos, um den String in Zeile 8 zu übersetzen. Es schlägt nur fehl, wenn man versucht den String in eine PO-Datei zu exportieren.

Kompilierte JavaScript-Datei

Aber wieso funktioniert das das Beispiel nicht, wenn man versucht die Strings zu extrahieren? Wenn man mit Komponenten wie diesen arbeitet, dann verteilt man den JavaScript Code in der Regel auf mehrere Dateien. Diese importiert dann man dann in eine Haupt-Datei und kompiliert diese in eine einzelne Datei, die an den Browser ausgeliefert wird. Hierzu verwendet man zum Beispiel @wordpress/scripts, das auch im Kapitel the JavaScript Build Setup beschrieben wird. Dieses Skript erstellt dann eine Datei build/index.js und die Strings aus dem Beispiel sehen dann wie folgt aus:

// ...
/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
// ...
function Edit(_ref) {
  var attributes = _ref.attributes,
      className = _ref.className,
      setAttributes = _ref.setAttributes;
  return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
    className: className
  }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__["TextControl"], {
    label: Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__["__"])('Message', 'block-i18n'),
    value: attributes.message,
    onChange: function onChange(val) {
      return setAttributes({
        message: val
      });
    }
  }));
}

In Zeile 11 finden wir wieder die Strings. Allerdings sind sie nicht direkt von der __ Funktion umschlossen. Stattdessen wurden beim Kompilieren sehr merkwürdige Funktionsnamen generiert, die beim Import durch Webpack entstanden sind. Da diese Syntax dem wp i18n make-pot Kommande oder der X-Poedit-KeywordsList in Poedit bekannt ist, können sie beim Parsen nicht gefunden werden.

Lösung: Eine andere Syntax beim Importieren von Komponenten verwenden

Es gibt eine sehr einfache Lösung für das Problem. Man kann Komponenten auf verschiedene Weisen importieren. Wir ersetzen den Import der i18n Funktion in Zeile 2 einfach durch diesen „Import“:

const { __ } = wp.i18n;

Als Ergebnis erhalten wir dann die folgende kompilierte JavaScript-Datei, welche wieder direkt die __ Funktion verwendet (in Zeile 10), die der Parser dann wieder erkennt:

// ...
var __ = wp.i18n.__;
function Edit(_ref) {
  var attributes = _ref.attributes,
      className = _ref.className,
      setAttributes = _ref.setAttributes;
  return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])("div", {
    className: className
  }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__["createElement"])(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__["TextControl"], {
    label: __('Message', 'block-i18n'),
    value: attributes.message,
    onChange: function onChange(val) {
      return setAttributes({
        message: val
      });
    }
  }));
}

Interessanterweise hat es auch dann funktioniert, wenn ich den import entfernt und nicht ersetzt habe. Eventuell wurde die __ Funktion bereits durch eine andere Komponente importiert und war deshalb verfügbar. Ich würde dennoch empfehlen alle externen Komponenten und Funktionen, die ihr in eurem Code verwenden auch explizit zu importieren. Auf die gleiche Weise könnte man übrigens auch die erste Zeile umschreiben:

const { TextControl } = wp.components;

Andere Tutorials verwenden immer diese Methode um Komponenten von WordPress/Gutenberg zu importieren und ich würde euch auch entfernen, es immer so zu tun. Ich hatte bisher damit noch keine Probleme und die resultierende JavaScript-Datei war sogar ein wenig kleiner.

Fazit

Das Übersetzen von String in Gutenberg-Blöcken (oder ähnlichem JavaScript-Code für WordPress) ist wirklich sehr einfach und man kann die gleichen Funktionen verwenden, die man auch von PHP her kennt. Wenn man aber die Imports „falsch“ machen, wird das Extrahieren von Strings mit Poedit nicht funktionieren.

Da es aber Plugins gibt, die dennoch Imports auf diese Weise machen und dennoch funktionsfähige Übersetzungen habe, gibt es vielleicht doch einen Weg. Wenn ihr vielleicht wisst, wie diese Plugins es machen, würde ich mich sehr freuen, wenn ihr es mir vielleicht in einem Kommentar erklärt.

Ein Plugin ohne zusätzlich Software oder Plugins übersetzen

Wenn ihr ein Plugin oder Theme übersetzen möchtet, dann würde ich euch immer empfehlen dies mit der kostenlosen Software Poedit zu machen, die es für Windows, Linux und Mac gibt. Die Pro-Version bringt ein paar spezielle WordPress-Funtionalitäten mit, aber die sind nicht unbedingt notwendig. Dennoch kann ich diese absolut empfehlen. Für einen einmaligen Kaufpreis ist die Software recht günstig und sie kann euch viel Zeit sparen, besonders bei der Übersetzung von Themes, die sehr ähnliche Strings haben.

Aber in diesem Beitrag soll es nicht darum gehen, wie ihr mit Poedit Plugins oder Themes übersetzt. Stattdessen will ich euch zeigen, wie ihr das nur mit ein paar Befehlen auf der Kommandozeile umsetzen könnt. Also auch wenn ihr keine zusätzlich Software (oder Plugins) verwenden könnt, ist es möglich.

Erstellen eines Übersetzungs-Templates

Der erste Schritt ist die Erstellung einer POT (Portable Object Template) Datei mit allen Strings, die euer Plugin/Theme verwendet. Wenn ich Poedit verwende, dann überspringe ich diesen Schritt meistens und verwende eine sprachspezifische Vorlage, die es Poedit erlaubt nach übersetzbaren Strings zu suchen. Der einfachste Weg ist aber die Verwendung eines WP-CLI Befehls um eine solche Datei zu erstellen:

wp i18n make-pot . languages/text-domain.pot

Wenn ihr diesen Befehl ausführt werden alle PHP und JavaScrupt Datein nach Strings durchsucht, deren Text-Domain gleich dem Namen des Plugin/Theme-Ordner ist. Es erstellt eine POT Datei im languages Ordner (ihr müsst einen solchen Ordner eventuell vorher erstellen). Dieser Befehl kennt alle Übersetzungsfunktionen von WordPress (die gleichen Funktionen, die ich in meiner Vorlage stehen habe).

Erstellen einer sprachspezifischen Übersetzung

Ale nächstes erstellen wir eine Übersetzung für eine Sprache, indem wir die POT Datei in eine PO (Portable Object) Datei kopieren. Hierzu wird die „Locale“ für die Sprache angehängt:

cp languages/text-domain.pot languages/text-domain-de_DE.po

Nun könnt ihr diese Datei in einem Texteditor öffnen und die Strings manuell übersetzen. Im Header der Datei könnt ihr noch die Sprache festlegen, technisch ist es aber nicht unbedingt notwendig.

Erstellen der binären Übersetzungsdatei

WordPress verwendet MO (Machine Object) Dateien, um Übersetzungen zu laden. Auch hierzu gibt es einen Befehl, der in vielen Betriebssystemen verfügbar ist (oder unter Windows in der Git-Bash, cygwin oder ähnlichem enthalten ist):

msgfmt languages/text-domain-de_DE.po -o languages/text-domain-de_DE.mo

Mehr braucht es nicht, um Übersetzungen zu erstellen. Ihr könnt nun überprüfen, ob die Übersetzungen in eurer WordPress-Installation verwendet werden (nachdem ihr natürlich sichergestellt habt, dass ihr eine entsprechende load_textdomain in eurem Plugin/Theme habt, der die Übersetzungsdatei lädt).

Bonus: Übersetzungen aktualisieren

Jedes Mal, wenn ihr Änderungen an den Strings vornehmt, müsst ihr die Übersetzungsdateien aktualisieren. Wenn ihr Poedit verwendet (und es richtig konfiguriert habt), könnt einfach nach diesen neuen Strings suchen lassen. Wenn ihr aber nur das Terminal verwendet ist die ebenfalls möglich. Führt dazu folgenden erneut Befehl aus:

wp i18n make-pot . languages/text-domain.pot

Dies generiert jedes mal eine neue Vorlagendatei und überschreibt die bestehende. Da POT Dateien keine übersetzen Stings enthalten (da sie nicht für eine spezifische Sprache verwendet werden) ist das kein Problem. Aber wie aktualisiert ihr eine sprachspezifische Übersetzungsdatei, ohne alle Strings erneut zu übersetzen? Hierzu könnt ihr das merge Argument verwenden:

wp i18n make-pot . languages/text-domain-de_DE.po --merge=languages/text-domain-de_DE.po

Das scannt erneut alle PHP und JavaScript Dateien aus dem aktuellen Ordner und „merged“ es mit der bestehenden Sprachdatei und schreibt alles in diese zurück. Nur Strings, die noch nicht in diese Datei vorhanden sind, werden neu hinzugefügt. Bereits übersetzte Strings bleiben erhalten. Der einzige Nachteil: der Befehl entfernt keine Strings, die nicht mehr in euren PHP oder JavaScript Dateien vorhanden sind.

Fazit

Wenn ihr sehr einfach Übersetzungen von Plugins oder Themes anfertigen wollt, dann verwendet am besten Poedit oder ähnliche Lösungen. Aber in den Fällen, in denen ihr diese nicht verwenden könnt, habt ihr auch über das Terminal die Möglichkeit zu übersetzen.

Ein Gebiet, bei dem der wp i18n make-pot Befehl sehr nützlich sein kann ist der Einsatz in eurem CI/CD-Workflow. Hier erstellt ihr einen Task, der diesen Befehl ausführt und immer eine aktuelle POT Datei zu euren aktuellen Entwicklungsstand erstellt.