如何调试gettext无法在PHP中工作?

时间:2014-04-19 13:45:48

标签: php localization internationalization gettext setlocale

我想在php 5.5中使用php gettext扩展(在win2008服务器上,使用IIS7)。我这样做:

<?php

$locale = "es";
if (isSet($_GET["locale"])) $locale = $_GET["locale"];
putenv("LC_ALL=$locale");
setlocale(LC_ALL, $locale);
bindtextdomain("messages", "./locale");
textdomain("messages");

echo gettext("Hello world");

?>

使用此文件夹结构:

locale/es/LC_MESSAGES/messages.mo

但它总是只返回Hello世界而不是正确的翻译现在(基于我缺乏西班牙语技能)是在messages.po文件中:

msgid ""
msgstr ""
"Project-Id-Version: TestXlations\n"
"POT-Creation-Date: 2014-04-19 08:15-0500\n"
"PO-Revision-Date: 2014-04-19 09:18-0500\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.3\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SearchPath-0: c:/dev\n"

msgid "Hello world"
msgstr "Hola World"

这从cmd行和IIS失败。所以我看到gettext调用等并执行它但它没有读取翻译文件。我该如何进一步调试?即使删除翻译文件,我也会得到相同的行为。

7 个答案:

答案 0 :(得分:17)

您应该检查返回的值并知道哪个函数失败了。它不是特定的,但对任何PHP脚本或任何编程语言调试都很有用。

<?php
$locale = 'es';
if (isSet($_GET["locale"])) $locale = $_GET["locale"];

$domain = 'messages';

$results = putenv("LC_ALL=$locale");
if (!$results) {
    exit ('putenv failed');
}

// http://msdn.microsoft.com/en-us/library/39cwe7zf%28v=vs.100%29.aspx
$results = setlocale(LC_ALL, $locale, 'spanish');
if (!$results) {
    exit ('setlocale failed: locale function is not available on this platform, or the given local does not exist in this environment');
}

$results = bindtextdomain($domain, "./locales");
echo 'new text domain is set: ' . $results. "\n";

$results = textdomain($domain);
echo 'current message domain is set: ' . $results. "\n";

$results = gettext("Hello world");
if ($results === "Hello world") {
    echo "original English was returned. Something wrong\n";
}
echo $results . "\n";

答案 1 :(得分:11)

你找到&#34; es&#34;在&#39; locale -a&#39;的输出中?如果没有,则需要运行以下命令。

 sudo locale-gen es

答案 2 :(得分:10)

在Linux上遇到同样的问题,我得出了这样的结论: 即使您为项目提供了自己的* .mo文件,操作系统也必须知道区域设置本身

在系统级别安装请求的区域设置为我解决了问题。

参见:locale-gen

实际上调试 gettext可能没什么帮助,但至少你可以尝试一下。

答案 3 :(得分:5)

由于不知道在操作系统上使用哪种语言包,谢天谢地setlocale()函数允许使用数组。根据{{​​3}}:

  

&#34;如果locale是一个数组或后跟其他参数,则尝试将每个数组元素或参数设置为新的语言环境,直到成功为止。如果在不同系统上以不同名称知道语言环境或为可能不可用的语言环境提供回退,这非常有用#34;

有了这个,你可以通过检查后面的设置来挖掘操作系统回落的区域设置:

$locales = array( "fr_FR", "fr_FR.UTF-8", "fr_FR.utf8", "fr-FR" );

if (( $setTo = setlocale( LC_ALL, $locales )) === FALSE )
{
    echo "Unable to set a locale that the OS recognises.";
    return false;
}
else
{
    echo "Set LC_ALL to " . $setTo; //echos fr_FR.utf8
    return true;
}

$setTo将提供成功的$locales值。在查找要为.po编写的区域设置时,这可能会有所帮助。

根据我的评论中的说明,我遇到的问题是,我没有在每个页面请求的每个脚本的顶部执行此setlocale(),因为您需要保留用户&#39;按会话或数据库值选择语言。一旦它被设定,我天真地相信,它永远被设定!

答案 4 :(得分:1)

我知道这个问题很老,但对于来自 Google 的任何人,我想分享我自己的经验。

在将 Debian 从 Stretch 升级到 Buster 后,我也遇到了这个问题,而且我花了很长时间试图调试这个问题。我不完全确定原因,但就我而言,我设法通过在代码中添加以下行来解决该问题,

putenv('LANGUAGE=');

令我惊讶的是,在从命令行运行的 PHP 脚本中使用 gettext 实际上按预期工作,与由 Apache 运行时相比。从终端运行命令 locales 后,我注意到 LANGUAGE 环境变量实际上设置为空字符串。当由 Apache 运行时,无论出于何种原因,它都设置为 en_US:en,正如我通过使用 getenv 函数发现的那样。

我不知道为什么将 LANGUAGE 环境变量设置为空字符串实际上为我解决了这个问题,但确实如此。希望有人会觉得这很有用。

答案 5 :(得分:0)

这是一个有点老问题,但这里的答案是希望对某人有用。

尝试将LC_ALL功能中的LANG更改为putenv

$results = putenv("LC_ALL=$locale");

到此:

$results = putenv("LANG=$locale");

在mac中, LC_ALL 出现问题,可能在这里也一样。

在其他情况下也请检查此答案 https://stackoverflow.com/a/3535866/6628843

希望它有所帮助!

答案 6 :(得分:0)

尝试设置env vars LC_LANGLC_LANGUAGE,而不仅仅是LC_ALL

putenv("LC_ALL=$locale");
putenv("LC_LANG=$locale");
putenv("LC_LANGUAGE=$locale");