Wenn du Polylang in einem Multi-Domain-Setup verwendest, wie ich es in einem Projekt tue, kann es zu Problemen bei der Anzeige von Beitragsvorschauen kommen. Um dieses Problem zu lösen, habe ich verschiedene mögliche Lösungen ausprobiert und nehme dich mit auf die Reise, wie ich das Problem schließlich loswerden konnte – zumindest für Seiten.

Das Problem

Das Hauptproblem bei unserer Einrichtung ist, dass wir einen einzigen (externen) Anmeldemechanismus pro Website haben – nicht pro Domain. Und da Domains heutzutage keine Cookies teilen (was eine gute Sache ist), kann eine Anmeldung über eine Domain nicht für eine andere Domain verwendet werden. Das heißt, wenn du die Domain example.com für deinen englischen Inhalt und die Domain example.de für deinen deutschen Inhalt hast, kannst du nicht in beiden Domains mit diesem einzigen Anmeldemechanismus angemeldet sein.

Das führt dazu, dass z. B. Vorschau-URLs nicht für alle Domains angezeigt werden können, da eine Anmeldung erforderlich ist.

Dies ist besonders wichtig, wenn du eine neue Sprache zuerst einrichten willst (während sie noch deaktiviert ist), was auch bedeutet, dass du alle Seiten übersetzen und den neuen Inhalt einfügen musst. Während dieser Zeit möchtest du die Seiten dieser Sprache nicht öffentlich machen und brauchst daher die Vorschaufunktion, um zu überprüfen, ob deine Seiten nach der Übersetzung gut aussehen.

Außerdem gibt es in unserem Fall zusätzliche Probleme, da wir eine Domain-Mapping verwenden und der Inhalt der Website auf dem Webserver 20 Minuten lang im Seitencache für nicht angemeldete Benutzer zwischengespeichert wird. Selbst wenn es also in Ordnung wäre, die neue Sprache in einem unfertigen Zustand öffentlich verfügbar zu machen, würde es immer noch bis zu 20 Minuten dauern, bis die Änderungen auf der eigentlichen Seite erscheinen.

Zuerst: mehrere (mögliche) Lösungen

Wir haben uns mehrere mögliche Lösungen überlegt und ein paar davon auch umgesetzt, aber nicht alle.

Polylang im Frontend für angemeldete Benutzer deaktivieren

Die erste Idee war, Polylang im Frontend für angemeldete Benutzer komplett zu deaktivieren. Dies hätte zwar dazu geführt, dass die Vorschau-URLs für angemeldete Benutzer funktionieren, aber es gab immer noch ein Problem, alle Benutzer für alle Domains anzumelden. Zu diesem Zeitpunkt hatten wir einen Workaround für unsere Kunden mit dem einzigen Anmeldemechanismus, der sich jedoch als unzuverlässig erwies, da der Kunde die URL nach der Anmeldung manuell anpassen musste, was ein größeres Problem darstellte, als wir zunächst dachten. Daher haben wir diese Lösung nie ausprobiert.

URL-Modifikationen für angemeldete Benutzer zu Ordnernamen ändern

Diese Idee war sehr vielversprechend: Anstatt zu versuchen, das Multi-Domain-Setup zu umgehen, dachten wir einfach daran, den URL-Modifikationstyp für angemeldete Benutzer von Polylang auf Ordner-Namen zu ändern. Dies würde dazu führen, dass die Sprachen sowohl auf example.com/ als auch auf example.com/de/ verfügbar wären.

Das Problem hierbei ist, insbesondere für den Kunden, der die Seiten selbst bearbeiten möchte, dass interne Links oder Links zu anderen Sprachen manuell angepasst werden müssen (z. B. um sicherzustellen, dass alle Links zu deutschen Seiten mit example.de verlinkt sind, obwohl sie für den Kunden über example.com/de/ zugänglich sind). Dies wäre ein großes Risiko für falsche URLs auf der Website und daher nicht sehr kundenfreundlich.

Polylang für Vorschau-URLs deaktivieren

