19

我正在尝试在 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 world 而不是正确的翻译,目前(基于我缺乏西班牙语技能)在 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 调用等并执行它,但它没有读取翻译文件。我该如何进一步调试?即使删除翻译文件,我也会得到相同的行为。

4

7 回答 7

17

您应该检查返回值并知道哪个函数失败了。它不是 i18n 特定的,但对任何 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";
于 2014-04-20T02:24:33.283 回答
13

您是否在 'locale -a' 的输出中找到“es”?如果没有,那么您需要运行以下命令。

 sudo locale-gen es
于 2014-07-22T17:04:06.167 回答
11

在 Linux 上遇到同样的问题,我得出了这样的结论:即使您为项目提供自己的 *.mo 文件,操作系统也必须知道语言环境本身(es)。

在系统级别安装请求的语言环境为我解决了这个问题。

看:locale-gen

它可能对实际调试gettext没有帮助,但至少它是您可以尝试的。

于 2015-12-01T16:26:10.163 回答
6

由于不知道在操作系统上使用哪种语言包,幸运的是该setlocale()函数允许使用数组。根据PHP 文档

“如果语言环境是一个数组或后跟附加参数,则尝试将每个数组元素或参数设置为新的语言环境,直到成功。如果一个语言环境在不同系统上以不同的名称已知,或者为可能的不可用的语言环境”

有了这个,您可以通过检查以下设置来挖掘操作系统正在回退的语言环境:

$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()在每个页面请求的每个脚本的顶部执行此操作,因为您需要通过会话或数据库值保留用户对语言的选择。正如我天真地相信,一旦它被设定,它就永远被设定了!

于 2016-03-15T09:57:02.487 回答
2

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

在将 Debian 从 Stretch 升级到 Buster 后,我也遇到了这个问题,而且我花了很长时间尝试调试它。我不完全确定为什么,但就我而言,我只需在代码中添加以下行就解决了这个问题,

putenv('LANGUAGE=');

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

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

于 2021-01-01T21:09:23.183 回答
1

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

尝试在函数中更改LC_ALL为,从此:LANGputenv

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

对此:

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

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

在其他情况下还要检查这个答案 https://stackoverflow.com/a/3535866/6628843

希望能帮助到你!

于 2017-02-10T19:22:31.220 回答
0

尝试设置环境变量LC_LANGLC_LANGUAGE而不仅仅是LC_ALL

putenv("LC_ALL=$locale");
putenv("LC_LANG=$locale");
putenv("LC_LANGUAGE=$locale");
于 2017-10-24T20:38:37.350 回答