Я помню, как несколько месяцев назад тестировал несколько тестов с помощью 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