diff --git a/framework/yii/base/Application.php b/framework/yii/base/Application.php index 49b52d9..80e93a6 100644 --- a/framework/yii/base/Application.php +++ b/framework/yii/base/Application.php @@ -20,7 +20,7 @@ use yii\web\HttpException; * @property \yii\db\Connection $db The database connection. This property is read-only. * @property ErrorHandler $errorHandler The error handler application component. This property is read-only. * @property \yii\base\Formatter $formatter The formatter application component. This property is read-only. - * @property \yii\i18n\I18N $i18N The internationalization component. This property is read-only. + * @property \yii\i18n\I18N $i18n The internationalization component. This property is read-only. * @property \yii\log\Logger $log The log component. This property is read-only. * @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only. * @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime" diff --git a/framework/yii/i18n/FallbackMessageFormatter.php b/framework/yii/i18n/FallbackMessageFormatter.php deleted file mode 100644 index 17928f5..0000000 --- a/framework/yii/i18n/FallbackMessageFormatter.php +++ /dev/null @@ -1,306 +0,0 @@ - - * @since 2.0 - */ -class FallbackMessageFormatter -{ - private $_locale; - private $_pattern; - private $_errorMessage = ''; - private $_errorCode = 0; - - /** - * Constructs a new Message Formatter - * @link http://php.net/manual/en/messageformatter.create.php - * @param string $locale The locale to use when formatting arguments - * @param string $pattern The pattern string to stick arguments into. - */ - public function __construct($locale, $pattern) - { - $this->_locale = $locale; - $this->_pattern = $pattern; - } - - /** - * Constructs a new Message Formatter - * @link http://php.net/manual/en/messageformatter.create.php - * @param string $locale The locale to use when formatting arguments - * @param string $pattern The pattern string to stick arguments into. - * @return MessageFormatter The formatter object - */ - public static function create($locale, $pattern) - { - return new static($locale, $pattern); - } - - /** - * Format the message - * @link http://php.net/manual/en/messageformatter.format.php - * @param array $args Arguments to insert into the format string - * @return string The formatted string, or `FALSE` if an error occurred - */ - public function format($args) - { - return static::formatMessage($this->_locale, $this->_pattern, $args); - } - - /** - * Quick format message - * @link http://php.net/manual/en/messageformatter.formatmessage.php - * @param string $locale The locale to use for formatting locale-dependent parts - * @param string $pattern The pattern string to insert things into. - * @param array $args The array of values to insert into the format string - * @return string The formatted pattern string or `FALSE` if an error occurred - */ - public static function formatMessage($locale, $pattern, $args) - { - if (($tokens = static::tokenizePattern($pattern)) === false) { - return false; - } - foreach($tokens as $i => $token) { - if (is_array($token)) { - if (($tokens[$i] = static::parseToken($token, $args, $locale)) === false) { - return false; - } - } - } - return implode('', $tokens); - } - - /** - * Tokenizes a pattern by separating normal text from replaceable patterns - * @param string $pattern patter to tokenize - * @return array|bool array of tokens or false on failure - */ - private static function tokenizePattern($pattern) - { - $depth = 1; - if (($start = $pos = mb_strpos($pattern, '{')) === false) { - return [$pattern]; - } - $tokens = [mb_substr($pattern, 0, $pos)]; - while(true) { - $open = mb_strpos($pattern, '{', $pos + 1); - $close = mb_strpos($pattern, '}', $pos + 1); - if ($open === false && $close === false) { - break; - } - if ($open === false) { - $open = mb_strlen($pattern); - } - if ($close > $open) { - $depth++; - $pos = $open; - } else { - $depth--; - $pos = $close; - } - if ($depth == 0) { - $tokens[] = explode(',', mb_substr($pattern, $start + 1, $pos - $start - 1), 3); - $start = $pos + 1; - $tokens[] = mb_substr($pattern, $start, $open - $start); - $start = $open; - } - } - if ($depth != 0) { - return false; - } - return $tokens; - } - - /** - * Parses a token - * @param array $token the token to parse - * @param array $args arguments to replace - * @param string $locale the locale - * @return bool|string parsed token or false on failure - * @throws \yii\base\NotSupportedException when unsupported formatting is used. - */ - private static function parseToken($token, $args, $locale) - { - $param = trim($token[0]); - if (isset($args[$param])) { - $arg = $args[$param]; - } else { - return '{' . implode(',', $token) . '}'; - } - $type = isset($token[1]) ? trim($token[1]) : 'none'; - switch($type) - { - case 'number': - case 'date': - case 'time': - case 'spellout': - case 'ordinal': - case 'duration': - case 'choice': - case 'selectordinal': - throw new NotSupportedException("Message format '$type' is not supported. You have to install PHP intl extension to use this feature."); - case 'none': return $arg; - case 'select': - /* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html - selectStyle = (selector '{' message '}')+ - */ - $select = static::tokenizePattern($token[2]); - $c = count($select); - $message = false; - for($i = 0; $i + 1 < $c; $i++) { - if (is_array($select[$i]) || !is_array($select[$i + 1])) { - return false; - } - $selector = trim($select[$i++]); - if ($message === false && $selector == 'other' || $selector == $arg) { - $message = implode(',', $select[$i]); - } - } - if ($message !== false) { - return static::formatMessage($locale, $message, $args); - } - break; - case 'plural': - /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html - pluralStyle = [offsetValue] (selector '{' message '}')+ - offsetValue = "offset:" number - selector = explicitValue | keyword - explicitValue = '=' number // adjacent, no white space in between - keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+ - message: see MessageFormat - */ - $plural = static::tokenizePattern($token[2]); - $c = count($plural); - $message = false; - $offset = 0; - for($i = 0; $i + 1 < $c; $i++) { - if (is_array($plural[$i]) || !is_array($plural[$i + 1])) { - return false; - } - $selector = trim($plural[$i++]); - if ($i == 1 && substr($selector, 0, 7) == 'offset:') { - $offset = (int) trim(mb_substr($selector, 7, ($pos = mb_strpos(str_replace(["\n", "\r", "\t"], ' ', $selector), ' ', 7)) - 7)); - $selector = trim(mb_substr($selector, $pos + 1)); - } - if ($message === false && $selector == 'other' || - $selector[0] == '=' && (int) mb_substr($selector, 1) == $arg || - $selector == 'zero' && $arg - $offset == 0 || - $selector == 'one' && $arg - $offset == 1 || - $selector == 'two' && $arg - $offset == 2 - ) { - $message = implode(',', str_replace('#', $arg - $offset, $plural[$i])); - } - } - if ($message !== false) { - return static::formatMessage($locale, $message, $args); - } - break; - } - return false; - } - - /** - * Parse input string according to pattern - * @link http://php.net/manual/en/messageformatter.parse.php - * @param string $value The string to parse - * @return array An array containing the items extracted, or `FALSE` on error - */ - public function parse($value) - { - throw new NotSupportedException('You have to install PHP intl extension to use this feature.'); - } - - /** - * Quick parse input string - * @link http://php.net/manual/en/messageformatter.parsemessage.php - * @param string $locale The locale to use for parsing locale-dependent parts - * @param string $pattern The pattern with which to parse the `value`. - * @param string $source The string to parse, conforming to the `pattern`. - * @return array An array containing items extracted, or `FALSE` on error - */ - public static function parseMessage($locale, $pattern, $source) - { - throw new NotSupportedException('You have to install PHP intl extension to use this feature.'); - } - - /** - * Set the pattern used by the formatter - * @link http://php.net/manual/en/messageformatter.setpattern.php - * @param string $pattern The pattern string to use in this message formatter. - * @return bool `TRUE` on success or `FALSE` on failure. - */ - public function setPattern($pattern) - { - $this->_pattern = $pattern; - return true; - } - - /** - * Get the pattern used by the formatter - * @link http://php.net/manual/en/messageformatter.getpattern.php - * @return string The pattern string for this message formatter - */ - public function getPattern() - { - return $this->_pattern; - } - - /** - * Get the locale for which the formatter was created. - * @link http://php.net/manual/en/messageformatter.getlocale.php - * @return string The locale name - */ - public function getLocale() - { - return $this->_locale; - } - - /** - * Get the error code from last operation - * @link http://php.net/manual/en/messageformatter.geterrorcode.php - * @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR. - */ - public function getErrorCode() - { - return $this->_errorCode; - } - - /** - * Get the error text from the last operation - * @link http://php.net/manual/en/messageformatter.geterrormessage.php - * @return string Description of the last error. - */ - public function getErrorMessage() - { - return $this->_errorMessage; - } -} - -if (!class_exists('MessageFormatter', false)) { - class_alias('yii\\i18n\\FallbackMessageFormatter', 'MessageFormatter'); - define('YII_INTL_MESSAGE_FALLBACK', true); -} diff --git a/framework/yii/i18n/I18N.php b/framework/yii/i18n/I18N.php index b2b99b5..fe0b533 100644 --- a/framework/yii/i18n/I18N.php +++ b/framework/yii/i18n/I18N.php @@ -14,6 +14,10 @@ use yii\base\InvalidConfigException; /** * I18N provides features related with internationalization (I18N) and localization (L10N). * + * @property MessageFormatter $messageFormatter The message formatter to be used to format message via ICU + * message format. Note that the type of this property differs in getter and setter. See + * [[getMessageFormatter()]] and [[setMessageFormatter()]] for details. + * * @author Qiang Xue * @since 2.0 */ @@ -69,7 +73,7 @@ class I18N extends Component * @param string $message the message to be translated. * @param array $params the parameters that will be used to replace the corresponding placeholders in the message. * @param string $language the language code (e.g. `en_US`, `en`). - * @return string the translated message. + * @return string the translated and formatted message. */ public function translate($category, $message, $params, $language) { @@ -78,7 +82,7 @@ class I18N extends Component } /** - * Formats a message using using [[MessageFormatter]]. + * Formats a message using [[MessageFormatter]]. * * @param string $message the message to be formatted. * @param array $params the parameters that will be used to replace the corresponding placeholders in the message. @@ -93,12 +97,8 @@ class I18N extends Component } if (preg_match('~{\s*[\d\w]+\s*,~u', $message)) { - $formatter = new MessageFormatter($language, $message); - if ($formatter === null) { - Yii::warning("Unable to format message in language '$language': $message."); - return $message; - } - $result = $formatter->format($params); + $formatter = $this->getMessageFormatter(); + $result = $formatter->format($message, $params, $language); if ($result === false) { $errorMessage = $formatter->getErrorMessage(); Yii::warning("Formatting message for language '$language' failed with error: $errorMessage. The message being formatted was: $message."); @@ -116,6 +116,35 @@ class I18N extends Component } /** + * @var string|array|MessageFormatter + */ + private $_messageFormatter; + + /** + * Returns the message formatter instance. + * @return MessageFormatter the message formatter to be used to format message via ICU message format. + */ + public function getMessageFormatter() + { + if ($this->_messageFormatter === null) { + $this->_messageFormatter = new MessageFormatter(); + } elseif (is_array($this->_messageFormatter) || is_string($this->_messageFormatter)) { + $this->_messageFormatter = Yii::createObject($this->_messageFormatter); + } + return $this->_messageFormatter; + } + + /** + * @param string|array|MessageFormatter $value the message formatter to be used to format message via ICU message format. + * Can be given as array or string configuration that will be given to [[Yii::createObject]] to create an instance + * or a [[MessageFormatter]] instance. + */ + public function setMessageFormatter($value) + { + $this->_messageFormatter = $value; + } + + /** * Returns the message source for the given category. * @param string $category the category name. * @return MessageSource the message source for the given category. diff --git a/framework/yii/i18n/MessageFormatter.php b/framework/yii/i18n/MessageFormatter.php index 9f198c9..8fcf4bf 100644 --- a/framework/yii/i18n/MessageFormatter.php +++ b/framework/yii/i18n/MessageFormatter.php @@ -7,17 +7,17 @@ namespace yii\i18n; -if (!class_exists('MessageFormatter', false)) { - require_once(__DIR__ . '/FallbackMessageFormatter.php'); -} -defined('YII_INTL_MESSAGE_FALLBACK') || define('YII_INTL_MESSAGE_FALLBACK', false); +use yii\base\Component; +use yii\base\NotSupportedException; /** - * MessageFormatter enhances the message formatter class provided by PHP intl extension. + * MessageFormatter allows formatting messages via [ICU message format](http://userguide.icu-project.org/formatparse/messages) + * + * This class enhances the message formatter class provided by the PHP intl extension. * * The following enhancements are provided: * - * - Accepts named arguments and mixed numeric and named arguments. + * - It accepts named arguments and mixed numeric and named arguments. * - Issues no error when an insufficient number of arguments have been provided. Instead, the placeholders will not be * substituted. * - Fixes PHP 5.5 weird placeholder replacement in case no arguments are provided at all (https://bugs.php.net/bug.php?id=65920). @@ -25,53 +25,135 @@ defined('YII_INTL_MESSAGE_FALLBACK') || define('YII_INTL_MESSAGE_FALLBACK', fals * However it is highly recommended that you install [PHP intl extension](http://php.net/manual/en/book.intl.php) if you want * to use MessageFormatter features. * + * The fallback implementation only supports the following message formats: + * - plural formatting for english + * - select format + * - simple parameters + * - integer number parameters + * + * The fallback implementation does NOT support the ['apostrophe-friendly' syntax](http://www.php.net/manual/en/messageformatter.formatmessage.php). + * Also messages that are working with the fallback implementation are not necessarily compatible with the + * PHP intl MessageFormatter so do not rely on the fallback if you are able to install intl extension somehow. + * + * @property string $errorCode Code of the last error. This property is read-only. + * @property string $errorMessage Description of the last error. This property is read-only. + * * @author Alexander Makarov * @author Carsten Brandt * @since 2.0 */ -class MessageFormatter extends \MessageFormatter +class MessageFormatter extends Component { + private $_errorCode = 0; + private $_errorMessage = ''; + + /** + * Get the error code from the last operation + * @link http://php.net/manual/en/messageformatter.geterrorcode.php + * @return string Code of the last error. + */ + public function getErrorCode() + { + return $this->_errorCode; + } + /** - * Format the message. + * Get the error text from the last operation + * @link http://php.net/manual/en/messageformatter.geterrormessage.php + * @return string Description of the last error. + */ + public function getErrorMessage() + { + return $this->_errorMessage; + } + + /** + * Formats a message via [ICU message format](http://userguide.icu-project.org/formatparse/messages) * - * @link http://php.net/manual/en/messageformatter.format.php - * @param array $args Arguments to insert into the format string. - * @return string|boolean The formatted string, or false if an error occurred. + * It uses the PHP intl extension's [MessageFormatter](http://www.php.net/manual/en/class.messageformatter.php) + * and works around some issues. + * If PHP intl is not installed a fallback will be used that supports a subset of the ICU message format. + * + * @param string $pattern The pattern string to insert parameters into. + * @param array $params The array of name value pairs to insert into the format string. + * @param string $language The locale to use for formatting locale-dependent parts + * @return string|boolean The formatted pattern string or `FALSE` if an error occurred */ - public function format($args) + public function format($pattern, $params, $language) { - if ($args === []) { - return $this->getPattern(); + $this->_errorCode = 0; + $this->_errorMessage = ''; + + if ($params === []) { + return $pattern; + } + + if (!class_exists('MessageFormatter', false)) { + return $this->fallbackFormat($language, $pattern, $params); } - if (version_compare(PHP_VERSION, '5.5.0', '<') && !YII_INTL_MESSAGE_FALLBACK) { - $pattern = self::replaceNamedArguments($this->getPattern(), $args); - $this->setPattern($pattern); - $args = array_values($args); + if (version_compare(PHP_VERSION, '5.5.0', '<')) { + $pattern = $this->replaceNamedArguments($pattern, $params); + $params = array_values($params); + } + $formatter = new \MessageFormatter($language, $pattern); + if ($formatter === null) { + $this->_errorCode = -1; + $this->_errorMessage = "Message pattern is invalid."; + return false; + } + $result = $formatter->format($params); + if ($result === false) { + $this->_errorCode = $formatter->getErrorCode(); + $this->_errorMessage = $formatter->getErrorMessage(); + return false; + } else { + return $result; } - return parent::format($args); } /** - * Quick format message. + * Parses an input string according to an [ICU message format](http://userguide.icu-project.org/formatparse/messages) pattern. * - * @link http://php.net/manual/en/messageformatter.formatmessage.php - * @param string $locale The locale to use for formatting locale-dependent parts. - * @param string $pattern The pattern string to insert things into. - * @param array $args The array of values to insert into the format string. - * @return string|boolean The formatted pattern string or false if an error occurred. + * It uses the PHP intl extension's [MessageFormatter::parse()](http://www.php.net/manual/en/messageformatter.parsemessage.php) + * and works around some issues. + * Usage of this method requires PHP intl extension to be installed. + * + * @param string $pattern The pattern to use for parsing the message. + * @param string $message The message to parse, conforming to the pattern. + * @param string $language The locale to use for formatting locale-dependent parts + * @return array|boolean An array containing items extracted, or `FALSE` on error. + * @throws \yii\base\NotSupportedException when PHP intl extension is not installed. */ - public static function formatMessage($locale, $pattern, $args) + public function parse($pattern, $message, $language) { - if ($args === []) { - return $pattern; + $this->_errorCode = 0; + $this->_errorMessage = ''; + + if (!class_exists('MessageFormatter', false)) { + throw new NotSupportedException('You have to install PHP intl extension to use this feature.'); } - if (version_compare(PHP_VERSION, '5.5.0', '<') && !YII_INTL_MESSAGE_FALLBACK) { - $pattern = self::replaceNamedArguments($pattern, $args); - $args = array_values($args); + // TODO try to support named args +// if (version_compare(PHP_VERSION, '5.5.0', '<')) { +// $message = $this->replaceNamedArguments($message, $params); +// $params = array_values($params); +// } + $formatter = new \MessageFormatter($language, $pattern); + if ($formatter === null) { + $this->_errorCode = -1; + $this->_errorMessage = "Message pattern is invalid."; + return false; + } + $result = $formatter->parse($message); + if ($result === false) { + $this->_errorCode = $formatter->getErrorCode(); + $this->_errorMessage = $formatter->getErrorMessage(); + return false; + } else { + return $result; } - return parent::formatMessage($locale, $pattern, $args); + } /** @@ -124,4 +206,159 @@ class MessageFormatter extends \MessageFormatter } return $pattern; } + + /** + * Fallback implementation for MessageFormatter::formatMessage + * @param string $pattern The pattern string to insert things into. + * @param array $args The array of values to insert into the format string + * @param string $locale The locale to use for formatting locale-dependent parts + * @return string|boolean The formatted pattern string or `FALSE` if an error occurred + */ + protected function fallbackFormat($pattern, $args, $locale) + { + if (($tokens = $this->tokenizePattern($pattern)) === false) { + return false; + } + foreach($tokens as $i => $token) { + if (is_array($token)) { + if (($tokens[$i] = $this->parseToken($token, $args, $locale)) === false) { + return false; + } + } + } + return implode('', $tokens); + } + + /** + * Tokenizes a pattern by separating normal text from replaceable patterns + * @param string $pattern patter to tokenize + * @return array|bool array of tokens or false on failure + */ + private function tokenizePattern($pattern) + { + $depth = 1; + if (($start = $pos = mb_strpos($pattern, '{')) === false) { + return [$pattern]; + } + $tokens = [mb_substr($pattern, 0, $pos)]; + while(true) { + $open = mb_strpos($pattern, '{', $pos + 1); + $close = mb_strpos($pattern, '}', $pos + 1); + if ($open === false && $close === false) { + break; + } + if ($open === false) { + $open = mb_strlen($pattern); + } + if ($close > $open) { + $depth++; + $pos = $open; + } else { + $depth--; + $pos = $close; + } + if ($depth == 0) { + $tokens[] = explode(',', mb_substr($pattern, $start + 1, $pos - $start - 1), 3); + $start = $pos + 1; + $tokens[] = mb_substr($pattern, $start, $open - $start); + $start = $open; + } + } + if ($depth != 0) { + return false; + } + return $tokens; + } + + /** + * Parses a token + * @param array $token the token to parse + * @param array $args arguments to replace + * @param string $locale the locale + * @return bool|string parsed token or false on failure + * @throws \yii\base\NotSupportedException when unsupported formatting is used. + */ + private function parseToken($token, $args, $locale) + { + $param = trim($token[0]); + if (isset($args[$param])) { + $arg = $args[$param]; + } else { + return '{' . implode(',', $token) . '}'; + } + $type = isset($token[1]) ? trim($token[1]) : 'none'; + switch($type) + { + case 'date': + case 'time': + case 'spellout': + case 'ordinal': + case 'duration': + case 'choice': + case 'selectordinal': + throw new NotSupportedException("Message format '$type' is not supported. You have to install PHP intl extension to use this feature."); + case 'number': + if (is_int($arg) && (!isset($token[2]) || trim($token[2]) == 'integer')) { + return $arg; + } + throw new NotSupportedException("Message format 'number' is only supported for integer values. You have to install PHP intl extension to use this feature."); + case 'none': return $arg; + case 'select': + /* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html + selectStyle = (selector '{' message '}')+ + */ + $select = static::tokenizePattern($token[2]); + $c = count($select); + $message = false; + for($i = 0; $i + 1 < $c; $i++) { + if (is_array($select[$i]) || !is_array($select[$i + 1])) { + return false; + } + $selector = trim($select[$i++]); + if ($message === false && $selector == 'other' || $selector == $arg) { + $message = implode(',', $select[$i]); + } + } + if ($message !== false) { + return $this->fallbackFormat($message, $args, $locale); + } + break; + case 'plural': + /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html + pluralStyle = [offsetValue] (selector '{' message '}')+ + offsetValue = "offset:" number + selector = explicitValue | keyword + explicitValue = '=' number // adjacent, no white space in between + keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+ + message: see MessageFormat + */ + $plural = static::tokenizePattern($token[2]); + $c = count($plural); + $message = false; + $offset = 0; + for($i = 0; $i + 1 < $c; $i++) { + if (is_array($plural[$i]) || !is_array($plural[$i + 1])) { + return false; + } + $selector = trim($plural[$i++]); + if ($i == 1 && substr($selector, 0, 7) == 'offset:') { + $offset = (int) trim(mb_substr($selector, 7, ($pos = mb_strpos(str_replace(["\n", "\r", "\t"], ' ', $selector), ' ', 7)) - 7)); + $selector = trim(mb_substr($selector, $pos + 1)); + } + if ($message === false && $selector == 'other' || + $selector[0] == '=' && (int) mb_substr($selector, 1) == $arg || + $selector == 'zero' && $arg - $offset == 0 || + $selector == 'one' && $arg - $offset == 1 || + $selector == 'two' && $arg - $offset == 2 + ) { + $message = implode(',', str_replace('#', $arg - $offset, $plural[$i])); + } + } + if ($message !== false) { + return $this->fallbackFormat($message, $args, $locale); + } + break; + } + return false; + } } diff --git a/framework/yii/log/Logger.php b/framework/yii/log/Logger.php index 4e0e547..f79c40f 100644 --- a/framework/yii/log/Logger.php +++ b/framework/yii/log/Logger.php @@ -65,8 +65,8 @@ use yii\base\InvalidConfigException; * second element the total time spent in SQL execution. This property is read-only. * @property float $elapsedTime The total elapsed time in seconds for current request. This property is * read-only. - * @property array $profiling The profiling results. Each array element has the following structure: - * `[$token, $category, $time]`. This property is read-only. + * @property array $profiling The profiling results. Each array element has the following structure: `[$token, + * $category, $time]`. This property is read-only. * * @author Qiang Xue * @since 2.0 diff --git a/tests/unit/framework/i18n/FallbackMessageFormatterTest.php b/tests/unit/framework/i18n/FallbackMessageFormatterTest.php index 407ec7f..910c433 100644 --- a/tests/unit/framework/i18n/FallbackMessageFormatterTest.php +++ b/tests/unit/framework/i18n/FallbackMessageFormatterTest.php @@ -7,7 +7,7 @@ namespace yiiunit\framework\i18n; -use yii\i18n\FallbackMessageFormatter; +use yii\i18n\MessageFormatter; use yiiunit\TestCase; /** @@ -115,19 +115,10 @@ _MSG_ /** * @dataProvider patterns */ - public function testNamedArgumentsStatic($pattern, $expected, $args) + public function testNamedArguments($pattern, $expected, $args) { - $result = FallbackMessageFormatter::formatMessage('en_US', $pattern, $args); - $this->assertEquals($expected, $result); - } - - /** - * @dataProvider patterns - */ - public function testNamedArgumentsObject($pattern, $expected, $args) - { - $formatter = new FallbackMessageFormatter('en_US', $pattern); - $result = $formatter->format($args); + $formatter = new FallbackMessageFormatter(); + $result = $formatter->fallbackFormat($pattern, $args, 'en_US'); $this->assertEquals($expected, $result, $formatter->getErrorMessage()); } @@ -135,9 +126,10 @@ _MSG_ { $expected = '{'.self::SUBJECT.'} is '.self::N_VALUE; - $result = FallbackMessageFormatter::formatMessage('en_US', '{'.self::SUBJECT.'} is {'.self::N.'}', [ + $formatter = new FallbackMessageFormatter(); + $result = $formatter->fallbackFormat('{'.self::SUBJECT.'} is {'.self::N.'}', [ self::N => self::N_VALUE, - ]); + ], 'en_US'); $this->assertEquals($expected, $result); } @@ -145,11 +137,17 @@ _MSG_ public function testNoParams() { $pattern = '{'.self::SUBJECT.'} is '.self::N; - $result = FallbackMessageFormatter::formatMessage('en_US', $pattern, []); - $this->assertEquals($pattern, $result); - $formatter = new FallbackMessageFormatter('en_US', $pattern); - $result = $formatter->format([]); + $formatter = new FallbackMessageFormatter(); + $result = $formatter->fallbackFormat($pattern, [], 'en_US'); $this->assertEquals($pattern, $result, $formatter->getErrorMessage()); } +} + +class FallbackMessageFormatter extends MessageFormatter +{ + public function fallbackFormat($pattern, $args, $locale) + { + return parent::fallbackFormat($pattern, $args, $locale); + } } \ No newline at end of file diff --git a/tests/unit/framework/i18n/MessageFormatterTest.php b/tests/unit/framework/i18n/MessageFormatterTest.php index c392ce0..9030d87 100644 --- a/tests/unit/framework/i18n/MessageFormatterTest.php +++ b/tests/unit/framework/i18n/MessageFormatterTest.php @@ -122,19 +122,10 @@ _MSG_ /** * @dataProvider patterns */ - public function testNamedArgumentsStatic($pattern, $expected, $args) + public function testNamedArguments($pattern, $expected, $args) { - $result = MessageFormatter::formatMessage('en_US', $pattern, $args); - $this->assertEquals($expected, $result, intl_get_error_message()); - } - - /** - * @dataProvider patterns - */ - public function testNamedArgumentsObject($pattern, $expected, $args) - { - $formatter = new MessageFormatter('en_US', $pattern); - $result = $formatter->format($args); + $formatter = new MessageFormatter(); + $result = $formatter->format($pattern, $args, 'en_US'); $this->assertEquals($expected, $result, $formatter->getErrorMessage()); } @@ -142,36 +133,19 @@ _MSG_ { $expected = '{'.self::SUBJECT.'} is '.self::N_VALUE; - $result = MessageFormatter::formatMessage('en_US', '{'.self::SUBJECT.'} is {'.self::N.', number}', [ + $formatter = new MessageFormatter(); + $result = $formatter->format('{'.self::SUBJECT.'} is {'.self::N.', number}', [ self::N => self::N_VALUE, - ]); - - $this->assertEquals($expected, $result, intl_get_error_message()); - } + ], 'en_US'); - /** - * When instantiating a MessageFormatter with invalid pattern it should be null with default settings. - * It will be IntlException if intl.use_exceptions=1 and PHP 5.5 or newer or an error if intl.error_level is not 0. - */ - public function testNullConstructor() - { - if(ini_get('intl.use_exceptions')) { - $this->setExpectedException('IntlException'); - } - - if (!ini_get('intl.error_level') || ini_get('intl.use_exceptions')) { - $this->assertNull(new MessageFormatter('en_US', '')); - } + $this->assertEquals($expected, $result, $formatter->getErrorMessage()); } public function testNoParams() { $pattern = '{'.self::SUBJECT.'} is '.self::N; - $result = MessageFormatter::formatMessage('en_US', $pattern, []); - $this->assertEquals($pattern, $result, intl_get_error_message()); - - $formatter = new MessageFormatter('en_US', $pattern); - $result = $formatter->format([]); + $formatter = new MessageFormatter(); + $result = $formatter->format($pattern, [], 'en_US'); $this->assertEquals($pattern, $result, $formatter->getErrorMessage()); } } \ No newline at end of file