Last active
December 14, 2020 16:26
-
-
Save markhowellsmead/7e3c298cfefc2f0572a7f2eb6afb5f43 to your computer and use it in GitHub Desktop.
This add-in gives you full Polylang support in WordPress customizer. By full support I mean that you customize each language site differently. Original from https://github.com/soderlind/customizer-polylang
This file contains 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
/** | |
* | |
*/ | |
/* global wp, jQuery */ | |
/* exported PluginCustomizer */ | |
var PSPolyLang = (function (api, $) { | |
'use strict'; | |
var component = { | |
data: { | |
url: null, | |
languages: null, | |
current_language: null, | |
} | |
}; | |
/** | |
* Initialize functionality. | |
* | |
* @param {object} args Args. | |
* @param {string} args.url Preview URL. | |
* @returns {void} | |
*/ | |
component.init = function init(pll) { | |
_.extend(component.data, pll); | |
if (!pll || !pll.url || !pll.languages || !pll.current_language) { | |
throw new Error('Missing args'); | |
} | |
api.bind('ready', function () { | |
api.previewer.previewUrl.set(pll.url); | |
var languages = pll.languages; | |
var current_language = pll.current_language; | |
var current_language_name = ''; | |
var html = '<span style="position:relative;left:38px">Language: </span>'; | |
html += '<select id="pll-language-select" style="position:relative; left: 35px; top: 1px; padding: 0 2em 0 .5em;">'; | |
for (var i = 0; i < languages.length; i++) { | |
var language = languages[i]; | |
var selected = (language.slug === current_language) ? 'selected' : ''; | |
current_language_name = (language.slug === current_language) ? language.name : ''; | |
html += '<option ' + selected + ' value="' + language.slug + '">' + language.name + '</option>'; | |
} | |
html += '</select>'; | |
$(html).prependTo('#customize-header-actions'); | |
$('body').on('change', '#pll-language-select', function () { | |
var language = $(this).val(); | |
var old_url = window.location.href; | |
window.location.href = updateQueryStringParameter(window.location.href, 'lang', language); | |
}); | |
}); | |
function updateQueryStringParameter(uri, key, value) { | |
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i"); | |
var separator = uri.indexOf('?') !== -1 ? "&" : "?"; | |
if (uri.match(re)) { | |
return uri.replace(re, '$1' + key + "=" + value + '$2'); | |
} else { | |
return uri + separator + key + "=" + value; | |
} | |
} | |
}; | |
return component; | |
}(wp.customize, jQuery)); |
This file contains 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 | |
/** | |
* This add-in gives you full Polylang support in WordPress customizer. By full support I mean that you customize each language site differently. | |
* Minor adaptation from https://github.com/soderlind/customizer-polylang to fit into the Hello Roots logic. | |
*/ | |
namespace SayHello\Theme\Plugin; | |
class CustomizerPolylang | |
{ | |
public function run() | |
{ | |
if (!function_exists('pll_current_language') || !function_exists('pll_default_language')) { | |
return; | |
} | |
/** | |
* Force "The language is set from content" (in Language->Settings->URL modifications) | |
*/ | |
$options = get_option('polylang'); | |
if (isset($options['force_lang']) && 0 !== $options['force_lang']) { | |
$options['force_lang'] = 0; | |
update_option('polylang', $options); | |
} | |
add_filter('pll_preferred_language', '__return_false'); | |
add_action('customize_controls_enqueue_scripts', [$this, 'addLangToCustomizerPreviewer'], 9); | |
add_action('wp_before_admin_bar_render', [$this, 'onWpBeforeAdminBarRender'], 100); | |
add_action('admin_menu', [$this, 'onAdminMenu'], 100); | |
$theme_stylesheet_slug = get_option('stylesheet'); | |
$option_types = ['blogname', 'blogdescription', 'site_icon']; | |
add_filter('option_theme_mods_' . $theme_stylesheet_slug, [$this, 'onOptionThemeModsGet'], 10, 1); | |
add_filter('pre_update_option_theme_mods_' . $theme_stylesheet_slug, [$this, 'onOptionThemeModsUpdate'], 10, 2); | |
foreach ($option_types as $option_type) { | |
add_filter('pre_option_' . $option_type, [$this, 'onWpOptionGet'], 10, 3); // get_option hook. | |
add_filter('pre_update_option_' . $option_type, [$this, 'onWpOptionUpdate'], 10, 3); // update_option hook. | |
} | |
$this->registerPolylangColumnStrings('options_footer_columns', ['title', 'text']); | |
$this->registerPolylangColumnStrings('options_footer_logos', ['image', 'url']); | |
} | |
/** | |
* Helper to fetch custom customizer db content. | |
* | |
* @return mixed Customizer array or false. | |
*/ | |
protected function getCustomCustomizerOption() | |
{ | |
$current_language = pll_current_language(); | |
$theme_slug = get_option('template'); | |
$option_prefix = \str_replace('-', '_', $theme_slug); | |
$option_name = $option_prefix . '_customizer_polylang_settings_' . $current_language; | |
return get_option($option_name, false); | |
} | |
/** | |
* Helper to update custom customizer db content. | |
* | |
* @param mixed $data Data to insert. | |
* | |
* @return bool Success. | |
*/ | |
protected function updateCustomCustomizerOption($data) | |
{ | |
$current_language = pll_current_language(); | |
$theme_slug = get_option('template'); | |
$option_prefix = \str_replace('-', '_', $theme_slug); | |
$option_name = $option_prefix . '_customizer_polylang_settings_' . $current_language; | |
return update_option($option_name, $data); | |
} | |
/** | |
* Helper | |
* | |
* @return bool If the current language is the default language. | |
*/ | |
protected function currentLangNotDefault() | |
{ | |
return pll_current_language() !== pll_default_language(); | |
} | |
/** | |
* Check the custom db field on get_option hook to be able to return custom language value. | |
* If the current language is default, then return from default wp option | |
* | |
* @param bool $pre_option This is false. If something else is returned wp exits the check in db and uses this value. | |
* @param string $option Option name asked for. | |
* @param mixed $default Default value, second args when asking for options. | |
* | |
* @return mixed | |
*/ | |
public function onWpOptionGet($pre_option, $option, $default) | |
{ | |
// If not the default language, then skip the custom check and wp will the use default options. | |
if ($this->currentLangNotDefault()) { | |
$data = $this->getCustomCustomizerOption(); | |
// Found the custom option. Move on. | |
if (is_array($data) && isset($data['options']) && isset($data['options'][$option])) { | |
return $data['options'][$option]; | |
} | |
} | |
return $default; | |
} | |
/** | |
* Update the custom db field on get_option hook. | |
* If the current language is not default, then return old value to prevent from saving to default wp option. | |
* | |
* @param mixed $value The new, unserialized option value. | |
* @param mixed $old_value The old option value. | |
* @param string $option Option name. | |
* | |
* @return mixed | |
*/ | |
public function onWpOptionUpdate($value, $old_value, $option) | |
{ | |
// Fetch custom option db field. | |
$data = $this->getCustomCustomizerOption(); | |
$theme_slug = get_option('template'); | |
// If false, the field hasn't been created yet, so it must be created. | |
if (false === $data) { | |
$data = [ | |
'template' => $theme_slug, | |
'mods' => [], | |
'options' => [], | |
]; | |
} | |
// Make sure the options array exists. We are going to use it soon. | |
if (!isset($data['options'])) { | |
$data['options'] = []; | |
} | |
$data['options'][$option] = $value; | |
// Update option value in custom db field. (Not necessary to save for default language since it uses default wp option fields for values when get option). | |
$this->updateCustomCustomizerOption($data); | |
// If the current language is not the default language, prevent saving to option table by passing the old value back. It will then exit after the filter. | |
if ($this->currentLangNotDefault()) { | |
return $old_value; | |
} | |
return $value; | |
} | |
/** | |
* Check the custom db field on get_option customizer field option name hook to be able to return custom language value. | |
* Parse arguments with default wp customizer values to make sure all are present in the return. | |
* | |
* @param array $value The customizer settings. | |
* | |
* @return array | |
*/ | |
public function onOptionThemeModsGet($value) | |
{ | |
$data = $this->getCustomCustomizerOption(); | |
if (isset($data['mods']) && is_array($data['mods']) && !empty($data['mods'])) { | |
$value = wp_parse_args($data['mods'], $value); | |
} | |
// Remove members with integer key from mods. | |
foreach ($value as $key => $mod) { | |
if (is_numeric($key)) { | |
unset($value[$key]); | |
} | |
} | |
return $value; | |
} | |
/** | |
* Update custom customizer option. | |
* If the current language is not default, then return old value to prevent from saving to customizer wp option. | |
* | |
* @param mixed $value The new, unserialized option value. | |
* @param mixed $old_value The old option value. | |
*/ | |
public function onOptionThemeModsUpdate($value, $old_value) | |
{ | |
$current_data = $this->getCustomCustomizerOption(); | |
$theme_slug = get_option('template'); | |
$data = [ | |
'template' => $theme_slug, | |
'mods' => isset($current_data['mods']) ? $current_data['mods'] : [], | |
'options' => isset($current_data['options']) ? $current_data['options'] : [], | |
]; | |
if (is_array($value) && !empty($value)) { | |
foreach ($value as $key => $val) { | |
$data['mods'][$key] = $val; | |
} | |
} | |
$this->updateCustomCustomizerOption($data); | |
if ($this->currentLangNotDefault()) { | |
return $old_value; | |
} | |
return $value; | |
} | |
/** | |
* If Polylang activated, set the preview url and add select language control | |
*/ | |
public function addLangToCustomizerPreviewer() | |
{ | |
$handle = 'dss-add-lang-to-template'; | |
$src = get_stylesheet_directory_uri() . '/assets/scripts/customizer-polylang.js'; | |
$deps = ['customize-controls']; | |
$version = rand(); | |
$in_footer = 1; | |
wp_enqueue_script($handle, $src, $deps, $version, $in_footer); | |
$language = (empty($_REQUEST['lang'])) ? pll_current_language() : $_REQUEST['lang']; | |
if (empty($language)) { | |
$language = pll_default_language(); | |
} | |
if (!empty($_REQUEST['url'])) { | |
$current_url = add_query_arg('lang', $language, $_REQUEST['url']); | |
} else { | |
$current_url = add_query_arg('lang', $language, pll_home_url($language)); | |
} | |
wp_add_inline_script( | |
$handle, | |
sprintf( | |
'PSPolyLang.init( %s );', | |
wp_json_encode( | |
[ | |
'url' => $current_url, | |
'languages' => get_transient('pll_languages_list'), | |
'current_language' => $language, | |
] | |
) | |
), | |
'after' | |
); | |
} | |
/** | |
* Append lang="contrycode" to the customizer url in the adminbar | |
* | |
* @return void | |
*/ | |
public function onWpBeforeAdminBarRender() | |
{ | |
global $wp_admin_bar; | |
$customize_node = $wp_admin_bar->get_node('customize'); | |
if (!empty($customize_node)) { | |
$customize_node->href = add_query_arg('lang', pll_current_language(), $customize_node->href); | |
$wp_admin_bar->add_node($customize_node); | |
} | |
} | |
/** | |
* Append lang="contrycode" to the customizer url in the Admin->Apperance->Customize menu | |
* | |
* @return void | |
*/ | |
public function onAdminMenu() | |
{ | |
global $submenu; | |
$parent = 'themes.php'; | |
if (!isset($submenu[$parent])) { | |
return; | |
} | |
foreach ($submenu[$parent] as $k => $d) { | |
if ('customize' === $d['1']) { | |
$submenu[$parent][$k]['2'] = add_query_arg('lang', pll_current_language(), $submenu[$parent][$k]['2']); | |
break; | |
} | |
} | |
} | |
public function registerPolylangColumnStrings($option_name, $fields) | |
{ | |
$columns = get_option($option_name); | |
$theme_name = wp_get_theme()->get('Name'); | |
if (!empty($columns)) : | |
for ($i = 0; $i < $columns; $i++) : | |
foreach ($fields as $field) { | |
pll_register_string($option_name . '_' . $i . '_' . $field, get_option($option_name . '_' . $i . '_' . $field), $theme_name, true); | |
} | |
endfor; | |
endif; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment