Проблемы с PHP/Gettext
Я помню, как несколько месяцев назад запускал некоторые тесты с gettext, и следующий код работал отлично:
putenv('LANG=l33t');
putenv('LANGUAGE=l33t');
putenv('LC_MESSAGES=l33t');
if (defined('LC_MESSAGES')) // available if PHP was compiled with libintl
{
setlocale(LC_MESSAGES, 'l33t');
}
else
{
setlocale(LC_ALL, 'l33t');
}
bindtextdomain('default', './locale'); // ./locale/l33t/LC_MESSAGES/default.mo
bind_textdomain_codeset('default', 'UTF-8');
textdomain('default');
echo _('Hello World!'); // h3110 w0r1d!
это сработало отлично (под Windows XP и CentOS, если я правильно помню), что было хорошо, потому что я мог использовать произвольные "языки", не беспокоясь, если они были установлены в системе или нет. Однако это, похоже, больше не работает, интересно, почему...
Red Hat + PHP 5.2.11:
Я возможность переключения назад и вперед из разных мест, и переводы показывают correclty до тех пор, как setlocale()
вызов не возвращает false (если локаль доступна/установлена в системе).
это не идеально (было бы здорово, если бы я мог просто указать gettext на любой произвольный каталог перевода без необходимости проверять наличие локали), но это приемлемо. Позже я проведу еще несколько тестов.
Windows 7 + PHP 5.3.1 (XAMPP):
setlocale()
всегда возвращает false (даже при использовании LC_ALL
вместо LC_MESSAGES
), если я не использую некоторые допустимые языковые стандарты Windows, такие как eng
, deu
или ptg
- в этом случае язык вроде бы правильно, но перевод еще не пришел. Я не могу проверить прямо сейчас, потому что я сотни открытых вкладок, но я думаю, что самый первый вызов этого скрипта дает правильный перевод (перезапуск Apache не хватит).
Я не уверен, что это связано с ошибка PHP #49349. Я проверю это через пару часов.
есть ли способ использовать расширение gettext (не чистые реализации PHP, такие как php-gettext или Zend Перевести Адаптер) достоверно в разных операционных системах (возможно, с таможни локалей как l33t
)?
кроме того, абсолютно необходимо использовать setlocale(LC_ALL, ...)
? Я бы предпочел оставить TIME
, NUMERIC
и MONETARY
(специально) настройки локали нетронуты (по умолчанию POSIX
locale).
у меня есть идея... Можно ли было бы позвонить setlocale()
С очень распространенным языком (например,C
, POSIX
или en_US
) и указать язык через домен? Что-то вроде этого:--20-->
/lang/C/LC_MESSAGES/domain.pt.mo
/lang/C/LC_MESSAGES/domain.de.mo
/lang/C/LC_MESSAGES/domain.en.mo
/lang/C/LC_MESSAGES/domain2.pt.mo
/lang/C/LC_MESSAGES/domain2.de.mo
/lang/C/LC_MESSAGES/domain2.en.mo
будет ли это работать на * nix и Windows plataforms без проблем?
2 ответов
Gettext не слишком практичен для webapps.
- как, например, он не чтит/использует настройки стиля Accept-Language сам по себе.
- обычно возникают некоторые проблемы с кэшированием на общих веб-хостах (mod_php SAPI).
поэтому я иногда хочу, чтобы PHP-модуль не существовал, и удобный _()
ярлык имени функции был доступен для реализаций userland.
(Была своя gettext версии.в PHP, который работал более надежный.)
ваши возможности:
-
Anway, согласно нескольким сообщениям об ошибках, порт Windows gettext имел некоторые недостатки с UTF-8. Возможно, ваша версия снова затронута. Так что попробуйте
bind_textdomain_codeset('default', 'ISO-8859-1');
для начала. Кроме того, он, похоже, предпочитает переменные среды в Windows IIRC, поэтомуputenv("LC_ALL", "fr_FR");
может работать лучше, чемsetlocale()
. Особенно работоспособен, если вы dl (gettext.dll) позже.также дайте ему шанс с включением кодировки прямо там
LANG=en_GB.ISO-8859-1
. (Поскольку ваш исходный текст все равно английский, забота о кодировке здесь не очень релавантна; но, вероятно, общий случай, когда gettext путешествует сам по себе.) О, и иногда это UTF8 не UTF-8; также попробуйте ASCII. -
альтернативно обойти gettext. Ваша идея домена близка, но я бы просто использовал предварительно определенный ./ locale / subdir для языков:
./lang/en/locale/C/LC_MESSAGES/domain.mo
тогда просто вызовите
bindtextdomain("default", "./lang/{$APP_LANG}/locale")
не давая gettext пространство для интерпретации много. Он всегда будет искать /C/, но правильный каталог локали уже введен. Но все равно попробуйте получить символическую ссылку из $LANG в /C/ in. укус в gnu. Откажитесь от gettext. "PhpWiki" имел пользовательский сценарий преобразования awk. Она преображается .языковые файлы .PHP array скрипты (да очень oldschool), и просто использует функцию _ _ () вместо этого. Закрывать. И надежнее.
этот код не будет работать идеально в каждой системе, потому что каждый репозиторий языковых стандартов системы + версия php отличается, среди прочего.
Если вы хотите согласованности, вам нужно использовать что-то вроде Zend_Translate, который, если вы установите Zend на каждую систему ( ту же версию), все они будут согласованы друг с другом, потому что они используют те же данные локализации, имена локалей и кодовую базу.
есть множество ошибок с setlocale
, Это просто не надежный. См. комментарии @ http://php.net/manual/en/function.setlocale.php