PHP / Gettext问题

时间:2010-08-03 15:34:20

标签: php locale gettext zend-translate setlocale

我记得几个月前用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下,如果我没记错的话),这很好,因为我可以使用任意“locales”,而不必担心它们是否安装在系统上。但是,这似乎不再起作用,我想知道为什么......


Red Hat + PHP 5.2.11:

只要setlocale()调用没有返回false(如果系统上有可用/已安装的语言环境),我就可以在各种语言环境中来回切换并且翻译显示相关内容。 / p>

这并不完美(如果我可以将gettext指向任意翻译目录而不必测试是否存在语言环境,那将会很棒),但这是可以接受的。我稍后会再进行一些测试。

Windows 7 + PHP 5.3.1(XAMPP):

setlocale()始终返回false(即使使用LC_ALL而不是LC_MESSAGES),除非我使用某些有效的Windows区域设置,例如engdeuptg - 在这种情况下,区域设置似乎已正确设置,但翻译仍未显示。我现在无法测试,因为我已经打开了数百个选项卡,但我认为第一次调用该脚本会产生正确的转换(重启Apache将无法解决问题)。

我不确定这是否与PHP Bug #49349有关。我将测试这几个小时。


有没有办法在不同的操作系统中可靠地使用gettext扩展(不是像php-gettextZend Translate Adapter这样的纯PHP实现)(可能使用自定义语言环境,如{ {1}})?

另外,是否绝对有必要使用l33t?我会保持setlocale(LC_ALL, ...)TIMENUMERIC(特别)区域设置保持不变(默认为MONETARY区域设置)。


我有一个想法......是否可以使用非常常见的区域设置(例如POSIXsetlocale()C)来呼叫POSIX并指定语言通过域名?像这样:

en_US

这可以在* nix和Windows plataforms上运行吗?

2 个答案:

答案 0 :(得分:18)

Gettext对于webapps并不太实用。

  • 例如,它本身并不尊重/使用Accept-Language样式首选项。
  • 通常会在共享的webhosts(mod_php SAPI)上引发一些缓存问题。

所以我有时希望PHP模块不存在,方便的_()函数名称快捷方式可用于用户区实现。
(有我自己的gettext.php,它更可靠。)

您的选择:

  1. Anway,根据一些错误报告,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. 咬入gnu。放弃gettext。 “PhpWiki”有一个自定义awk转换脚本。它将.po文件转换为.php数组脚本(是的,非常oldschool),而只是使用__()函数。关。而且更可靠。

答案 1 :(得分:6)

此代码不能在每个系统上完美运行,因为每个系统locale repository + php版本都不同,等等。

如果你想要一致性,你需要使用像Zend_Translate这样的东西,如果你在每个系统上安装Zend(相同版本),它们将彼此一致,因为它们使用相同的本地化数据,区域名称和代码库。

setlocale存在大量漏洞,但这并不可靠。请参阅评论@ http://php.net/manual/en/function.setlocale.php