So kombinieren wir Nested Pages, SEO Framework & Polylang in WordPress
Bei vielen Kundenwebseiten setzen wir auf das Plugin Nested Pages, um Seitenstruktur besser sehen (und verwalten) zu können.
Ohne dieses Plugin sieht die Anzeige von "Seiten" beispielsweise wie folgt aus:
Die Ansicht mit Nested Pages sieht hingegen so aus:
Gerade für Seiten mit diversen Unterseiten von Unterseiten wird es mit der normalen WordPress Ansicht sehr schnell unübersichtlich. Wenn dann noch 2 zusätzliche Sprachen für 50 Seiten hinzukommen, sind wir bei 150 Seiten mehr oder weniger ungeordnetem WordPress Inhalt.
tl;dr: Ich will wissen welchen Code ich benötige, um das besser zu machen!
Stand Heute
Unsere Kunden kommunizieren oft in mehreren Sprachen - dazu setzen wir auf Polylang. Hierbei handelt es sich um ein stabiles, aber einfach einzusetzendes Plugin um Wordpress-Seiten mehrsprachig zu erstellen.
SEO (Search Engine Optimization) ist selbstverständlich auch bei uns ein Thema. Warum sollten wir für unsere Kunden eine tolle Webseite erstellen, welche dann auf Seite 10 bei den Suchergebnissen landet? Um hierfür gewappnet zu sein setzen wir auf "The SEO Framework" und sind sehr zufrieden mit den erreichten Resultaten.
Warum erwähne ich diese beiden Plugins?
Im Zusammenhang mit Nested Pages verlieren unsere Kunden diese Informationen und Möglichkeiten fast gänzlich, da diese in Nested Pages nicht angezeigt werden.
Konkret:
- Übersetzungsfunktionalitäten fehlen
- Informationen zum SEO Status fehlen
Wir hatten bereits vor einiger Zeit mit dem Pluginautor Kontakt aufgenommen und ihn gebeten, dass er einen neuen Hook einfügt, damit wir die Darstellung im WordPress Backend beeinflussen können. Dieser Wunsch wurde uns relativ schnell erfüllt und innert kurzer Zeit konnten wir so zumindest die Sprache der aktuellen Seite anzeigen:
Das ist doch schon einmal toll! So konnten sich unsere Kunden trotzdem relativ einfach orientieren und wussten jederzeit, welche Sprache die gelistete Seite hat.
Stand Morgen
Wir wären nicht Digital Rebels, wenn wir dies einfach akzeptieren würden... ?
Aus diesem Grund haben wir uns hingesetzt und nach Lösungen gesucht um das Beste von der klassischen WordPress Ansicht mit der Nested Pages Ansicht zu kombinieren. Das Resultat sieht wie folgt aus:
Unsere Kunden haben mit den neuen Features die Möglichkeit Nested Pages einzusetzen und sehen trotzdem mehr:
1. Sprache des Beitrags (erste Flagge)
2. Übersetzungen
- grau: noch nicht übersetzt
➡️ ein Klick auf diese Flagge erstellt eine Übersetzung in der gewünschten Sprache. - leicht transparent: bereits übersetzt
➡️ ein Klick auf diese Flagge bearbeitet die gewünschte Sprache.
3. SEO Statusinformationen
Somit können unsere Kunden in der von Nested Pages gewohnten verschachtelten Ansicht arbeiten und profitieren trotzdem von den zusätzlich Informationen und Möglichkeiten, welche unsere Erweiterung bereitstellt. Aktuell müssen wir auf Grund von technischen Limitierungen all diese Informationen beim Titel hinzufügen. Diesbezüglich sind wir aber bereits mit dem Plugin Autor von Nested Pages in Kontakt und hoffen, dass wir dies demnächst noch "in schön" umsetzen können.
Wir sind der Meinung, dass trotz der etwas chaotischen Darstellung, dies ein extremer Mehrwert ist und die Verwaltung und Bearbeitung von (mehrsprachigen) Webseiten vereinfacht und ausserdem eine tolle Übersicht über die SEO Performance der eigenen Webseite bietet. Möchtest Du auch von einer einfachen Verwaltung von mehrsprachigen und/oder suchmaschinenoptimierten Seiten profitieren? Wir sind für dich da!
Technische Details
Sobald man die nötigen Hooks & Funktionen kennt, ist die Implementierung eigentlich keine Hexerei. Nachfolgend der Code für oben erwähnte Erweiterung:
<?php namespace ctcore\Hooks; class Translations { public static function AddCustomColumns($title, $postId) { // check if polylang is present if (function_exists('pll_get_post_language')) { $postId = \is_object($postId) ? $postId->ID : $postId; $postType = get_post_type($postId); if (pll_is_translated_post_type($postType)) { // get language details $currentLanguage = pll_get_post_language($postId, 'slug'); $postTranslations = pll_get_post_translations($postId); $languages = pll_the_languages([ 'raw' => true, 'echo' => 0, ]); $mainLanguage = ''; $additionalLanguages = ''; if (\is_array($languages)) { // get basic create new link $newPostLink = admin_url('post-new.php'); $newPostLink = add_query_arg( [ 'post_type' => $postType, 'from_post' => $postId, ], $newPostLink ); $currentLink = get_edit_post_link($postId); foreach ($languages as $langKey => $langValue) { if (array_key_exists($langKey, $postTranslations)) { if ($currentLanguage == $langKey) { // current language $mainLanguage = '</a><a href="' . $currentLink . '"><img title="' . $languages[$langKey]['name'] . ' (' . $languages[$langKey]['locale'] . ')" src="' . $languages[$langKey]['flag'] . '" class="lang-flag primary" ></a>'; } else { // translation available $editPostLink = get_edit_post_link($postTranslations[$langKey]); $additionalLanguages .= '</a><a href="' . $editPostLink . '"><img title="' . $languages[$langKey]['name'] . ' (' . $languages[$langKey]['locale'] . ')" src="' . $languages[$langKey]['flag'] . '" class="lang-flag is-translated" ></a>'; } } else { // no translation available $newPostLinkLanguage = add_query_arg('new_lang', $langKey, $newPostLink); $newPostLinkLanguage = wp_nonce_url( $newPostLinkLanguage, 'new-post-translation' ); $additionalLanguages .= '</a><a href="' . $newPostLinkLanguage .'"><img title="' . $languages[$langKey]['name'] . ' (' . $languages[$langKey]['locale'] . ')" src="' . $languages[$langKey]['flag'] . '" class="lang-flag not-translated" ></a>'; } } // build title string $title = $mainLanguage . $additionalLanguages . '<a href="' . $currentLink . '">' . $title; } } } // check if the seo framework is present if (class_exists('\The_SEO_Framework\Interpreters\SEOBar')) { $tsf = tsf(); if ($tsf->is_post_type_supported($postType)) { // post type is supported by the seo framework, display seo bar $seobar = new \The_SEO_Framework\Interpreters\SEOBar(); $bar = $seobar->generate_bar([ 'id' => $postId, 'post_type' => $postType, ]); $title = $title . $bar; } } return $title; } } add_action('nestedpages_post_title', ['\' . __NAMESPACE__ . '\Translations', 'AddCustomColumns'], 99, 2);
Was passiert hier?
Zuerst wird via dem Hook nestedpages_post_title eine Funktion aufgerufen, welche den Titel in Nested Pages manipulieren kann.
Dach wird für den jeweiligen Post geprüft ob 1) Polylang aktiv ist und 2) der Post überhaupt übersetzbar ist. Falls ja, werden die verschiedenen Sprachen (übersetzt oder nicht) angezeigt.
Anschliessend wird geprüft ob The SEO Framework aktiv ist. Falls ja, wird die SEO Bar von diesem Plugin geladen und ebenfalls dargestellt.
Ganz am Ende wird der neue Titel zurückgegeben und führt zum Resultat in obigem Screenshot.
Details
Natürlich "missbrauchen" wir den Hook um den Titel zu ändern für etwas, wofür dieser Hook eigentlich nicht gedacht ist. Dies sieht man unter anderem daran, dass wir das A-Tag jeweils zuerst schliessen und am Ende wieder öffnen, da wir uns gemäss Hook mitten in einem A-Tag befinden. Funktioniert es? Ja. Ergibt es Mehrwert? Ja? Gut :)
Ausserdem kann man sich natürlich die Frage bezüglich Performance stellen. Da es sich hier aber um eine Funktionalität handelt, welche nur im Kontext von 1) WordPress Backend und 2) Kombination Nested Pages, Polylang und The SEO Framework auftritt, ist die Performance zu vernachlässigen. Für das Frontend (sprich: für den Kunden unseres Kunden) hat diese Funktionalität somit überhaupt keinen negativen Einfluss.
Habe ich im Code Fehler hinterlassen, hast Du Fragen oder eine bessere Idee wie man dies lösen kann?
Schreib mir - oder noch besser: Bewirb Dich! Wir sind immer auf der Suche nach Talenten!