Проводить локализацию проектов
PHP, и тем более
WordPress, силами
gettext не приходилось, но на днях делал это с некоторыми
bash-скриптами. Возможно мой опыт будет полезен.
1. Необходимо определить домен и область поиска файлов сообщений.
Домен задается функцией
textdomain, а путь к ресурсам -
bindtextdomain.
bindtextdomain('example', './local');
textdomain('example');
2. В коде, весь локализуемый текст следует выводить через функцию
gettext. Например:
echo gettext("Hello world!");
echo gettext("Test123");
Можно использовать фразы, либо ключи.
Если использовать фразы, то не нужно будет создавать ресурсы для языка по умолчанию. Из минусов такого подхода, то что некоторые фразы могут иметь разное значение в зависимости от контекста использования, но эту проблему в принципе можно решить перефразированием.
Если использовать ключи (например,
MSG_ABOUT_TEXT1), то придется создавать ресурсы для языка по умолчанию. При отсутствии ресурсов, или если что-то сломается, пользователю будут выводиться ключи, что не очень хорошо.
Какой подход выбрать, зависит от сложности проекта и предпочтений. Фразы проще и проблем с ними в небольших проектах точно не будет.
3. Необходимо извлечь строки из кода и создать файлы
po. Делается это при помощи набора инструментов
gettext. Если ранее этим заниматься не приходилось, то скорее всего придется выполнить установку необходимых компонентов.
Под
Debian/Ubuntu установить пакет
gettext можно следующей командой:
sudo apt-get install gettext
Под остальными разновидностями
Linux систем в общем-то примерно также, только диспетчер пакетов будет другим.
Под
Windows мне не доводилось этим заниматься. Думаю, можно что-нибудь найти. Например,
sourceforge.net/projects/gettext
Я опишу только порядок действий под
Linux (конкретно
Debian).
Для создания
po-файла необходимо выполнить следующую команду:
xgettext --extract-all --default-domain=example --from-code=utf-8 /путь к проекту/*.php
Параметры:
--default-domain - имя домена, должно соответствовать домену, который используется в коде
PHP (
textdomain). Не путать с доменом сайта, хотя обычно используется название проекта;
--from-code=имя кодировки текста. Например:
utf-8;
--extract-all - указывает на необходимость извлечения всех строк.
Дополнительно можно указать параметры:
--output=имяФайла.po - по умолчанию строки будут извлечены в файл
messages.po, этот параметр позволяет указать любое имя файла;
--no-wrap - запрет разбития длинных строк;
--join-existing - если есть предыдущие извлеченные строки, то эта опция указывает на необходимость склейки новых найденных строк с существующими (использовать, только если
po-файл существует);
--copyright-holder="Вася Пупкаидзе" - кому принадлежат авторские права.
Параметр
--help позволяет посмотреть список всех параметров :-)
Программа создаст
po-файл примерно следующего содержания:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-15 14:55+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "Hello world!"
msgstr ""
msgid "Test123"
msgstr ""
msgid - это идентификатор сообщения.
msgstr - перевод.
После указания перевода и сохранения изменений в файле
po:
msgid "Hello world!"
msgstr "Привет, мир!"
msgid "Test123"
msgstr "Тест123"
Его необходимо компилировать в файл
mo.
Делается это при помощи команды
msgfmt:
msgfmt --output-file="/путь к файлу.mo" "/путь к файлу.po"
Для себя я написал следующий
bash-скрипт, который компилирует все файлы
po в каталоге (включая все подкаталоги), в котором был запущен скрипт:
#!/bin/bash
lang="$1"
path="$(cd "$(dirname "$0")" && pwd)"
if [[ -n "$lang" ]]; then
path="$path/$lang"
if [[ ! -d "$path" ]]; then
mkdir "$path"
fi
fi
cd "$path"
find "$path" -name "*.po" | while read -r f; do
po_dir="$(dirname $f)"
po_file="$(basename $f)"
po_name="$(echo $po_file | cut -d'.' -f1)"
msgfmt --output-file="$po_dir/$po_name.mo" "$f" && \
printf "Created: $po_dir/$po_name.mo\n" || \
printf "ERROR: Could not create mo-file from: $f\n"
done
Если все пройдет без эксцессов, файлы
mo следует разместить по подпапкам
LC_MESSAGES нужных культур, которые должны располагаться в папке указанной в коде
PHP функцией
bindtextdomain. Запутано вышло, проще показать :-)
Если:
bindtextdomain('example', './local');
textdomain('example');
, то структуру размещения файлов
mo:
/local/ru/LC_MESSAGES/messages.mo
/local/en/LC_MESSAGES/messages.mo
/local/en_US/LC_MESSAGES/messages.mo
/local/ru_GB/LC_MESSAGES/messages.mo
/local/[Код культуры]/LC_MESSAGES/messages.mo
/local - часть пути, указанная в коде
PHP: bindtextdomain('example', '
./local');
Код культуры - это стандартный (
ISO 639) двузначный код языка, или код языка с указанием кода региона (
ISO 639 + ISO 3166):
ru (русский язык),
ru_RU (русский язык, Россия),
en (английский язык),
en_US (американский английский) и т.п.
Честно говоря, я не вижу пока никаких особых преимуществ от использования
gettext. Слишком сложный процесс генерирования всех этих
po и
mo. Проще и удобней текстовой файл с нужными ресурсами создать, или использовать базу. Хотя работу с
gettext можно автоматизировать, но придется потратить на это время.