Last active
June 25, 2025 14:29
-
-
Save hirasso/55ece097189fa24aca026323e462f692 to your computer and use it in GitHub Desktop.
Polylang UI Improvements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* Copyright (c) Rasso Hilber | |
* https://rassohilber.com | |
*/ | |
namespace Hirasso\WP; | |
/** | |
* Improvements of the Polylang admin UI, that helps my customers to better understand | |
* what they are doing. Can be required from a theme or plugin and then instanciated via | |
* new \Hirasso\WP\PolylangUI() | |
*/ | |
final class PolylangUI | |
{ | |
protected ?\WP_Post $post = null; | |
protected ?\PLL_Language $postLanguage = null; | |
public function __construct() | |
{ | |
add_action('admin_head', [$this, 'on_admin_head']); | |
add_action('admin_bar_menu', [$this, 'add_post_language_switcher'], 999); | |
add_filter('acf/prepare_field', [$this, 'acf_prepare_field'], PHP_INT_MAX - 100); | |
} | |
/** | |
* Detect if we are currently on the post edit screen for a translatable post type | |
*/ | |
public function on_admin_head() | |
{ | |
if (get_current_screen()?->base !== 'post') { | |
return; | |
} | |
if (!$post = get_post()) { | |
return; | |
} | |
if (!pll_is_translated_post_type(get_post_type($post))) { | |
return; | |
} | |
if (!$postLanguage = pll_get_post_language($post->ID, \OBJECT)) { | |
return; | |
} | |
$this->post = $post; | |
$this->postLanguage = $postLanguage; | |
add_filter('pll_admin_languages_filter', fn () => []); | |
} | |
/** | |
* Add a post specific language switcher on admin post edit pages, instead of the default | |
* global Polylang language switcher | |
*/ | |
public function add_post_language_switcher(\WP_Admin_Bar $wpAdminBar): void | |
{ | |
$post = $this->post; | |
$postLanguage = $this->postLanguage; | |
if (!$post || !$postLanguage) { | |
return; | |
} | |
$parentNodeID = 'languages'; | |
// Main node (parent item) | |
$wpAdminBar->add_node([ | |
'id' => $parentNodeID, | |
'title' => sprintf( | |
'%s %s: %s', | |
$postLanguage->flag, | |
__('Post Language'), | |
$postLanguage->name | |
), | |
'meta' => ['class' => 'pll-filtered-languages'] | |
]); | |
$translations = pll_get_post_translations($post->ID) ?: []; | |
if (count($translations) < 2) { | |
return; | |
} | |
foreach ($translations as $lang => $translatedPostID) { | |
if ($translatedPostID === $post->ID) { | |
continue; | |
} | |
$editLink = get_edit_post_link($translatedPostID); | |
$langObject = PLL()->model->get_language($lang); | |
$wpAdminBar->add_node([ | |
'id' => 'post-language-' . $lang, | |
'title' => $langObject->flag . ' ' . $langObject->name, | |
'href' => $editLink, | |
'parent' => $parentNodeID, | |
]); | |
} | |
} | |
/** | |
* Move the polylang translation status in the admin area from a field's instructions | |
* to an icon in the field's label, with a (ACF-native) tooltip that | |
* displays the field's translation status. | |
* | |
* Currently depending on preg_replace until | |
* WP_Syntex\Polylang_Pro\Integrations\ACF\Translation_Instructions::get_field_instruction() | |
* becomes `public`. | |
*/ | |
public function acf_prepare_field(?array $field): ?array | |
{ | |
if (empty($field)) { | |
return null; | |
} | |
$pllIcon = '<span style="font-size: 1.2em; vertical-align: middle;" class="dashicons dashicons-translation"></span>'; | |
if (!preg_match( | |
"#{$pllIcon}\s(?<translationStatus>.*)#", | |
$field['instructions'] ?? '', | |
$matches | |
)) { | |
return $field; | |
} | |
/** remove the instructions from the $field */ | |
$field['instructions'] = str_replace($matches[0], '', $field['instructions']); | |
$translationStatus = preg_replace('/This field is (.*)\./', '$1', $matches['translationStatus']); | |
$field['label'] = $field['label'] . " <span title='$translationStatus' style='font-size: 1.2em; vertical-align: middle; opacity: 0.7;' class='dashicons dashicons-translation acf-js-tooltip '></span>"; | |
return $field; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment