Complianz and Polylang timing diagram showing early document creation and a guarded rebuild after language selection

Complianz + Polylang: Cookie-Richtlinie bleibt teilweise Englisch – Ursache und sicherer Fix

Am Anfang sah das nach einem ganz gewöhnlichen Übersetzungsproblem aus. Die polnische Seite hatte den richtigen Titel „Polityka plików cookie (UE)”, den erwarteten Permalink und auch der Complianz-Banner verlinkte auf die polnische Version. Der generierte Inhalt der Cookie-Richtlinie begann trotzdem weiterhin auf Englisch: Introduction, What are cookies?, What are scripts? und die folgenden Absätze waren englisch.

Der entscheidende Hinweis war, dass das Dokument nicht vollständig englisch war. Weiter unten waren einzelne Service-Bezeichnungen und dynamische Felder bereits auf Polnisch übersetzt, während der umgebende Rechtstext englisch blieb. Genau dieses gemischte Ergebnis führte am Ende zur eigentlichen Ursache.

Caches leeren, die Locales erneut prüfen und den kompletten Richtlinientext unter Polylang → String translations suchen half nicht. Die Ursache lag im Timing: Complianz baute die statischen Dokumentelemente bereits auf, bevor Polylang im Modus The language is set from content die Sprache der aktuellen Seite festgelegt hatte.

Ich habe das weder durch Änderungen an Complianz-Dateien noch durch das Trennen der Dokument-Synchronisierung gelöst. Stattdessen läuft ein eng begrenztes MU-Plugin, das erst nach der Sprachauswahl von Polylang ausschließlich die synchronisierte EU Cookie Policy für Polnisch und Deutsch kontrolliert neu aufbaut. Der Produktionstest endete mit PL PASS / DE PASS / EN PASS.

Wichtig: Das ist ein realer Compatibility Case mit einem getesteten Workaround, aber kein offizieller Patch von Complianz oder Polylang. Der Code ist absichtlich eng begrenzt und sollte nicht blind auf jeder mehrsprachigen WordPress-Installation eingesetzt werden.

Das Symptom: Seitensprache korrekt, Dokumentinhalt falsch

Die Website verwendet drei Sprachen. Englisch ist die Standard-Sprache in Polylang; Deutsch und Polnisch sind verknüpfte Übersetzungen.

Zum Zeitpunkt der Diagnose galt folgender Baseline-Stand:

  • WordPress 7.1;
  • PHP 8.5.7;
  • Complianz 7.5.4;
  • Polylang im Modus The language is set from content;
  • Locales en_US, de_DE, pl_PL;
  • EN als Standardsprache;
  • das Legal Document weiterhin auf Synchronize document with Complianz.

Die englische Cookie Policy (EU) funktionierte normal. Danach habe ich in Polylang die verknüpfte polnische Seite angelegt. Der Seitentitel war polnisch, und nach der Veröffentlichung war Page ID 2453 unter /polityka-plikow-cookie-ue/ erreichbar. Auch der Complianz-Banner führte auf die richtige polnische Seite.

Der Fehler steckte im Dokument selbst: Der Großteil der Hauptüberschriften und Absätze blieb englisch.

Polnische Cookie-Policy-Seite mit polnischem Titel, aber englischem Haupttext
Seite, Permalink und Sprachkontext waren polnisch, der Hauptinhalt des generierten Dokuments blieb jedoch englisch.

Die deutsche Übersetzung zeigte dasselbe Muster: deutscher Seitenkontext, aber der Großteil der synchronisierten Richtlinie weiterhin auf Englisch.

Der wichtigste Hinweis: Nur ein Teil des Dokuments war falsch

Wenn lediglich das Translation Pack gefehlt hätte, wäre ein durchgehend englisches Dokument zu erwarten gewesen. Genau das war nicht der Fall.

Im Bereich der Services und Cookies waren bereits polnische Bezeichnungen wie Używanie, Udostępnianie danych, Nazwa, Wygaśnięcie und Funkcja sichtbar. Gleichzeitig blieben Überschriften wie Placed cookies, Consent und die umliegenden rechtlichen Texte englisch.

Das deutete darauf hin, dass nicht alle Bestandteile der Richtlinie zum gleichen Zeitpunkt innerhalb des WordPress-Requests erzeugt werden. Ein Teil der dynamischen Daten wurde später gerendert und sah bereits das korrekte polnische Locale, während die statischen Dokumentelemente früher übersetzt und auf Englisch festgeschrieben worden waren.

Genau dieses Verhalten passte anschließend zum Complianz-Quellcode.

Gemischtsprachige Complianz Cookie Policy mit englischen statischen Abschnitten und polnischen dynamischen Service-Feldern
Das gemischte Ergebnis war der entscheidende Hinweis: Später gerenderte Service-Daten waren bereits polnisch, während der statische Richtlinientext englisch blieb.

Was ich geprüft habe, bevor ich den Code auditiert habe

Bevor ich mich mit der Reihenfolge der WordPress-Hooks beschäftigt habe, habe ich die naheliegenden Ursachen ausgeschlossen.

1. Polylang-Locales

Die Sprachkonfiguration war korrekt:

  • English → en_US — Standardsprache;
  • Deutsch → de_DE;
  • Polski → pl_PL.

Es war also weder ein einfacher Locale-Tippfehler noch eine Seite, die in Polylang der falschen Sprache zugeordnet war.

Polylang-Sprachkonfiguration mit en_US als Standard sowie de_DE und pl_PL
Die Locale-Konfiguration war korrekt: Englisch war die Standardsprache, Deutsch und Polnisch waren als Übersetzungssprachen eingerichtet.

2. Complianz-Übersetzungsdateien

Ich habe wp-content/languages/plugins/ geprüft. Die deutschen und polnischen Complianz-Ressourcen waren physisch vorhanden, einschließlich Dateien passend zu complianz-gdpr-de_DE.* und complianz-gdpr-pl_PL.*.

Damit war die einfachste Erklärung ausgeschlossen: WordPress hatte die Plugin-Übersetzungen nicht heruntergeladen.

Vorhandene deutsche und polnische Complianz-Übersetzungsdateien im WordPress-Sprachverzeichnis
Die benötigten deutschen und polnischen Complianz-Übersetzungsdateien waren auf dem Dateisystem vorhanden.

3. Cache

Cache war ein plausibler Verdacht, weil ein früheres, separates Problem mit der Banner-Übersetzung nach stale output aussah. Beim Legal Document habe ich jedoch die verfügbaren Page-Cache-Layer geleert und in Polnisch wie Deutsch blieb dasselbe gemischte Sprachbild bestehen.

Deshalb klassifiziere ich dieses Legal-Document-Problem nicht als Cache-Fehler.

4. Polylang String translations

Polylang → String translations ist für Teile des Complianz-Banners und eigene Strings die richtige Stelle. Der komplette generierte Rechtstext — etwa alle Absätze von Introduction und What are cookies? — war dort jedoch nicht vorhanden.

Die komplette Cookie-Richtlinie manuell als Polylang-Strings nachzubauen wäre daher keine sinnvolle Lösung gewesen.

5. Dokument-Synchronisierung

Der Complianz-Block stand weiterhin auf:

Synchronize document with Complianz

Ich habe Edit document and stop synchronization bewusst nicht als Lösung verwendet. Damit ließe sich der Inhalt zwar manuell bearbeiten, gleichzeitig würde aber ein zentraler Vorteil des generierten Legal Documents verloren gehen: die laufende Synchronisierung mit Complianz.

Complianz Legal-Document-Block mit aktivierter Option Synchronize document with Complianz
Die Cookie Policy blieb mit Complianz synchronisiert; das manuelle Trennen der Synchronisierung wurde nicht als Fix verwendet.

Ein kurzer Fehlalarm: Beim ersten Test kam ein 404

Beim ersten polnischen Test führte der Banner-Link zu /?page_id=2453, und ein anonymer Besucher erhielt einen 404. Das gehörte nicht zum eigentlichen Übersetzungsfehler.

Die polnische Seite war zu diesem Zeitpunkt noch ein Draft. Ein öffentlicher 404 war deshalb das erwartete WordPress-Verhalten. Nach der Veröffentlichung funktionierte das Routing korrekt und die Seite erhielt /polityka-plikow-cookie-ue/. Erst dann zeigte sich der tatsächliche Defekt: korrekte polnische Seite, aber englischer Dokumentinhalt.

Das ist nur ein Nebendetail, aber eine nützliche Debugging-Regel: Routing- und Statusprobleme getrennt von Rendering- und Lokalisierungsproblemen behandeln.

Source Audit: Wo die Cookie Policy tatsächlich entsteht

Nachdem Locales, Übersetzungsdateien, Cache und String translations ausgeschlossen waren, habe ich die exakten Produktionsdateien von Complianz 7.5.4 geprüft. Vier Stellen waren entscheidend.

gutenberg/block.php

Der Render-Callback des Blocks complianz/document erzeugt die Übersetzungen nicht neu. Bei einem synchronisierten Dokument delegiert er im Kern an:

$html = COMPLIANZ::$document->get_document_html( $type, $region );

Der Gutenberg-Block wählt also weder selbst ein Locale aus noch baut er die statischen Strings neu auf.

documents/class-document.php

get_document_html() liest eine bereits vorbereitete Struktur:

$elements = COMPLIANZ::$config->pages[ $region ][ $type ]["document_elements"];

Anschließend werden diese Elemente durchlaufen und ihre Überschriften und Inhalte gerendert. Callback-basierte Elemente können erst in dieser späteren Rendering-Phase ausgeführt werden.

Genau dadurch ist ein gemischtes Ergebnis möglich: Normale Elemente sind bereits festgeschrieben, während dynamische Fragmente erst später ausgewertet werden.

config/class-config.php

Hier wird die zeitliche Reihenfolge relevant.

load_documents() lädt die Dokumentdateien und wendet anschließend den Filter cmplz_document_elements an. Im Produktionscode wird load_documents() auf den WordPress-Hook init registriert.

config/documents/cookie-policy-eu.php

Die Hauptelemente der EU Cookie Policy werden direkt beim Include dieser Datei erzeugt. Ein Beispiel ist die Überschrift:

_x(
    'Introduction',
    'Legal document cookie policy:paragraph title',
    'complianz-gdpr'
)

Dieser Aufruf wird sofort ausgewertet und das Resultat in document_elements gespeichert.

Ist das aktive Locale zu diesem Zeitpunkt noch Englisch, steht in der Struktur bereits Introduction. Eine spätere Änderung der Request-Sprache übersetzt diesen vorhandenen Wert nicht rückwirkend neu.

Die zweite Hälfte der Ursache: Wann Polylang die Sprache festlegt

Die Entwicklerdokumentation von Polylang beschreibt unterschiedliche Abläufe. Im von mir verwendeten Modus The language is set from content muss Polylang auf den abgefragten Content warten und definiert die Sprache erst auf der WordPress-Aktion wp mit Priority 5.

Die gleiche Dokumentation warnt Plugin-Autoren ausdrücklich davor, in diesem Modus Strings bereits vor wp zu übersetzen.

Vereinfacht sah der Request deshalb so aus:

WordPress init
    ↓
Complianz load_documents()
    ↓
cookie-policy-eu.php führt _x()/__() aus
    ↓
document_elements entstehen noch als EN
    ↓
WordPress wp, Priority 5
    ↓
Polylang definiert die endgültige Sprache PL oder DE
    ↓
Complianz rendert die zuvor erzeugten document_elements
    ↓
einige Callbacks laufen später und sehen bereits PL/DE

Damit lässt sich das ungewöhnliche Symptom genau erklären: Der Haupttext war englisch, während einige dynamische Elemente bereits korrekt polnisch oder deutsch waren.

Timing-Diagramm mit Complianz init, Polylang wp Priority 5 und dem MU-Plugin-Rebuild auf wp Priority 20
Complianz erzeugte die statischen Dokumentelemente, bevor Polylang die Seitensprache auswählte. Der Workaround baut sie erst nach dem dokumentierten Polylang-Punkt `wp/5` kontrolliert neu auf.

Die Lösung: Eng begrenztes MU-Plugin statt Complianz-Dateien zu bearbeiten

Vendor-Dateien von Complianz direkt zu ändern wäre die falsche Richtung gewesen. Ein Plugin-Update würde die Änderung überschreiben, und ein privater Fork würde zukünftige Audits unnötig erschweren.

Ebenso wollte ich die Polylang-URL-Architektur der Website nicht nur wegen dieses Compatibility Edge Case umbauen. The language is set from content bleibt eine bewusste Eigenschaft dieser Installation.

Die Produktionslösung ist ein separates MU-Plugin:

wp-content/mu-plugins/bybrzoza-complianz-polylang-legal-i18n-fix.php

Sein Einstiegspunkt läuft auf:

add_action(
    'wp',
    'bybrzoza_cmplz_polylang_relocalize_cookie_policy',
    20
);

Priority 20 ist absichtlich gewählt: Der Fix läuft nach dem dokumentierten Punkt wp/5, an dem Polylang in diesem Modus die Sprache definiert.

Das MU-Plugin schaltet die Sprache nicht selbst um. Es prüft zuerst, ob Polylang und WordPress bereits dasselbe aktive Locale sehen, und baut nur dann — hinter weiteren Schutzbedingungen — die konkrete Struktur document_elements neu auf.

Warum der Workaround so viele Guardrails hat

Ein deutlich kürzerer Snippet könnte cookie-policy-eu.php einfach bei jedem Request erneut includen. Genau das wollte ich nicht.

Version 0.1.0 arbeitet nur, wenn alle relevanten Bedingungen erfüllt sind:

  • nur Frontend;
  • normale WordPress-Seite;
  • Polylang und Complianz verfügbar;
  • benötigte Complianz-Konstanten und -Objekte vorhanden;
  • Complianz >= 7.5.4 und < 8.0.0;
  • Polylang-Locale und WordPress-Locale stimmen überein;
  • Locale ist exakt pl_PL oder de_DE;
  • die Seite ist ein cookie-statement-Dokument;
  • Region ist eu;
  • erwartete document_elements-Struktur existiert;
  • erste Überschrift entspricht exakt dem defekten englischen Zustand Introduction;
  • _x() liefert nach der Sprachauswahl jetzt tatsächlich eine übersetzte Variante.

Ist das Dokument bereits korrekt lokalisiert, macht das MU-Plugin nichts. Dieses Self-Noop-Verhalten ist für Updates wichtig: Wenn Upstream das Timing später korrigiert, soll der Workaround einen bereits korrekten Zustand nicht unnötig neu aufbauen.

Nach dem erneuten Include der Dokumentdatei wird cmplz_document_elements nochmals angewendet, damit der normale Complianz-Pfad möglichst genau gespiegelt wird. Anschließend prüft der Fix das Ergebnis. Bei einem unerwarteten Zustand oder einer Exception werden die ursprünglichen request-lokalen Elemente wiederhergestellt und die Verarbeitung endet fail-closed.

Es gibt keine Datenbank-Schreibzugriffe.

Vollständiger, in Produktion getesteter MU-Plugin-Quellcode 0.1.0
<?php
/**
 * Plugin Name: byBrzoza Complianz + Polylang Legal i18n Fix
 * Description: Narrow compatibility fix for Complianz legal-document translations when Polylang uses “The language is set from content”.
 * Version: 0.1.0
 * Author: byBrzoza
 */

defined( 'ABSPATH' ) || exit;

/**
 * Rebuild the synchronized EU Cookie Policy after Polylang has selected the
 * language from the current page content.
 *
 * Why this exists:
 * - Polylang's content-based language mode defines the language on `wp`
 *   (priority 5).
 * - Complianz 7.5.4 loads/translates cookie-policy-eu.php earlier, on `init`.
 * - The resulting document_elements can therefore be frozen in the default
 *   locale (EN), while later callback-driven sections render in PL/DE.
 *
 * Safety / update behavior:
 * - front end only;
 * - only synchronized EU Cookie Policy pages;
 * - only pl_PL and de_DE;
 * - only if the current main heading is exactly the broken EN value
 *   "Introduction";
 * - self-noops if Complianz/upstream already renders the correct translation;
 * - guards Complianz version and internal structure and does nothing on an
 *   unexpected state;
 * - no database writes and no vendor-file modifications.
 */