An diesem Punkt dachte ich, wir hätten nun die endgültige Lösung. Es war nicht die schönste, denn die vollständige Deaktivierung von Polylang für Vorschau-URLs würde Inhalte sichtbar machen, die für bestimmte Sprachen ausdrücklich deaktiviert sind. Außerdem wäre das Menü immer das englische (bzw. das der standardmäßig eingestellten Sprache), aber wenigstens würde die Vorschau funktionieren.

Zumindest habe ich das zuerst gedacht. Nachdem ich diese Lösung implementiert und getestet hatte, entdeckte ich ein Problem: Wenn Seiten in mehreren Sprachen dieselbe Titelform (denselben Pfad in ihrer URL) haben, funktioniert es nicht. Stattdessen würde jedes Mal die Seite in der Standardsprache angezeigt werden.

Permalink-Struktur für Vorschau-URLs deaktivieren

Um das Titelform-Problem zu umgehen, dachte ich, ich könnte einfach die Permalink-Struktur deaktivieren (d. h. die Methode „Einfach“ verwenden), die nur die Beitrags-ID in der URL anstelle der Titelform verwendet.

Dies funktionierte nach einigen Tests gut, aber da es keinen Filter oder ähnliches gibt, musste ich die tatsächliche Permalink-Struktur bei jeder Vorschauanforderung manuell überschreiben. Das war etwas umständlich und ich musste die aktuelle Permalink-Struktur an anderer Stelle speichern, um sie anschließend wiederherstellen zu können. Deshalb war ich mit dieser Lösung nicht zufrieden und suchte weiter.

Endlich: die Lösung

Als ich nachsah, wie die Vorschau für nicht veröffentlichte Seiten funktioniert, entdeckte ich, dass es drei URL-Parameter gibt: ?page_id=123&preview=true&lang=nn

Für bereits veröffentlichte Seiten waren die Parameter anders: ?preview_id=67565&preview_nonce=6c67bb8f51&preview=true

Solange ich also die Parameter page_id und lang zur Vorschau-URL hinzufügen konnte, würde es funktionieren. Und das tat es!

Zusätzlich mussten wir auch sicherstellen, dass die aktuell verwendete Domain in der Vorschau verwendet wurde, damit wir sicherstellen konnten, dass der Kunde angemeldet ist. Daher verwenden wir nur die URL-Query der eigentlichen Vorschau-URL, erweitern sie und verwenden die aktuelle home_url, welche die aktuelle Domain ist, die der Kunde verwendet – Dank Domain-Mapping.

Damit sieht der Code so aus:

/**
 * Add the 'lang' and 'page_id' URL parameters to the preview link.
 * 
 * This allows to display the correct post for previews even pages with identical slug.
 * 
 * @param	string	$preview_link Current preview link
 * @param	WP_Post	$post Current post object
 * @return	string Updated preview link
 */
function add_preview_link_parameters( string $preview_link, \WP_Post $post ): string {
	$option = \get_option( 'polylang' );
	
	// the problem needs only to be solved if domains are used
	if ( ! isset( $option['force_lang'] ) || $option['force_lang'] !== self::URL_MODIFICATION_DOMAIN ) {
		return $preview_link;
	}
	
	// get the current preview URL query
	$query = \wp_parse_url( $preview_link, \PHP_URL_QUERY );
	// get the current home_url for domain mapping support and extend it with the preview URL query
	$new_link = \home_url( '?' . $query );
	// add lang and page ID query parameter to make sure to display this exact page in the desired language
	$new_link = \add_query_arg(
		[
			'lang' => \pll_get_post_language( $post->ID, 'slug' ),
			'page_id' => $post->ID,
		],
		$new_link
	);
	
	return $new_link;
}

\add_filter( 'preview_post_link', 'add_preview_link_parameters', 30, 2 );
Code-Sprache: PHP (php)

Wir können hier nicht den p-Parameter verwenden, damit das bei jedem Beitrag funktioniert, da WordPress dies dann für veröffentlichte Beiträge als ungültige Vorschau ansieht und dann nicht die Vorschau anzeigt, sondern den veröffentlichten Inhalt des Beitrags.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert