Я помню, как несколько месяцев назад тестировал несколько тестов с помощью 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, если я правильно помню), что было хорошо, потому что я мог использовать произвольные «локали», не беспокоясь о том, были ли они установлены в системе или нет. Однако, похоже, это больше не работает, мне интересно, почему …
Я могу переключаться между различными локалями, и переводы отображают соответствие, пока вызов setlocale()
не возвращает false (если локаль доступна / установлена в системе).
Это не идеально (было бы здорово, если бы я мог просто указать gettext в любой произвольный каталог переводов без проверки на наличие локали), но это приемлемо. В дальнейшем я проведу еще несколько тестов.
setlocale()
всегда возвращает false (даже при использовании LC_ALL
вместо LC_MESSAGES
), если я не использую какой-либо допустимый локаль Windows, такой как eng
, deu
или ptg
– в этом случае локаль кажется правильно установленным, но переводы все еще не отображаются , Я не могу проверить прямо сейчас, потому что у меня открыто несколько вкладок, но я думаю, что самый первый вызов этого скрипта дает правильный перевод (перезапуск Apache не будет делать трюк).
Я не уверен, связано ли это с ошибкой PHP # 49349 . Я проверю это на пару часов.
Есть ли способ использовать расширение gettext (а не чистые PHP-реализации, такие как php-gettext или Zend Translate Adapter ) надежно в разных операционных системах (возможно, с пользовательскими локалями, такими как l33t
)?
Кроме того, абсолютно необходимо использовать setlocale(LC_ALL, ...)
? Я бы предпочел оставить настройки TIME
, NUMERIC
и MONETARY
(специально) неаудированными (по умолчанию для языкового стандарта POSIX
).
У меня была идея … Можно ли вызвать setlocale()
с очень распространенной локалью (например, C
, POSIX
или en_US
) и указать язык через домен? Что-то вроде этого:
/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 платами без проблем?
Gettext не слишком практичен для webapps.
Поэтому я иногда предпочитаю, чтобы PHP-модуль не существовал, а удобная функция имени функции _()
была доступна для пользовательских реализаций.
(Имел мой собственный gettext.php , который работал более надежно).
Ваши варианты:
Anway, согласно нескольким сообщениям об ошибках, порт Windows gettext имел некоторые недостатки с UTF-8. Возможно, ваша версия снова затронута. Поэтому попробуйте bind_textdomain_codeset('default', 'ISO-8859-1');
для начинающих. Кроме того, он предпочитает переменные среды в Windows IIRC, поэтому putenv("LC_ALL", "fr_FR");
может работать лучше, чем setlocale()
. Особенно эффективен, если вы позже (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 /.
Укусить в гну. Откажитесь от gettext. «PhpWiki» имел специальный скрипт преобразования awk. Он преобразует файлы .po в скрипты массива .php (да, очень oldschool), и вместо этого использует вместо этого функцию __ (). Закрыть. И более надежный.
Этот код не будет работать отлично в каждой системе, потому что каждый репозиторий языковых систем + php-версия отличается, в частности.
Если вы хотите согласованности, вам нужно использовать что-то вроде Zend_Translate, которое, если вы устанавливаете Zend в каждой системе (одна и та же версия), все они будут соответствовать друг другу, потому что они используют одни и те же данные локализации, имена локалей и кодовые базы.
Есть множество ошибок с setlocale
, это просто ненадежно. См. Комментарии @ http://php.net/manual/en/function.setlocale.php