Я знаю, что это старый вопрос, но я чувствую, что в ответах не хватает более практического подхода от начала до конца.Вот что я сделал, чтобы заставить перевод работать, используя PHP gettext
library и Poedit без использования каких-либо дополнительных библиотек PHP на сервере Debian:
Подготовительный шаг 1:Установите gettext
и локали на сервере
Я не уверен, как это делается с другими операционными системами, но для Debian вы делаете:
sudo apt-get install gettext
sudo dpkg-reconfigure locales
Редактировать : Я предполагал, что Ubuntu будет таким же, как Debian, но, видимо, он немного другой.См. на этой странице для получения инструкций по установке локалей в Ubuntu.
Убедитесь, что вы выбрали все локалей, которые вы хотите использовать.Затем вы должны увидеть что-то вроде:
Generating locales (this might take a while)...
en_US.UTF-8... done
es_MX.UTF-8... done
fr_FR.UTF-8... done
zh_CN.UTF-8... done
Generation complete.
Примечание: Убедитесь, что вы выбрали правильные варианты и кодировки символов (скорее всего UTF-8) для каждого языка.Если вы установите es_MX.UTF-8
и попытаетесь использовать es_ES.UTF-8
или es_MX.ISO-8859-1
, он не будет работать.
Шаг подготовки 2: Установите Poedit на компьютеры переводчиков
Poedit доступен по адресухранилище программного обеспечения для большинства операционных систем Linux.Для Debian просто выполните:
sudo apt-get install poedit
Для Windows и Mac, перейдите по адресу: https://poedit.net/download
Начните кодирование:
Хорошо, теперь выготовы начать кодирование.Я написал следующую gettext()
функцию-обертку для перевода как единственного, так и множественного числа:
function __($text, $plural=null, $number=null) {
if (!isset($plural)) {
return _($text);
}
return ngettext($text, $plural, $number);
}
Пример использования:
// Singular
echo __('Hello world');
// Plural
$exp = 3;
printf(
__(
'Your account will expire in %d day',
'Your account will expire in %d days',
$exp
),
$exp
);
Это будет работать для всех языков, а не только для языков, где множественное числовсе, где n != 1
- это включает языки с множественным множественным типом.
Вы также можете добавить примечания переводчика, например:
/** NOTE: The name Coconut Hotel is a brand name and shouldn't be
translated.
*/
echo __('Welcome to Coconut Hotel');
Вы можете изменить текст с NOTE
на любой другойхочу, но вам придется изменить его в сценарии оболочки ниже. Важно : примечание переводчика должно быть частью комментария к строке , непосредственно предшествующего функции __()
, иначе оно не будет обнаружено, когда мы сканируем файлы PHP на предмет переводимых строк.
// Warning! THIS WILL NOT WORK!
/* NOTE: This translator's note will not be picked up because it is
not immediately preceding the __() function. */
printf(
__(
'Your account will expire in %d day',
'Your account will expire in %d days',
$exp
),
$exp
);
// Warning! THIS WILL NOT WORK!
После того, как вы готовы отправить строки переводчикам, сохраните следующее в виде сценария оболочки (например, update.sh) в корневом каталоге вашего приложения:
#!/bin/sh
find . -iname "*.php" | xargs xgettext --add-comments=NOTE --keyword=__:1,2 --keyword=__ --from-code=UTF-8 -o i18n.pot
find . -name '*.po' | xargs -I{} msgmerge -U {} i18n.pot
Чтобы выполнить его, просто выполните:
cd /path/to/script && sh update.sh
Это рекурсивно отсканирует все файлы PHP в этом каталоге и создаст файл .pot
(я назвал его i18n.pot
, но не стесняйтесь называть его как угодновам нравится) и обновите все существующие файлы .po
, которые он найдет, новыми строками.
Затем нам нужно создать каталоги, в которых будут храниться все файлы локалей, по одному для каждой локали.Они должны быть в формате ./locale/{locale}/LC_MESSAGES
.Например:
cd /path/to/your/project
mkdir -p ./locale/en_US.UTF-8/LC_MESSAGES
mkdir -p ./locale/es_MX.UTF-8/LC_MESSAGES
# ...etc.
Вам необходимо выбрать текстовый домен для использования.Это может быть что угодно, но сценарий будет искать файл с именем {yourTextDomain}.mo
в папке LC_MESSAGES для этого языка.Поместите в ваш скрипт PHP следующее:
define('TEXT_DOMAIN', 'yourdomain');
bindtextdomain(TEXT_DOMAIN, __DIR__.'/locale');
textdomain(TEXT_DOMAIN);
bind_textdomain_codeset(TEXT_DOMAIN, 'UTF-8');
Затем, чтобы фактически переключиться на другую локаль, выполните:
$lang = 'es_MX.UTF-8'; // Change this to the language you want to use
if (setlocale(LC_ALL, $lang) === false) {
throw new Exception("Server error: The $lang locale is not installed");
}
putenv('LC_ALL='.$lang));
Первоначально вы отправляете файл .pot
, сгенерированный приведенным выше скриптомпереводчикам.Затем они открывают Poedit и нажимают File > New from POT/PO file
.Когда они сохраняют его, они должны сохранить его как {yourTextDomain}.po
.{yourTextDomain}
должен быть точно таким же, как текстовый домен, который есть в вашем PHP-скрипте.Когда они сохранят его, он автоматически создаст как файл .po
, так и файл .mo
.Оба они должны быть сохранены в каталоге LC_MESSAGES
этого языка после завершения перевода.
Теперь, когда вы обновляете строки в своем PHP-файле, просто повторите сценарий оболочки и отправьте только что обновленный .po
файлов для переводчиков.Затем они переводят строки, и оба файла .po
и .mo
необходимо повторно загрузить.
Вот и все.Это может показаться немного сложным в настройке, но как только вы его настроите и запустите, это действительно легко.