Проблемы 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 или Зенд Переводят Адаптер) надежно через различные операционные системы (возможно с пользовательскими локалями как 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

Это продолжило бы работать *, отклоняют и plataforms Windows без проблем?

18
задан Alix Axel 17 August 2010 в 15:06
поделиться

2 ответа

Gettext не слишком удобен для веб-приложений.

  • Например, он сам по себе не учитывает / не использует предпочтения стиля Accept-Language.
  • Обычно возникают некоторые проблемы с кешированием на общих веб-хостах (mod_php SAPI).

Так что мне иногда хочется, чтобы PHP-модуль не существовал, а удобное сокращение имени функции _ () было доступно для пользовательских реализаций.
(У меня был собственный gettext.php , который работал более надежно.)

Ваши варианты:

  1. В любом случае, согласно нескольким сообщениям об ошибках, порт gettext для Windows имел некоторые недостатки с 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.

  2. В качестве альтернативы можно обойти gettext. Идея вашего домена близка, но я бы просто использовал предварительно определенный подкаталог ./locale/ для языков:

     ./ lang / en / locale / C / LC_MESSAGES / domain.mo
    

    Затем просто вызовите bindtextdomain ("default", "./lang/{$APP_LANG}/locale"), не давая gettext возможности для интерпретации.Он всегда будет искать / C /, но уже введен правильный каталог локали. Но все равно попытайтесь иметь там символическую ссылку из $ LANG в / C /.

  3. Укусите гну. Откажитесь от gettext. «PhpWiki» имеет собственный сценарий преобразования awk. Он преобразует файлы .po в сценарии массива .php (да, очень старая школа), и вместо этого просто использует функцию __ (). Закрывать. И надежнее.

18
ответ дан 30 November 2019 в 08:37
поделиться

Этот код не будет работать идеально в каждой системе, потому что каждый репозиторий локали системы + версия PHP отличается, среди прочего.

Если вам нужна согласованность, вам нужно использовать что-то вроде Zend_Translate, что если вы установите Zend в каждой системе (одну и ту же его версию), все они будут согласованы друг с другом, потому что они используют одни и те же данные локализации, имена локалей. и кодовая база.

В setlocale есть множество ошибок, это просто ненадежно. См. Комментарии @ http://php.net/manual/en/function.setlocale.php

6
ответ дан 30 November 2019 в 08:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: