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

namespace yii\i18n;

Qiang Xue committed
10 11
use Yii;

Qiang Xue committed
12 13 14
/**
 * PhpMessageSource represents a message source that stores translated messages in PHP scripts.
 *
Qiang Xue committed
15 16 17 18 19 20 21 22
 * PhpMessageSource uses PHP arrays to keep message translations.
 *
 * - Each PHP script contains one array which stores the message translations in one particular
 *   language and for a single message category;
 * - Each PHP script is saved as a file named as `[[basePath]]/LanguageID/CategoryName.php`;
 * - Within each PHP script, the message translations are returned as an array like the following:
 *
 * ~~~
Alexander Makarov committed
23
 * return [
Qiang Xue committed
24 25
 *     'original message 1' => 'translated message 1',
 *     'original message 2' => 'translated message 2',
Alexander Makarov committed
26
 * ];
Qiang Xue committed
27
 * ~~~
Qiang Xue committed
28
 *
29 30
 * You may use [[fileMap]] to customize the association between category names and the file names.
 *
Qiang Xue committed
31 32 33 34 35
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class PhpMessageSource extends MessageSource
{
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    /**
     * @var string the base path for all translated messages. Defaults to null, meaning
     * the "messages" subdirectory of the application directory (e.g. "protected/messages").
     */
    public $basePath = '@app/messages';
    /**
     * @var array mapping between message categories and the corresponding message file paths.
     * The file paths are relative to [[basePath]]. For example,
     *
     * ~~~
     * [
     *     'core' => 'core.php',
     *     'ext' => 'extensions.php',
     * ]
     * ~~~
     */
    public $fileMap;
Qiang Xue committed
53

54 55 56 57 58
    /**
     * 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`.
     *
59 60 61 62
     * @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.
63 64 65 66 67
     */
    protected function loadMessages($category, $language)
    {
        $messageFile = $this->getMessageFilePath($category, $language);
        $messages = $this->loadMessagesFromFile($messageFile);
Alexander Makarov committed
68

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

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
            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
90

91 92
        return (array) $messages;
    }
Alexander Makarov committed
93

94 95 96
    /**
     * Returns message file path for the specified language and category.
     *
97 98
     * @param string $category the message category
     * @param string $language the target language
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
     * @return string path to message file
     */
    protected function getMessageFilePath($category, $language)
    {
        $messageFile = Yii::getAlias($this->basePath) . "/$language/";
        if (isset($this->fileMap[$category])) {
            $messageFile .= $this->fileMap[$category];
        } else {
            $messageFile .= str_replace('\\', '/', $category) . '.php';
        }

        return $messageFile;
    }

    /**
     * Loads the message translation for the specified language and category or returns null if file doesn't exist.
     *
     * @param $messageFile string path to message file
     * @return array|null array of messages or null if file not found
     */
    protected function loadMessagesFromFile($messageFile)
    {
        if (is_file($messageFile)) {
            $messages = include($messageFile);
            if (!is_array($messages)) {
                $messages = [];
            }

            return $messages;
        } else {
            return null;
        }
    }
Zander Baldwin committed
132
}