1 | <?php |
||
27 | class I18N extends Component |
||
28 | { |
||
29 | /** |
||
30 | * @var array list of [[MessageSource]] configurations or objects. The array keys are message |
||
31 | * category patterns, and the array values are the corresponding [[MessageSource]] objects or the configurations |
||
32 | * for creating the [[MessageSource]] objects. |
||
33 | * |
||
34 | * The message category patterns can contain the wildcard '*' at the end to match multiple categories with the same prefix. |
||
35 | * For example, 'app/*' matches both 'app/cat1' and 'app/cat2'. |
||
36 | * |
||
37 | * The '*' category pattern will match all categories that do not match any other category patterns. |
||
38 | * |
||
39 | * This property may be modified on the fly by extensions who want to have their own message sources |
||
40 | * registered under their own namespaces. |
||
41 | * |
||
42 | * The category "yii" and "app" are always defined. The former refers to the messages used in the Yii core |
||
43 | * framework code, while the latter refers to the default message category for custom application code. |
||
44 | * By default, both of these categories use [[PhpMessageSource]] and the corresponding message files are |
||
45 | * stored under "@yii/messages" and "@app/messages", respectively. |
||
46 | * |
||
47 | * You may override the configuration of both categories. |
||
48 | */ |
||
49 | public $translations; |
||
50 | |||
51 | |||
52 | /** |
||
53 | * Initializes the component by configuring the default message categories. |
||
54 | */ |
||
55 | 554 | public function init() |
|
56 | { |
||
57 | 554 | parent::init(); |
|
58 | 554 | if (!isset($this->translations['yii']) && !isset($this->translations['yii*'])) { |
|
59 | 554 | $this->translations['yii'] = [ |
|
60 | 554 | 'class' => 'yii\i18n\PhpMessageSource', |
|
61 | 554 | 'sourceLanguage' => 'en-US', |
|
62 | 554 | 'basePath' => '@yii/messages', |
|
63 | ]; |
||
64 | 554 | } |
|
65 | 554 | if (!isset($this->translations['app']) && !isset($this->translations['app*'])) { |
|
66 | 554 | $this->translations['app'] = [ |
|
67 | 554 | 'class' => 'yii\i18n\PhpMessageSource', |
|
68 | 554 | 'sourceLanguage' => Yii::$app->sourceLanguage, |
|
69 | 554 | 'basePath' => '@app/messages', |
|
70 | ]; |
||
71 | 554 | } |
|
72 | 554 | } |
|
73 | |||
74 | /** |
||
75 | * Translates a message to the specified language. |
||
76 | * |
||
77 | * After translation the message will be formatted using [[MessageFormatter]] if it contains |
||
78 | * ICU message format and `$params` are not empty. |
||
79 | * |
||
80 | * @param string $category the message category. |
||
81 | * @param string $message the message to be translated. |
||
82 | * @param array $params the parameters that will be used to replace the corresponding placeholders in the message. |
||
83 | * @param string $language the language code (e.g. `en-US`, `en`). |
||
84 | * @return string the translated and formatted message. |
||
85 | */ |
||
86 | 550 | public function translate($category, $message, $params, $language) |
|
87 | { |
||
88 | 550 | $messageSource = $this->getMessageSource($category); |
|
89 | 550 | $translation = $messageSource->translate($category, $message, $language); |
|
90 | 550 | if ($translation === false) { |
|
91 | 408 | return $this->format($message, $params, $messageSource->sourceLanguage); |
|
92 | } else { |
||
93 | 161 | return $this->format($translation, $params, $language); |
|
|
|||
94 | } |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Formats a message using [[MessageFormatter]]. |
||
99 | * |
||
100 | * @param string $message the message to be formatted. |
||
101 | * @param array $params the parameters that will be used to replace the corresponding placeholders in the message. |
||
102 | * @param string $language the language code (e.g. `en-US`, `en`). |
||
103 | * @return string the formatted message. |
||
104 | */ |
||
105 | 554 | public function format($message, $params, $language) |
|
106 | { |
||
107 | 554 | $params = (array) $params; |
|
108 | 554 | if ($params === []) { |
|
109 | 539 | return $message; |
|
110 | } |
||
111 | |||
112 | 251 | if (preg_match('~{\s*[\d\w]+\s*,~u', $message)) { |
|
113 | 116 | $formatter = $this->getMessageFormatter(); |
|
114 | 116 | $result = $formatter->format($message, $params, $language); |
|
115 | 116 | if ($result === false) { |
|
116 | $errorMessage = $formatter->getErrorMessage(); |
||
117 | Yii::warning("Formatting message for language '$language' failed with error: $errorMessage. The message being formatted was: $message.", __METHOD__); |
||
118 | |||
119 | return $message; |
||
120 | } else { |
||
121 | 116 | return $result; |
|
122 | } |
||
123 | } |
||
124 | |||
125 | 141 | $p = []; |
|
126 | 141 | foreach ($params as $name => $value) { |
|
127 | 141 | $p['{' . $name . '}'] = $value; |
|
128 | 141 | } |
|
129 | |||
130 | 141 | return strtr($message, $p); |
|
131 | } |
||
132 | |||
133 | /** |
||
134 | * @var string|array|MessageFormatter |
||
135 | */ |
||
136 | private $_messageFormatter; |
||
137 | |||
138 | /** |
||
139 | * Returns the message formatter instance. |
||
140 | * @return MessageFormatter the message formatter to be used to format message via ICU message format. |
||
141 | */ |
||
142 | 116 | public function getMessageFormatter() |
|
143 | { |
||
144 | 116 | if ($this->_messageFormatter === null) { |
|
145 | 116 | $this->_messageFormatter = new MessageFormatter(); |
|
146 | 116 | } elseif (is_array($this->_messageFormatter) || is_string($this->_messageFormatter)) { |
|
147 | $this->_messageFormatter = Yii::createObject($this->_messageFormatter); |
||
148 | } |
||
149 | |||
150 | 116 | return $this->_messageFormatter; |
|
151 | } |
||
152 | |||
153 | /** |
||
154 | * @param string|array|MessageFormatter $value the message formatter to be used to format message via ICU message format. |
||
155 | * Can be given as array or string configuration that will be given to [[Yii::createObject]] to create an instance |
||
156 | * or a [[MessageFormatter]] instance. |
||
157 | */ |
||
158 | public function setMessageFormatter($value) |
||
162 | |||
163 | /** |
||
164 | * Returns the message source for the given category. |
||
165 | * @param string $category the category name. |
||
166 | * @return MessageSource the message source for the given category. |
||
167 | * @throws InvalidConfigException if there is no message source available for the specified category. |
||
168 | */ |
||
169 | 550 | public function getMessageSource($category) |
|
202 | } |
||
203 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.