function bybrzoza_cmplz_polylang_relocalize_cookie_policy(): void {
	static $done = false;

	if ( $done ) {
		return;
	}
	$done = true;

	if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
		return;
	}

	if ( ! function_exists( 'pll_current_language' ) || ! class_exists( 'COMPLIANZ' ) ) {
		return;
	}

	if ( ! defined( 'CMPLZ_VERSION' ) || ! defined( 'CMPLZ_PATH' ) ) {
		return;
	}

	if ( ! isset( COMPLIANZ::$config, COMPLIANZ::$document ) ) {
		return;
	}

	// Tested against Complianz 7.5.4. Allow 7.x updates only while the guarded
	// internal structure still matches; stop automatically at the next major.
	$cmplz_version = strtok( (string) CMPLZ_VERSION, '#' );
	if ( version_compare( $cmplz_version, '7.5.4', '<' ) || version_compare( $cmplz_version, '8.0.0', '>=' ) ) {
		return;
	}

	if ( ! is_page() ) {
		return;
	}

	global $post;
	if ( ! ( $post instanceof WP_Post ) ) {
		return;
	}

	// Ensure Polylang and WordPress agree on the active locale at this point.
	$pll_locale = pll_current_language( 'locale' );
	$wp_locale  = get_locale();
	if ( ! is_string( $pll_locale ) || $pll_locale === '' || $pll_locale !== $wp_locale ) {
		return;
	}

	if ( ! in_array( $wp_locale, array( 'pl_PL', 'de_DE' ), true ) ) {
		return;
	}

	if ( ! method_exists( COMPLIANZ::$document, 'get_document_data' ) ) {
		return;
	}

	$document_data = COMPLIANZ::$document->get_document_data( $post->ID );
	if ( ! is_array( $document_data ) || ( $document_data['type'] ?? '' ) !== 'cookie-statement' ) {
		return;
	}

	$region = $document_data['region'] ?? false;
	if ( ! $region && function_exists( 'cmplz_get_region_from_legacy_type' ) ) {
		$region = cmplz_get_region_from_legacy_type( 'cookie-statement' );
	}
	if ( $region !== 'eu' ) {
		return;
	}

	$pages = COMPLIANZ::$config->pages;
	if ( ! isset( $pages['eu']['cookie-statement']['document_elements'] ) || ! is_array( $pages['eu']['cookie-statement']['document_elements'] ) ) {
		return;
	}

	$original_elements = $pages['eu']['cookie-statement']['document_elements'];
	$current_intro     = bybrzoza_cmplz_find_first_document_title( $original_elements );
	$expected_intro    = _x( 'Introduction', 'Legal document cookie policy:paragraph title', 'complianz-gdpr' );

	// Missing/failed translation: fail closed rather than rewriting anything.
	if ( ! is_string( $expected_intro ) || $expected_intro === '' || $expected_intro === 'Introduction' ) {
		return;
	}

	// Upstream/another integration already fixed it: no-op.
	if ( $current_intro === $expected_intro ) {
		return;
	}

	// Do not overwrite a custom/unknown document state.
	if ( $current_intro !== 'Introduction' ) {
		return;
	}

	$document_file = trailingslashit( CMPLZ_PATH ) . 'config/documents/cookie-policy-eu.php';
	if ( ! is_readable( $document_file ) ) {
		return;
	}

	$reload = function ( string $file ): bool {
		include $file;

		if ( ! isset( $this->pages['eu']['cookie-statement']['document_elements'] ) || ! is_array( $this->pages['eu']['cookie-statement']['document_elements'] ) ) {
			return false;
		}

		// Mirror Complianz::load_documents() so integrations using this official
		// filter are preserved on the rebuilt element set.
		$this->pages['eu']['cookie-statement']['document_elements'] = apply_filters(
			'cmplz_document_elements',
			$this->pages['eu']['cookie-statement']['document_elements'],
			'eu',
			'cookie-statement',
			$this->fields
		);

		return true;
	};

	$restore = function ( array $elements ): void {
		$this->pages['eu']['cookie-statement']['document_elements'] = $elements;
	};

	try {
		$loaded = $reload->call( COMPLIANZ::$config, $document_file );
		if ( ! $loaded ) {
			$restore->call( COMPLIANZ::$config, $original_elements );
			return;
		}

		$pages_after = COMPLIANZ::$config->pages;
		$new_elements = $pages_after['eu']['cookie-statement']['document_elements'] ?? array();
		$new_intro    = is_array( $new_elements ) ? bybrzoza_cmplz_find_first_document_title( $new_elements ) : null;

		if ( $new_intro !== $expected_intro ) {
			$restore->call( COMPLIANZ::$config, $original_elements );
		}
	} catch ( Throwable $e ) {
		// Front-end availability wins over the workaround. Restore the exact
		// request-local original state and fail closed without exposing details.
		$restore->call( COMPLIANZ::$config, $original_elements );
	}
}

