Почему Yii игнорирует мой файл.po?

Поскольку Yii не может создавать PO-файлы без специального расширения, я просто создал.po-файл с помощью Poedit. Я хочу использовать 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,

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 ответа

Решение

Прежде всего, 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;
}

Как вы можете видеть - может быть, не на первый взгляд, но позже наверняка, шаблон делает "msgctxt" необязательным. Но проблема в том, что в цикле for он проверяет, совпадает ли именно этот 'msgctxt' из файла.po с категорией, которую вы передаете t(),

Поэтому, если у вас нет для каждой записи.po "msgctxt", это не сработает. Кроме того, вы можете видеть, что в этом классе также есть функция сохранения - но у нее нет шансов использовать ее (или я не нашел способа использовать ее). Потому что, если вы используете yiic messages он всегда генерирует php-файл, независимо от того, настроены ли вы CGettextMessage в настройках вашей консоли или нет.

Решение:

Поскольку я не хочу исправлять эту загрузку кода, я подумал о том, чтобы просто использовать gettext в php. Побочным эффектом является то, что я могу разобрать его намного проще с помощью таких инструментов, как Poedit.

И что самое приятное - уже есть расширение Yii, которое вы можете использовать очень просто - Yii-gettext!

Так как я действительно новичок в gettext(), я немного запутался, где разместить и как назвать мои файлы перевода. Но на ТАК я нашел этот вопрос / ответ, где они объясняют это очень хорошо. (Помимо того, что мне пришлось редактировать и этот пост. Потому что автор использовал 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

Вам не хватает контекста "msgctxt" в вашем po-файле.

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

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

Как @chris--- сказал, что вы скучаете по msgctxt. Скажите поедить сгенерировать msgctxt от Yii:t()category param, установив соответствующий заголовок в вашем.po файле:

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

Это означает, что первый параметр будет использоваться как context в gettext, а второй - в виде строки сообщения.

Также см. Мою статью вики.

Другие вопросы по тегам