为什么Yii会忽略我的.po文件?

时间:2014-04-29 07:40:54

标签: php yii gettext po

由于Yii无法在没有特殊扩展名的情况下创建PO文件,因此我只使用Poedit创建了一个.po文件。我想使用CGettextMessageSource并配置main.php中的所有内容。

但Yii只是忽略了main.php和我的.po文件中的设置。

main.php

'language' => 'de_DE',
[...]    
'components' => array(
    'messages' => array(
        'class' => 'CGettextMessageSource',
        'useMoFile' => false,
        'catalog' => 'messages',
        'basePath' => 'protected/messages'
    ),
),

我的档案

protected => messages => de_DE => messages.mo, messages.po

我的.po文件内容

msgid ""
msgstr ""
"Project-Id-Version: myTest\n"
"POT-Creation-Date: 2014-04-28 17:18+0100\n"
"PO-Revision-Date: 2014-04-29 09:16+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.4\n"
"X-Poedit-Basepath: .\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: t\n"
"X-Poedit-SearchPath-0: /..."
"trunk/fe/htdocs/protected\n"

#: /htdocs/protected/views/site/index.php:9
msgid "_TEST_"
msgstr "Congratulations! You have successfully created your Yii application."

由于严格的标准我无法扩展t - 函数,因此我在yii.php中编写了一个包装器,我将其复制到protected并将其包含在main.php中。< / p>

class Yii extends YiiBase
{
    public static function _($message, $category, $params = array())
    {
        return parent::t($category, $message, $params);
    }
}

这是我的index.php,我有一个应该转换的字符串:

<?php echo Yii::_('_TEST_', 'messages');?>

3 个答案:

答案 0 :(得分:2)

您的po文件中缺少上下文“msgctxt”。

[...]
msgctxt "messages"
msgid "_TEST_"
msgstr "Congratulations! You have successfully created your Yii application."

msgctxt "messages"
msgid "_TEST2_"
msgstr "Another translated text."
[...]

答案 1 :(得分:2)

首先 Yii没有忽略我的.po文件

问题:

Yii只是被窃听。

如果您想使用.po文件进行翻译,则使用类CGettextPoFile

public function load($file,$context)
{
    $pattern='/(msgctxt\s+"(.*?(?<!\\\\))")?\s+'
        .'msgid\s+((?:".*(?<!\\\\)"\s*)+)\s+'
        .'msgstr\s+((?:".*(?<!\\\\)"\s*)+)/';
    $matches=array();
    $n=preg_match_all($pattern,file_get_contents($file),$matches);

    $messages=array();
    for($i=0; $i<$n; $i++)
    {
        if($matches[2][$i]===$context)
        {
            $id=$this->decode($matches[3][$i]);
            $message=$this->decode($matches[4][$i]);
            $messages[$id]=$message;
        }
    }
    return $messages;
}

就像你可以看到的那样 - 也许不是第一次观看,但是后来肯定,这种模式会使得#g; msgctxt&#39;可选的。但问题是,在for循环中,它会检查这个&#39; msgctxt&#39;来自.po文件与您传递给t()的类别匹配。

因此,如果您没有为每个.po条目提供一个&#39; msgctxt&#39;它不会起作用。此外,您可以看到此类也具有保存功能 - 但没有机会使用它(或者我没有找到任何使用方法)。因为如果你使用yiic messages它总是生成一个php文件,无论你是否在控制台设置中设置CGettextMessage

解决方案:

由于我不想修复这段代码,我想只需使用php的gettext。 Sideeffect是,我可以使用Poedit等工具轻松解析它。

最重要的是 - 已经有一个非常容易使用的Yii扩展程序 - Yii-gettext

因为我是gettext()的新手,所以我有点困惑在哪里放置以及如何命名我的翻译文件。但是,我已经找到了question/answer,他们在那里解释得非常好。 (除此之外,我还必须编辑这篇文章。因为作者使用了domain消息,这有点令人困惑,因为gettext文件夹的硬编码路径部分是LC_MESSAGES。所以我将domain条消息重命名为mycatalog。)

<强>记住:

bindtextdomain(<your namespace for your .mo/.po file>, <your directory>);

//put your files into: 
//<your directory>/<language i.e. en_EN>/LC_MESSAGES/<your namespace/domain>.mo/.po
//i.e.:
//  /htdocs/locale/en_EN/LC_MESSAGES/mycatalog.mo
//  /htdocs/locale/en_EN/LC_MESSAGES/mycatalog.po

答案 2 :(得分:0)

@chris ---说你想念msgctxt。通过在.po文件中设置适当的标题,告诉poedit从msgctxt Yii:t() param生成category

"X-Poedit-KeywordsList: t:1c,2\n"

这意味着,第一个参数将在gettext中用作context,第二个参数用作消息字符串。

另见wiki article