/**
 * Return the first non-empty document title.
 *
 * @param array $elements Complianz document elements.
 * @return string|null
 */
function bybrzoza_cmplz_find_first_document_title( array $elements ): ?string {
	foreach ( $elements as $element ) {
		if ( is_array( $element ) && isset( $element['title'] ) && is_string( $element['title'] ) && $element['title'] !== '' ) {
			return $element['title'];
		}
	}
	return null;
}

// In Polylang's "language from content" mode the locale is defined on `wp`
// at priority 5. Running later avoids changing the site's URL architecture.
add_action( 'wp', 'bybrzoza_cmplz_polylang_relocalize_cookie_policy', 20 );

Der gleiche Quellcode liegt zusätzlich als Datei in der Publication Package. So muss er nicht aus dem HTML kopiert werden.

Installation

Vor der Installation sollte ein aktuelles Backup vorhanden sein. Der Fix ändert zwar weder Datenbank noch Vendor-Dateien, aber auch bei einer kleinen Produktionsänderung gehört ein Rollback-Pfad dazu.

  1. Falls noch nicht vorhanden, Verzeichnis anlegen:
wp-content/mu-plugins/
  1. Die Datei dort ablegen:
wp-content/mu-plugins/bybrzoza-complianz-polylang-legal-i18n-fix.php
  1. Den tatsächlich aktiven Page Cache leeren.
  2. Die synchronisierte Cookie Policy nacheinander in PL, DE und EN prüfen.

Der von mir verwendete Smoke-Test war absichtlich einfach:

PL → Haupttext polnisch
DE → Haupttext deutsch
EN → unverändert englisch

Zusätzlich habe ich geprüft, dass die Banner-Links weiterhin auf die richtige Sprachseite zeigen.

Im Produktionsfall lautete das Ergebnis:

PL PASS / DE PASS / EN PASS

Warum ich weder Site Language noch den Polylang-URL-Modus geändert habe

Zwei scheinbar einfache Auswege wären gewesen, WordPress Site Language auf Deutsch oder Polnisch zu setzen oder Polylang auf sprachabhängige Verzeichnisse wie /de/, /pl/ und /en/ umzustellen.

Beides wäre für diesen einzelnen Defekt ein zu großer Eingriff gewesen. Der Sprachmodus beeinflusst Routing, bestehende URLs, Canonicals, hreflang und den Language Switcher. Auf dieser Website ist Englisch bewusst die Standardsprache, und The language is set from content bleibt eine gewollte Architekturentscheidung.

Deshalb korrigiert der Workaround ausschließlich den nachgewiesenen Timing-Konflikt beim synchronisierten Legal Document, statt die mehrsprachige Struktur der gesamten Website umzubauen.

Rollback

Der Rollback ist bewusst klein:

  1. Datei entfernen:
wp-content/mu-plugins/bybrzoza-complianz-polylang-legal-i18n-fix.php
  1. Page Cache leeren.
  2. Cookie Policy erneut prüfen.

Da der Workaround keine DB-Writes ausführt, gibt es keine Datenbankänderung zurückzunehmen.

Verhalten nach Complianz- und Polylang-Updates

Ein MU-Plugin wird von normalen Updates von Complianz oder Polylang nicht überschrieben. Das bedeutet aber nicht, dass interne APIs der Plugins für immer kompatibel bleiben.

Deshalb prüfe ich nach einem Update kurz:

  1. PL Cookie Policy;
  2. DE Cookie Policy;
  3. EN als Regression;
  4. Banner-Link und Polylang-Beziehung.

Der Fix ist für Complianz >= 7.5.4 und < 8.0.0 begrenzt. Bei Complianz 8.x führt er absichtlich nichts mehr aus. Vor einer Anpassung an eine neue Major-Version sollte der relevante Quellcode erneut auditiert werden.

Wenn Complianz oder Polylang das Problem upstream beheben, sollte das MU-Plugin wegen seines Self-Noop-Guards bereits nichts mehr verändern. Trotzdem würde ich zuerst die drei Sprachversionen testen und erst danach entscheiden, ob die Datei entfernt werden kann.

Wann ich diesen Fix nicht einsetzen würde

Der Workaround ist nicht die richtige Antwort, wenn:

  • das gesamte WordPress- oder Plugin-Translation Pack fehlt;
  • Polylang falsche Locales verwendet;
  • eine Seite der falschen Sprache zugeordnet ist;
  • ein anderer Polylang-Modus verwendet wird und der Fehler nicht reproduzierbar ist;
  • die Cookie Policy bewusst von Complianz getrennt und manuell gepflegt wird;
  • Complianz bereits korrekt lokalisiert und das MU-Plugin deshalb self-noopt;
  • Complianz 8.x oder neuer verwendet wird, ohne vorherigen Source Audit;
  • der beobachtete Fehler nicht dem hier beschriebenen Muster entspricht.

Vor allem ist dieser Artikel kein Argument dafür, jede Polylang-Installation auf einen anderen URL-Modus zu migrieren. Für diese Website bleibt The language is set from content absichtlich erhalten; der Fix adressiert nur den konkret nachgewiesenen Timing-Konflikt.

Upstream-Status am 1. September 2026

Zum Zeitpunkt dieses Artikels ist Complianz 7.5.4 die aktuelle öffentliche Version. Genau diese Version lief auch im beschriebenen Produktionsfall. Im Changelog von 7.5.4 ist keine Korrektur für diesen konkreten Konflikt zwischen Legal-Document-Erzeugung und Polylang Content Mode dokumentiert.

Polylang ist inzwischen öffentlich bei 3.8.7. Der Produktionsfall wurde auf 3.8.6 diagnostiziert und getestet; ich behaupte deshalb nicht, den Defekt auf 3.8.7 erneut reproduziert zu haben. Die aktuelle Entwicklerdokumentation beschreibt den entscheidenden Mechanismus jedoch weiterhin unverändert: Im Content-basierten Modus wird die Sprache auf wp Priority 5 definiert.

Auch der offizielle Complianz-Guide zu Polylang geht grundsätzlich davon aus, dass ein verknüpftes Legal Document nach dem Veröffentlichen in die gewählte Sprache übersetzt wird. Das macht den beschriebenen Fall zu einem Compatibility Edge Case — nicht zu einem normalen Konfigurationsschritt, den jeder Benutzer benötigt.

Was ich aus diesem Fehler mitnehme

Der nützlichste Teil dieser Diagnose war am Ende nicht der MU-Plugin-Code selbst, sondern das teilweise übersetzte Ergebnis.

Ein komplett englisches Dokument hätte auf fehlende Sprachdateien, falsches Locale oder eine falsche Zuordnung hingedeutet. Ein Dokument, in dem statische Texte englisch, aber später erzeugte Felder bereits polnisch waren, war dagegen ein starker Hinweis auf zwei unterschiedliche Ausführungszeitpunkte.

Erst dadurch wurde aus einem vermeintlichen Übersetzungs- oder Cache-Problem eine konkrete Hook-Timing-Frage:

Complianz init
vs.
Polylang wp / priority 5

Und genau deshalb ist die Lösung auch kein großer Umbau: Die bestehende Architektur bleibt erhalten; nur das zu früh erzeugte Dokument wird nach der sicheren Sprachauswahl eng begrenzt neu aufgebaut.

Quellen und Versionsstand

Für die Root-Cause-Analyse wurden die exakten Produktionsdateien von Complianz 7.5.4 verwendet: gutenberg/block.php, documents/class-document.php, config/class-config.php, config/documents/cookie-policy-eu.php und complianz-gpdr.php. Der Upstream-Stand wurde am 1. September 2026 erneut geprüft.

Hat dir diese Anleitung geholfen?
Wenn sie dir etwas Zeit oder Nerven gespart hat, kannst du mir einen Kaffee ausgeben.