Использовать PHP Gettext без необходимости устанавливать локали
Я рассматривал варианты интернационализации проекта с открытым исходным кодом:
-
Gettext, которому все, кажется, рекомендуют, по-видимому, требует, чтобы локали были "установлены в вашей системе", которые будут использоваться. Смотрите note в руководстве по PHP, которое точно отражает мою ситуацию. Этот вопрос SO > также спрашивает об одной и той же проблеме. Это не подходит для проекта с открытым исходным кодом, потому что я не могу доверить, что конечные пользователи имеют соответствующие локали, установленные в их системе. Кроме того, очень странно, что вам нужно установить локали только для использования перенесенных строк (IMO).
-
Zend_Translate также рекомендуется иногда использовать gettext, но я не использую структуру Zend, поэтому я не думаю, что это вариант для меня. Некоторые люди говорят, что вы можете разделить его на структуру Zend, но я не знаю, как это сделать. Если кто-нибудь скажет мне, какие файлы мне нужны (я загрузил tarball из рамки Zend), чтобы выбрать, я был бы открыт для использования Zend_Translate.
-
Массивы. Это то, что я делаю сейчас, но это не идеально, потому что:
- Он будет использовать много памяти для определения каждого перевода, когда большинство не будет использоваться текущей страницей.
- У меня возникают проблемы с поиском дублирования ключей в массиве, который уже стал 1000 строк кода, и я пока ничего не добавил...
- Это означает, что не-программисты не могут действительно переводить, тогда как POedit - это стандарт, который все ожидают использовать.
Могу ли я как-то читать файлы .mo
без Gettext или Zend_Translate, или я должен использовать Gettext? Если да, как я могу заставить все локали работать, как в вопросе, который я связал с выше?
EDIT: теперь я готов использовать Zend_Translate. Мне просто нужно выяснить, какие файлы мне нужны (было бы здорово, если бы их можно было объединить в один файл) - мне не нужна вся Zend Framework в моем проекте.
Обновление: мне было интересно увидеть, как большие проекты с открытым исходным кодом обрабатывают i18n:
Таким образом, ни один из этих трех случайных проектов не использует Zend_Translate, а не gettext, насколько я могу судить.
Может быть, неплохо использовать локаль C
, сохранить имя языка в текстовом доменном имени и перейти оттуда.
Так что, насколько я понял,
$lang = 'de'; //debug
setlocale( LC_ALL, 'C' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );
var_dump( file_exists( PATH . "/locale/$lang/C/LC_MESSAGES/default.mo" ) ); //bool(true)
Но я все еще просто получаю английскую строку, хотя я использовал poedit, msgfmt и т.д. для создания соответствующих файлов. Я также попытался перезапустить Apache.
Ответы
Ответ 1
Вот решение:
$lang = 'de'; //debug
setlocale( LC_ALL, 'C.UTF-8' );
bindtextdomain( 'default', PATH . "/locale/$lang" );
bind_textdomain_codeset( 'default', 'UTF-8' );
textdomain( 'default' );
Единственная разница между тем, что я привел в нижней части моего ответа, заключается в том, что он использует C.UTF-8
не только C
.
Я буду больше тестировать это, и если он работает кросс-платформенным и обновит этот ответ, если я узнаю что-нибудь еще.
Ответ 2
Попробуйте gettext-php. Это переполнение для gettext, написанное на PHP. Первоначально это было сделано для WordPress, поскольку WP необходимо запускать на общих хостах, которые не всегда настроены для каждой локали. Мне кажется, это тоже ваша проблема.
У этого есть бит производительности, но это не было проблемой для меня вообще.
Ответ 3
Для тех, у кого все еще есть проблемы с этим, вы можете попробовать код ниже, который я получаю отсюда: http://php.net/manual/en/function.gettext.php#58310
Это решило меня на сервере freebsd без дополнительной установки локали (fr_FR и my_MY). Этот код также полезен, когда у вас есть проблемы с кешем gettext.
<?php
function initialize_i18n($locale) {
$locales_root="/app/php/locale"; // change This to where you locale folder at
putenv('LANG='.$locale);
setlocale(LC_ALL,"");
setlocale(LC_MESSAGES,$locale);
setlocale(LC_CTYPE,$locale);
$domains = glob($locales_root.'/'.$locale.'/LC_MESSAGES/*.mo');
$current = basename($domains[0],'.mo');
$timestamp = preg_replace('{messages-}i','',$current);
bindtextdomain($current,$locales_root);
textdomain($current);
}
?>
Ответ 4
Для получения более подробной информации о том, как решить эту проблему, см. Ответы в этой теме: PHP GetText без локали на сервере?