Примечание: и снова рекомендую начать с инструкции первоисточника(англ.): https://codex.wordpress.org/User:Lorelle/Installing
или читать первую часть. Более подробо о формате gettext см. в Части 2
Часть 1 «для чайников»
Перевод темы WordPress на русский язык
Оформление большей части шаблонов WordPress на английском языке. Конечно, имеются темы и на русском, а также других языках, но большинство все же остается на английском. В связи с этим может возникнуть необходимость в русификации темы на Вордпресс.
Эта статья поможет разобраться, как локализировать шаблон на русский язык, используя программу Poedit, и как выполнить перевод тем WordPress при помощи одного плагина под названием CodeStyling Localization.
С самого начала следует обозначить, что перевод на русский язык английских строк внутри исходных файлов .php темы – ошибочное мнение. Данную ошибку допускают многие начинающие разработчики и пользователи WordPress.
Для локализации в WordPress используется GNU gettext технология, которая говорит о том, что исходный программный код должен быть прописан на английском языке. Почему так?
Это позволит, например, переводить на русский темы WordPress, не внося изменений в исходный код шаблона. Главное, при выходе обновлений к шаблонам, перевод никуда не исчезнет.
Русификация темы WordPress
Иногда, к сожалению, не каждую тему для WordPress возможно перевести «правильным» способом. Все зависит от того, провел ли разработчик подготовку своей темы к переводу.
Где найти шаблон, готовый к переводу? На самом деле, это несложно. Например, на сайте WordPress.org имеется специальная пометка translation-ready, указывающая на тот факт, что тема подготовлена разработчиком к переводу, и вы сможете перевести ее на русский язык, не изменяя исходный программный код.
Если вы выбрали тему не с официального сайта, то информацию о том, готов ли шаблон к переводу, уточняйте у разработчика.
Совет! Шаблоны для WordPress нужно скачивать с официального ресурса. Использовать темы с «левых» сайтов, особенно, если они бесплатные, очень рискованно.
Файлы .po и .mo
После скачивания темы переходим к этапу «Как перевести тему WordPress на русский язык?». Ищем в теме директорию languages. Именно в ней находятся нужные файлы для перевода темы шаблона на разные языки. Имя файла должно указывать на локаль. К примеру, ru_RU – это русский. Все эти файлы идут с расширением .po и .mo.
.po файлы хранят в текстовом формате переведенные строки. К этим данным обращается переводчик темы.
.mo файлы — те же строки, но в скомпонованном варианте. Данные файлы использует WordPress ядро для отображения выполненного перевода.
Отредактировав перевод в файле .po, его следует скомпилировать в .mo, чтоб подтвердить и применить исправления. Используя редактор Poedit, это можно делать автоматически.
Как русифицировать Вордпресс при помощи Poedit
Poedit — это редактор .po файлов (gettext каталогов), отвечающий за перевод программного обеспечения. Большая часть разработчиков отдает предпочтение gettext, чтоб локализовать программы Unix. Так, решив перевести любимые программы Linux, можно смело использовать Poedit.
Какие особенности имеет редактор Poedit:
- Имеется проверка орфографии.
- .mo файлы компилируются автоматически.
- Присутствует поддержка множественных форм.
- Есть возможность редактировать комментарии.
- В наличии удобный строчный поиск.
Скачать Poedit редактор можно по ссылке https://poedit.net/download.
Запустив программу для создания нового перевода, нужно (через раздел меню Файл) создать из POT-файла каталог.
Выбираем .pot файл (или .po) в директории languages вашей темы. Далее редактор предложит заполнить форму перевода и сохранить новый созданный каталог. Сохраняем его в той же languages директории под именем локали, к примеру, ru_RU.po.
Если нужно, то для внесения поправок в существующий перевод, нужно открыть соответствующий .po файл.
Работа с редактором Poedit не вызывает дополнительных вопросов. Все просто и понятно. Исходный вариант текста расположен слева, а текст перевода — справа. Чтоб внести коррективы в перевод, нужно щелкнуть на нужную строчку и ввести правильный перевод. Нажав сохранить, редактор сам скомпилирует новый перевод и создаст соответствующий .mo файл.
Установка перевода в Вордпресс
После внесения окончательных изменений в перевод, помним, что его нужно сохранить. Следующий этап – это загрузка темы с русским переводом на сайт и его активация.
Если на сайте тема уже установлена, то достаточно загрузить файлы ru_RU.po и ru_RU.mo в ее директорию languages.
Примечание: файлы конкретной темы находятся в …./wp-content/languages/themes/.., для изменить исходный(английский) текст не получилось в Poedit, максимум можно взять чужой перевод и изменить русские названия. Пробую редактировать исходный текст в обычном редакторе сначала.
Это можно сделать, к примеру, через FTP.
Если шаблон установлен на русском языке, то изменения будут видны сразу. Если он на английском языке, следует поменять локаль в wp-config.php. Нужно найти в файле строчку WPLANG и изменить ее:
Примечание: это работало для WordPress v3.9.2 и ниже. Для WordPress v4.0 и выше:
- изменяй язык в настройках административной Консоли. Settings > General > Site Language.
В результате, тема на сайте будет отображена на русском языке. Однако это не единственный способ!
Как русифицировать WordPress, используя плагин?
Плагины для Вордпресс активно используются для настройки тех или иных функций. Этот случай не будет исключением. Плагин CodeStyling Localization, в данном случае, будет очень полезен.
-
- Чтоб воспользоваться плагином, первый шаг — это скачать его и установить. В консоли находим Плагины-Добавить новый.
- В окне поиска вводим CodeStyling Localization и жмем Поиск.
- Когда поисковик его найдет, нажимаем Установить, а далее Активировать.
- В меню консоли сбоку выбираем Инструменты-Локализация.
-
- Появится список, состоящий из локализаций WordPress, установленных тем и плагинов. Внизу будет размещено название нужной темы. Если ее нет, то русифицировать тему придется способом, указанным выше.
При отсутствии в перечне русского языка, нажимаем Добавить новый язык и отмечаем русский. В появившейся строчке русского языка жмем Сканировать и Завершить. Далее в строчке русского языка выбираем Редактировать. Откроется перечень фраз и перевод для них.
Можно редактировать отдельно каждую фразу, выбрав соответствующее действие справа.
Многие фразы отображаются с %s в конце. От этих внешних ссылок в отдельных случаях можно избавиться. Например, перевод «Powered by %1$s and %2$s theme by %3$s» можно заменить «Сайт на WordPress» без ссылок.
Переводить все имеющиеся фразы не обязательно, только самые важные. Проверив и отредактировав перевод, нажимаем над списком фраз Генерировать mo-файл.
Выполнив все этапы и поняв как русифицировать шаблон wordpress, плагин CodeStyling Localization можно смело удалить, так как даже после этого все .po и .mo файлы сохранятся.
Итог
Многие пользователи, выбирая шаблон WordPress, пугаются, увидев английский язык интерфейса. Почему-то не все понимают, что это только шаблон, который можно настроить и модифицировать. Поэтому, подобрав подходящий шаблон на английском языке, не стоит от него отказываться, так как русифицировать WordPress сможет даже новичок.
скопировал-вставил отсюда: https://www.templatemonster.com/ru/faq/kak-rusificirovat-temu-wordpress/
Редактор Poedit-2.1.1-setup.exe залил себе. Работает от windows7 и выше. На линукс ставится просто, из репозиториев: aptitude install poedit
Часть 2. Продвинутая
Перевод сайта с помощью gettext
Довольно часто перед веб-разработчиками возникает необходимость перевести сайт на несколько языков, сделать сайт мультиязычным. Многие веб-подмастерья используют для хранения переводов базу данных, тем самым создавая на неё дополнительную и ненужную нагрузку. Обращение к файловой системе имеет более высокую скорость, но создаёт необходимость грамотно огранизовать хранение и считывание переводов. Благо, в PHP уже имеется максимально оптимальный для таких целей механизм gettext, который не просто работает с файловой системой, так ещё и с уже скомпилированными файлами, обеспечивая наилучшую производительность.
Функции gettext реализуют NLS (Native Language Support) API. Официальная документация находится на сайте gnu.org. Для работы модуля требуется пакет gettext. Его можно установить из репозиториев, например в Debian-дистрибутивах это будет так:
sudo apt-get install gettext
Проверить версию установленного пакета можно командой:
gettext -V
Применение
Самый простой пример использования gettext в PHP:
echo _("message");
Слово «message» ищется в библиотеке переводов и, при его наличии, выводится найденный перевод, иначе выводится исходное слово «message».
Сами переводы хранить неважно где, главное чтоб они были доступны для кода. Для удобства расположим их в корне сайта в папке langs. Пусть будет 3 языка: немецкий, английский и русский. Конечная структура папки langs будет такой:
.
├── de_DE
│ └── LC_MESSAGES
│ ├── de_DE.mo
│ └── de_DE.po
├── en_US
└── ru_RU
└── LC_MESSAGES
├── ru_RU.mo
└── ru_RU.po
Файлы *.po содержат переводы в текстовом виде, *.mo — их компилированные версии. В имени файлов удобно использовать их локаль. Английскому языку эти файлы не обязательны, так как все ключи в коде будем писать на нём. Для ключей можно использовать и любой другой язык, лишь бы кодировка позволяла, но если сайт международный, то крайне желательно использовать английский.
Структура po-файлов простая:
msgid "message"
msgstr "сообщение"
В начале файла пишут служебную информацию, например для русского языка можно написать так:
"POT-Creation-Date: 2016-04-10 17:15+0500\n"
"PO-Revision-Date: 2016-04-29 02:14+0500\n"
"Last-Translator: Sergey\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n % 10==1 && n % 100!=11 ? 0 : n % 10>=2 && n % 10<=4 && (n % 100<10 || n % 100>=20) ? 1 : 2);\n"
Строка «Plural-Forms» задаёт правила для форм множественных чисел. Ниже в примере она будет разобрана подробнее.
Подключение файлов с переводами к проекту:
define('BASE_PATH', realpath(dirname(__FILE__)));
define('LANGUAGES_PATH', BASE_PATH . '/langs');
$locale = ‘ru_RU’;
putenv(«LC_ALL=» . $locale);
setlocale(LC_ALL, $locale, $locale . ‘.utf8’);
bind_textdomain_codeset($locale, ‘UTF-8’);
bindtextdomain($locale, LANGUAGES_PATH);
textdomain($locale);
Здесь подключается русский язык, чтобы подключить другой язык его нужно так же записать в переменную $locale. Брать его из выставленных пользователем настроек или из URL сайта — этот выбор зависит от особенностей Вашего сайта.
Пример использования в коде:
echo mb_ucfirst(_('message')) . '. ' . _('Message') . '. ' . _('Second message') . '. ' . sprintf(_('Message #%d'), 3) . '. 4 ' . ngettext('message', 'messages', 4) . '. 5 ' . ngettext('message', 'messages', 5) . '.';
Здесь шесть обращенией к gettext:
- _(‘message’)
- _(‘Message’)
- _(‘Second message’)
- _(‘Message #%d’)
- ngettext(‘message’, ‘messages’, 4)
- ngettext(‘message’, ‘messages’, 5)
Обращения 1, 2 и 3 максимально просты: есть ключ, ищется перевод. Обращение 4 с этой позиции ничем не отличается от предыдущих, разница лишь в последующем использовании: вставлен %d для подставления туда чисел, например с помощью sprintf. Также можно использовать любые другие ключевые слова для их последующей замены, например «%username%», и заменять их потом с помощью str_replace, главное не перевести их. Обращения 5 и 6 используют множественные формы.
Функция mb_ucfirst самописная, ибо ucfirst плохо работает с юникодом. В надежде что когда-то появится нативная функция mb_ucfirst перед определением функции делается проверка на её существование. Иногда приходится использовать одно и то же слово в разных регистрах, в таких случаях подобные функции помогают.
if (!function_exists('mb_ucfirst')) {
function mb_ucfirst($string) {
return mb_strtoupper(mb_substr($string, 0, 1, 'UTF-8'), 'UTF-8') . mb_substr($string, 1, mb_strlen($string), 'UTF-8');
}
}
В итоге файл langs/ru_RU/LC_MESSAGES/ru_RU.po пусть будет таким (даты будут изменяться автоматически описанным ниже ПО):
msgid ""
msgstr ""
"POT-Creation-Date: 2016-04-10 17:15+0500\n"
"PO-Revision-Date: 2016-04-29 02:14+0500\n"
"Last-Translator: username\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n % 10==1 && n % 100!=11 ? 0 : n % 10>=2 && n % 10<=4 && (n % 100<10 || n % 100>=20) ? 1 : 2);\n"
msgid «Second message»
msgstr «Второе сообщение»
msgid «Message #%d»
msgstr «Сообщение #%d»
msgid «message»
msgid_plural «messages»
msgstr[0] «сообщение»
msgstr[1] «сообщения»
msgstr[2] «сообщений»
Третья запись («message») покрывает обращения 1, 5 и 6, первая и вторая — 3 и 4. Перевод для обращения 2 не будет найден, т.к. регистрозависимость.
Третья запись здесь самая интересная, т.к. описывает множественные формы. Правила описаны в начале файла в пункте «Plural-Forms».
"Plural-Forms: nplurals=3; plural=(n % 10==1 && n % 100!=11 ? 0 : n % 10>=2 && n % 10<=4 && (n % 100<10 || n % 100>=20) ? 1 : 2);\n"
nplurals — количество форм, в данном случае равно трём.
plural — сами правила, представляют из себя вложенный тернарный оператор, который возвращает число от 0 до 2, в зависимости от этого числа берётся элемент из msgstr. Сравнив эти условия и числа с примером из po-файла всё станет понятно. Правила в разных языках отличаются.
Немецкий файл langs/de_DE/LC_MESSAGES/de_DE.po заполняется по аналогии:
msgid ""
msgstr ""
"POT-Creation-Date: 2016-04-10 17:15+0500\n"
"PO-Revision-Date: 2016-04-29 02:14+0500\n"
"Last-Translator: username\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid «Second message»
msgstr «Zweite nachricht»
msgid «Message #%d»
msgstr «Nachricht #%d»
msgid «message»
msgid_plural «messages»
msgstr[0] «nachricht»
msgstr[1] «nachrichten»
В нём множественных форм две, потому и правило заметно проще. Также изменился пункт «Language». Это единственные поля в данном примере которые нужно менять при добавлении новых языков.
Компилирование MO
Из po-файлов получить скомпилированный mo-файл можно несколькими способами.
Первый — с помощью программ вроде Poedit. В ней есть и редактирование po-файлов и возможность автоматически компилировать файл MO при сохранении. Включается/отключается она в общих настройках приложения. Минус — нельзя задать параметры этого компилирования. Плюс — там немало возможностей для редактирования переводов; например, сканирование кода на предмет вызова gettext и добавления их в PO.
Второй способ — консольная команда msgfmt. Полный список параметров доступен в документации по ссылке, но обычно достаточно такой простой команды:
/usr/bin/msgfmt "ru_RU.po" -f -o "ru_RU.mo"
Здесь файл ru_RU.mo компилируется из находящихся в файле ru_RU.po исходников с использованием fuzzy-записей. Fuzzy — это нечёткие переводы, которые могут быть некорректными. Появляются они, например, при автоматических переводах. Если возникают сомнения в правильности этих переводов, то параметр -f следует убрать.
Чтобы скомпилировать все файлы в папке langs можно воспользоваться bash-скриптом. Предположим, что все bash-скрипты расположены в папке bash в корне сайта:
cd ../langs
for lang_locale in * ; do
if [ ! -f "$lang_locale/LC_MESSAGES/$lang_locale.po" ]; then
continue
fi
cd "$lang_locale/LC_MESSAGES"
/usr/bin/msgfmt "$lang_locale.po" -f -o "$lang_locale.mo"
echo "$lang_locale - compiled"
cd ../../
done
Проверку наличия файла (третья строка) нельзя назвать обязательной, но она предотвратит ошибки в случае если в папке найдутся какие-либо не относящиеся к переводам файлы и папки. Итог выполнения:
$ sh compile.sh
de_DE - compiled
ru_RU - compiled
После этого можно проверить вывод переводов через PHP. Итоговый index.php выглядит так:
define('BASE_PATH', realpath(dirname(__FILE__)));
define('LANGUAGES_PATH', BASE_PATH . '/langs');
$locale = ‘ru_RU’;
putenv(‘LC_ALL=’ . $locale);
setlocale(LC_ALL, $locale, $locale . ‘.utf8’);
bind_textdomain_codeset($locale, ‘UTF-8’);
bindtextdomain($locale, LANGUAGES_PATH);
textdomain($locale);
if (!function_exists(‘mb_ucfirst’)) {
function mb_ucfirst($string) {
return mb_strtoupper(mb_substr($string, 0, 1, ‘UTF-8’), ‘UTF-8’) . mb_substr($string, 1, mb_strlen($string), ‘UTF-8’);
}
}
echo mb_ucfirst(_(‘message’)) . ‘. ‘ . _(‘Message’) . ‘. ‘ . _(‘Second message’) . ‘. ‘ . sprintf(_(‘Message #%d’), 3) . ‘. 4 ‘ . ngettext(‘message’, ‘messages’, 4) . ‘. 5 ‘ . ngettext(‘message’, ‘messages’, 5) . ‘.’;
Результатом выполнения кода будет это:
Сообщение. Message. Второе сообщение. Сообщение #3. 4 сообщения. 5 сообщений.
Также самостоятельно проверьте вывод в немецкой локали de_DE.
Если вывод по-прежнему на английском, то, вероятно, в Вашей системе не установлены нужные локали. Список умеющихся можно получить командой:
locale -a
Недостающие можно добавить командой (на примере немецкой):
sudo locale-gen de_DE.utf8
После добавления новой локали иногда требуется перезапуск апача, иначе он её не увидит.
sudo service apache2 restart
Сканирование кода, добавление новых переводов
Ручное добавление всех новых фраз в po-файлы в процессе разработки — не самый удобный способ, из-за него приходится отвлекаться от самой разработки. Гораздо удобнее сразу писать код так, словно перевод уже есть — когда он появится тогда он и выведется. В таком случае потребуется сканирование кода на предмет новых переводов. Для этих целей используется утилита xgettext.
Добавим в index.php новое слово, пусть будет «Application»:
echo mb_ucfirst(_('message')) . '. ' . _('Message') . '. ' . _('Second message') . '. ' . sprintf(_('Message #%d'), 3) . '. 4 ' . ngettext('message', 'messages', 4) . '. 5 ' . ngettext('message', 'messages', 5) . '. ';
echo _("Application");
Bash-скрипт для сканирования кода и добавления новых найденных переводов пусть лежит в той же папке bash. Сначала разберём этот пример сканирования:
LIST=`find . -name "*.php"`
/usr/bin/xgettext --language=PHP $LIST --from-code=UTF-8 --no-location --no-wrap -o /tmp/xgettext.pot
Здесь происходит поиск всех файлов *.php, затем весь этот список отдаётся в xgettext и все найденные в этих файлах фразы (без указания их расположения в файлах (—no-location) и без переносов(—no-wrap)) пишутся в /tmp/xgettext.pot. Дополнительно заданы кодировка файлов (UTF-8) и язык (PHP). Утилита поддерживает немало других языков, включая JavaScript. Название и расположение файла экспорта можно сделать любым другим, но временная папка /tmp подходит для этого дела идеально.
Получившийся файл — это стандартный po-файл, только без настроек и переводов. В нём находятся все используемые в index.php фразы: к трём уже имеющимся в наших файлах добавились две — «Message» и «Application». Добавлять их вручную к имеющимся тоже не вариант, для этих целей лучше подойдёт утилита msgmerge. В итоге со сканированием получится вот такой bash-скрипт:
cd ..
echo "Parsing..."
LIST=`find . -name "*.php"`
/usr/bin/xgettext --language=PHP $LIST --from-code=UTF-8 --no-location --no-wrap -o /tmp/xgettext.pot
echo «Merging…»
cd langs
for lang_locale in * ; do
if [ ! -f «$lang_locale/LC_MESSAGES/$lang_locale.po» ]; then
continue
fi
echo $lang_locale
cd «$lang_locale/LC_MESSAGES»
/usr/bin/msgmerge «$lang_locale.po» /tmp/xgettext.pot -U —backup=off —no-wrap —no-fuzzy-matching
cd ../../
done
Слияние файлов $lang_locale.po и xgettext.pot происходит с обновлением первого (параметр -U), без создания бэкапа (—backup=off; ибо зачем оно когда есть git и аналоги), без переносов длинных строк (—no-wrap; ибо это мешает чтению исходников) и без автоперевода по имеющимся фразам (—no-fuzzy-matching; странный включенный по умолчанию функционал, который ищет по имеющимся переводам похожие и добавляет их к новым фразам с пометкой fuzzy, при этом работает плохо и немного замедляет весь процесс слияния).
Результат выполнения:
$ sh lang.sh
Parsing...
Merging...
de_DE
.... завершено.
ru_RU
... завершено.
Количество точек перед «завершено» зависит от времени выполнения.
После выполнения команды оба недостающих ранее слова добавились в po-файлы внутри папки langs. Теперь им стоит добавить перевод (вручную или с помощью Poedit) и затем выполнить компилирование.
Конечное дерево файлов данного проекта выглядит так:
.
├── bash
│ ├── compile.sh
│ └── lang.sh
├── index.php
└── langs
├── de_DE
│ └── LC_MESSAGES
│ ├── de_DE.mo
│ └── de_DE.po
├── en_US
└── ru_RU
└── LC_MESSAGES
├── ru_RU.mo
└── ru_RU.po
Добавление нового языка
Например, нужно добавить испанский язык. Обозначение локали языка можно найти, например, здесь или здесь (но вместо «-» использовать «_»). Интернациональному испанскому (или испанскому из Испании) соответствует обозначение es_ES.
Нужно проделать эти шаги:
- Создать папку langs/es_ES/LC_MESSAGES, в ней создать файл es_ES.po.
- Заполнить его по аналогии с приведёнными выше языками, подправив поля «Language» и, при необходимости, «Plural-Forms». Сами фразы можно не добавлять:
msgid ""
msgstr ""
"POT-Creation-Date: 2016-04-10 17:15+0500\n"
"PO-Revision-Date: 2016-04-29 02:14+0500\n"
"Last-Translator: username\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n - Провести сканирование кода — все имеющиеся фразы добавятся в этот файл (bash-скрипт выше)
- Заполнить файл переводами (вручную в текстовом редакторе или специальными программами, лучше всего с этой задачей справятся переводчики)
- Скомпилировать MO (bash-скрипт выше)
Затем, если сайт уже рабочий, как-нибудь добавить новый язык в интерфейс, чтобы пользователи могли его выбрать и использовать.
Аналогично можно использовать gettext для любых других проектов с другими языками программирования.
Дополнительно:
Источник: http://coddism.com/php/perevod_sajta_s_pomocshju_gettext