GettextMessageSource.php 4.47 KB
Newer Older
resurtm committed
1 2 3 4 5 6 7 8 9 10 11
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\i18n;

use Yii;

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/**
 * GettextMessageSource represents a message source that is based on GNU Gettext.
 *
 * Each GettextMessageSource instance represents the message tranlations
 * for a single domain. And each message category represents a message context
 * in Gettext. Translated messages are stored as either a MO or PO file,
 * depending on the [[useMoFile]] property value.
 *
 * All translations are saved under the [[basePath]] directory.
 *
 * Translations in one language are kept as MO or PO files under an individual
 * subdirectory whose name is the language ID. The file name is specified via
 * [[catalog]] property, which defaults to 'messages'.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
resurtm committed
29 30
class GettextMessageSource extends MessageSource
{
31 32
    const MO_FILE_EXT = '.mo';
    const PO_FILE_EXT = '.po';
resurtm committed
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
    /**
     * @var string
     */
    public $basePath = '@app/messages';
    /**
     * @var string
     */
    public $catalog = 'messages';
    /**
     * @var boolean
     */
    public $useMoFile = true;
    /**
     * @var boolean
     */
    public $useBigEndian = false;
resurtm committed
50

51 52 53 54 55 56 57 58 59 60 61 62 63 64
    /**
     * Loads the message translation for the specified language and category.
     * If translation for specific locale code such as `en-US` isn't found it
     * tries more generic `en`.
     *
     * @param  string $category the message category
     * @param  string $language the target language
     * @return array  the loaded messages. The keys are original messages, and the values
     *                         are translated messages.
     */
    protected function loadMessages($category, $language)
    {
        $messageFile = $this->getMessageFilePath($language);
        $messages = $this->loadMessagesFromFile($messageFile, $category);
Alexander Makarov committed
65

66 67 68 69
        $fallbackLanguage = substr($language, 0, 2);
        if ($fallbackLanguage != $language) {
            $fallbackMessageFile = $this->getMessageFilePath($fallbackLanguage);
            $fallbackMessages = $this->loadMessagesFromFile($fallbackMessageFile, $category);
Alexander Makarov committed
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
            if ($messages === null && $fallbackMessages === null && $fallbackLanguage != $this->sourceLanguage) {
                Yii::error("The message file for category '$category' does not exist: $messageFile Fallback file does not exist as well: $fallbackMessageFile", __METHOD__);
            } elseif (empty($messages)) {
                return $fallbackMessages;
            } elseif (!empty($fallbackMessages)) {
                foreach ($fallbackMessages as $key => $value) {
                    if (!empty($value) && empty($messages[$key])) {
                        $messages[$key] = $fallbackMessages[$key];
                    }
                }
            }
        } else {
            if ($messages === null) {
                Yii::error("The message file for category '$category' does not exist: $messageFile", __METHOD__);
            }
        }
Alexander Makarov committed
87

88 89
        return (array) $messages;
    }
resurtm committed
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    /**
     * Returns message file path for the specified language and category.
     *
     * @param  string $language the target language
     * @return string path to message file
     */
    protected function getMessageFilePath($language)
    {
        $messageFile = Yii::getAlias($this->basePath) . '/' . $language . '/' . $this->catalog;
        if ($this->useMoFile) {
            $messageFile .= static::MO_FILE_EXT;
        } else {
            $messageFile .= static::PO_FILE_EXT;
        }

        return $messageFile;
    }

    /**
     * Loads the message translation for the specified language and category or returns null if file doesn't exist.
     *
     * @param  string     $messageFile path to message file
     * @param  string     $category    the message category
     * @return array|null array of messages or null if file not found
     */
    protected function loadMessagesFromFile($messageFile, $category)
    {
        if (is_file($messageFile)) {
            if ($this->useMoFile) {
                $gettextFile = new GettextMoFile(['useBigEndian' => $this->useBigEndian]);
            } else {
                $gettextFile = new GettextPoFile();
            }
            $messages = $gettextFile->load($messageFile, $category);
            if (!is_array($messages)) {
                $messages = [];
            }

            return $messages;
        } else {
            return null;
        }
    }
resurtm committed
134
}