Добавляем мультиязычность в Wordpress #2: Loco Translate
Прододжаем эпопею с добавлением мультиязычности в Wordpress. В этой статье переводим надписи и элементы шаблонов Pods с помощью плагина Loco и пары хаков.
В предыдущей статье мы рассмотрели плагин WPGlobus, для переводов текстов сайта. Однако, WPGlobus не всегда удобен, поскольку расчитан на перевод содержимого сайта. Для перевода различных надписей, служебной информации и прочего, Wordpress предлагает встроенную поддержку системы переводов (i18n) на основе gettext.
Очевидно, вести эти файлы не очень удобно, даже при использовании специального ПО, поскольку это подразумевает изменение PO/MO файлов после каждого изменения файлов темы, а также это неудобно конечному пользователю — Wordpress в первую очередь делался для людей не искушённых в программировании, поэтому было бы вполне логично ожидать, что подобная система может и должна работать без участия программиста.
Решение проблемы изменения файлов переводов берёт на себя замечательный плагин Loco Translate. Loco позволяет генерировать шаблоны переводов (POT файлы) и создавать/модифицировать переводы для тем, плагинов и даже самого Wordpress.
Для использования подобного функционала, в вашей теме должна быть включена поддержка textdomain:
<?php
/* functions.php */
function my_theme_setup() {
// убедитесь, что php имеет право на чтение/запись в каталоге /wp-content/themes/my_theme/languages
load_theme_textdomain( 'my_theme', get_template_directory() . '/languages' );
/* ещё какой-то код */
}
add_action('after_setup_theme', 'my_theme_setup');
?>
Соответственно, в каталоге languages вашей темы будут храниться файлы с переводами. Тут не важно, есть–ли у вас готовые po/mo файлы или нет, Loco либо создаст новые, либо подхватит существующие файлы.
Для удобства использования переводов (а для использования в Pods Template это будет необходимостью), рекомендую создать shortcut для функции перевода:
<?php
/* functions.php */
function my_theme_t($text) {
return __($text, 'my_theme');
}
?>
Теперь можно установить плагин Loco Translate — описывать установку нет смысла (в wp все плагины устанавливаются одинаково), однако давайте посмотрим на интерфейс Loco:
Здесь нас интересует раздел Active themes, выбираем тему и видим примерно следующее:
Следующий шаг — создание/изменение POT файла. Переходим в Create/Edit template и кликаем по кнопке Sync, чтобы Loco подобрал шаблонные строки из стандартных функций перевода сам (__, _e), после чего добавляем все свои дополнительные шаблонные строки в файл и сохраняем шаблон (Save).
После того, как шаблон был успешно сохранён, самое время позаботиться о переводах шаблонных строк. Для этого добавляем нужные языки (New language) и переходим в режим редактирования (Edit):
Сперва необходимо синхронизировать файл переводов с шаблоном — кнопка Sync, после чего можно начать забивать переводы в поле translation (используя сочетание ctrl+enter автоматически выбирается следующая непереведённая строка).
После перевода всех нужных строк сохраняем переводы кнопкой Save.
ОК, причём тут Pods???!
Как известно, Pods сам по себе очень крут и могуч, однако у Pods framework есть ещё и охрененно удобная штука под названием Pods Templates. По сути, это небольшой шаблонный движок завязанный на сущности Pods. Эти шаблоны можно использовать в шорткодах или виджетах Pods, что позволяет почти полностью избавиться от необходимости редактировать код вне админки.
* * *
Но у шаблонного движка есть один недостаток, а именно — отсутствие поддержки Wordpress i18n функций для статичного текста.
* * *
Авторы обещают переезд на новый шаблонный движок, который будет учитывать все эти требования в будущих версиях, однако на данный момент готового решения у них нет.
Но не стоит унывать! В Wordpress встроена очень мощная система хуков, поэтому мы вполне можем создать свои magic tags для шаблонов Pods!
<?php
/* functions.php */
// разрешаем использовать в шаблонах функцию my_theme_t
// это нужно, из соображений безопасности
// чтобы избежать применения произвольной функции к произвольному тексту
function my_theme_pods_template_echo_tag_allowed_functions($funcs) {
return array_merge($funcs, array('my_theme_t'));
}
add_filter('pods_template_echo_tag_allowed_functions', 'my_theme_pods_template_echo_tag_allowed_functions');
/*
Добавляем в Pods Template тег echo {@="TEXT",FILTER}
*/
function my_theme_pods_template_echo($code) {
$allowed_functions = apply_filters('pods_template_echo_tag_allowed_functions', array() );
$echo_tag_rx = '/{@="([^"]*)"\,?([^}]*)}/m';
$matches = array();
return preg_replace_callback($echo_tag_rx, function ($matches) use ($allowed_functions) {
// return value "as is" if no valid filter passed
$executed = $matches[1];
if (in_array($matches[2], $allowed_functions)) {
$executed = call_user_func($matches[2], $matches[1]);
}
return $executed;
}, $code);
}
add_filter('pods_templates_pre_template', 'my_theme_pods_template_echo');
Я уже создал feature request в официальном репозитории, и вроде как нашёл поддержку пользователей, однако, у изначального подхода имеются некоторые проблемы с безопасностью, как указал @jamesgol, поэтому в первоначальный вариант я добавил обязательный фильтр pods_template_echo_tag_allowed_functions, контроллирующий разрешённые к исполнению функции.
Этот код добавляет в Pods Templates поддержку дополнительного тега со следующей сигнатурой:
{@="Текст для перевода",allowed_function}
А вот пример использования этого тега в шаблоне Pods:
[before]
<div class="b-about-us-reviews--left">
[/before]
<div class="b-review">
<div class="b-review__quote">
<blockquote>
{@post_content,floris_trim_quotes_text}
</blockquote>
<div class="b-review__link_container">
<a href="{@post_type,get_post_type_archive_link}">{@="More reviews",floris_t}</a>
</div>
</div>
<div class="b-review__author">
<img class="b-review__author_photo" src="{@post_thumbnail_url.thumbnail}">
<div class="b-review__author_info">
<p>
<strong>
{@post_title}
</strong>
</p>
<p>
<small>
{@position}
</small>
</p>
</div>
</div>
</div>
[after]
</div>
[/after]
Ну и соответственно вывод для разных языков: