diff --git a/build/controllers/LocaleController.php b/build/controllers/LocaleController.php
deleted file mode 100644
index 7b2a5df..0000000
--- a/build/controllers/LocaleController.php
+++ /dev/null
@@ -1,114 +0,0 @@
-
- * @since 2.0
- */
-class LocaleController extends Controller
-{
-	public $defaultAction = 'plural';
-
-	/**
-	 * Generates the plural rules data.
-	 *
-	 * This command will parse the plural rule XML file from CLDR and convert them
-	 * into appropriate PHP representation to support Yii message translation feature.
-	 * @param string $xmlFile the original plural rule XML file (from CLDR). This file may be found in
-	 *      http://www.unicode.org/Public/cldr/latest/core.zip
-	 * Extract the zip file and locate the file "common/supplemental/plurals.xml".
-	 * @throws Exception
-	 */
-	public function actionPlural($xmlFile)
-	{
-		if (!is_file($xmlFile)) {
-			throw new Exception("The source plural rule file does not exist: $xmlFile");
-		}
-
-		$xml = simplexml_load_file($xmlFile);
-
-		$allRules = array();
-
-		$patterns = array(
-			'/n in 0..1/' => '(n==0||n==1)',
-			'/\s+is\s+not\s+/i' => '!=', //is not
-			'/\s+is\s+/i' => '==', //is
-			'/n\s+mod\s+(\d+)/i' => 'fmod(n,$1)', //mod (CLDR's "mod" is "fmod()", not "%")
-			'/^(.*?)\s+not\s+in\s+(\d+)\.\.(\d+)/i' => '!in_array($1,range($2,$3))', //not in
-			'/^(.*?)\s+in\s+(\d+)\.\.(\d+)/i' => 'in_array($1,range($2,$3))', //in
-			'/^(.*?)\s+not\s+within\s+(\d+)\.\.(\d+)/i' => '($1<$2||$1>$3)', //not within
-			'/^(.*?)\s+within\s+(\d+)\.\.(\d+)/i' => '($1>=$2&&$1<=$3)', //within
-		);
-		foreach ($xml->plurals->pluralRules as $node) {
-			$attributes = $node->attributes();
-			$locales = explode(' ', $attributes['locales']);
-			$rules = array();
-
-			if (!empty($node->pluralRule)) {
-				foreach ($node->pluralRule as $rule) {
-					$expr_or = preg_split('/\s+or\s+/i', $rule);
-					foreach ($expr_or as $key_or => $val_or) {
-						$expr_and = preg_split('/\s+and\s+/i', $val_or);
-						$expr_and = preg_replace(array_keys($patterns), array_values($patterns), $expr_and);
-						$expr_or[$key_or] = implode('&&', $expr_and);
-					}
-					$expr = preg_replace('/\\bn\\b/', '$n', implode('||', $expr_or));
-					$rules[] = preg_replace_callback('/range\((\d+),(\d+)\)/', function ($matches) {
-						if ($matches[2] - $matches[1] <= 5) {
-							return 'array(' . implode(',', range($matches[1], $matches[2])) . ')';
-						} else {
-							return $matches[0];
-						}
-					}, $expr);
-
-				}
-				foreach ($locales as $locale) {
-					$allRules[$locale] = $rules;
-				}
-			}
-		}
-		// hard fix for "br": the rule is too complex
-		$allRules['br'] = array(
-			0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),array(11,71,91))',
-			1 => 'fmod($n,10)==2&&!in_array(fmod($n,100),array(12,72,92))',
-			2 => 'in_array(fmod($n,10),array(3,4,9))&&!in_array(fmod($n,100),array_merge(range(10,19),range(70,79),range(90,99)))',
-			3 => 'fmod($n,1000000)==0&&$n!=0',
-		);
-		if (preg_match('/\d+/', $xml->version['number'], $matches)) {
-			$revision = $matches[0];
-		} else {
-			$revision = -1;
-		}
-
-		echo "getMessageSource($category)->translate($category, $message, $language);
+		$params = (array)$params;
 
-		if (!is_array($params)) {
-			$params = array($params);
-		}
-
-		if (isset($params[0])) {
-			$message = $this->applyPluralRules($message, $params[0], $language);
-			if (!isset($params['{n}'])) {
-				$params['{n}'] = $params[0];
+		if (class_exists('MessageFormatter', false) && preg_match('~{\s*[\d\w]+\s*,~u', $message)) {
+			$formatter = new MessageFormatter($language, $message);
+			if ($formatter === null) {
+				\Yii::$app->getLog()->log("$language message from category $category failed. Message is: $message.", Logger::LEVEL_WARNING, 'application');
+			}
+			$result = $formatter->format($params);
+			if ($result === false) {
+				$errorMessage = $formatter->getErrorMessage();
+				\Yii::$app->getLog()->log("$language message from category $category failed with error: $errorMessage. Message is: $message.", Logger::LEVEL_WARNING, 'application');
+			}
+			else {
+				return $result;
 			}
-			unset($params[0]);
 		}
 
 		return empty($params) ? $message : strtr($message, $params);
@@ -125,62 +118,4 @@ class I18N extends Component
 			throw new InvalidConfigException("Unable to locate message source for category '$category'.");
 		}
 	}
-
-	/**
-	 * Applies appropriate plural rules to the given message.
-	 * @param string $message the message to be applied with plural rules
-	 * @param mixed $number the number by which plural rules will be applied
-	 * @param string $language the language code that determines which set of plural rules to be applied.
-	 * @return string the message that has applied plural rules
-	 */
-	protected function applyPluralRules($message, $number, $language)
-	{
-		if (strpos($message, '|') === false) {
-			return $message;
-		}
-		$chunks = explode('|', $message);
-
-		$rules = $this->getPluralRules($language);
-		foreach ($rules as $i => $rule) {
-			if (isset($chunks[$i]) && $this->evaluate($rule, $number)) {
-				return $chunks[$i];
-			}
-		}
-		$n = count($rules);
-		return isset($chunks[$n]) ? $chunks[$n] : $chunks[0];
-	}
-
-	private $_pluralRules = array(); // language => rule set
-
-	/**
-	 * Returns the plural rules for the given language code.
-	 * @param string $language the language code (e.g. `en_US`, `en`).
-	 * @return array the plural rules
-	 * @throws InvalidParamException if the language code is invalid.
-	 */
-	protected function getPluralRules($language)
-	{
-		if (isset($this->_pluralRules[$language])) {
-			return $this->_pluralRules[$language];
-		}
-		$allRules = require(Yii::getAlias($this->pluralRuleFile));
-		if (isset($allRules[$language])) {
-			return $this->_pluralRules[$language] = $allRules[$language];
-		} elseif (preg_match('/^[a-z]+/', strtolower($language), $matches)) {
-			return $this->_pluralRules[$language] = isset($allRules[$matches[0]]) ? $allRules[$matches[0]] : array();
-		} else {
-			throw new InvalidParamException("Invalid language code: $language");
-		}
-	}
-
-	/**
-	 * Evaluates a PHP expression with the given number value.
-	 * @param string $expression the PHP expression
-	 * @param mixed $n the number value
-	 * @return boolean the expression result
-	 */
-	protected function evaluate($expression, $n)
-	{
-		return eval("return $expression;");
-	}
 }
diff --git a/framework/yii/i18n/MessageFormatter.php b/framework/yii/i18n/MessageFormatter.php
new file mode 100644
index 0000000..e7163c0
--- /dev/null
+++ b/framework/yii/i18n/MessageFormatter.php
@@ -0,0 +1,74 @@
+
+ * @since 2.0
+ */
+class MessageFormatter extends \MessageFormatter
+{
+	/**
+	 * Format the message.
+	 *
+	 * @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.
+	 */
+	public function format($args)
+	{
+		$pattern = self::replaceNamedArguments($this->getPattern(), $args);
+		$this->setPattern($pattern);
+		return parent::format(array_values($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|boolean The formatted pattern string or false if an error occurred.
+	 */
+	public static function formatMessage($locale, $pattern, $args)
+	{
+		$pattern = self::replaceNamedArguments($pattern, $args);
+		return parent::formatMessage($locale, $pattern, array_values($args));
+	}
+
+	/**
+	 * Replace named placeholders with numeric placeholders.
+	 *
+	 * @param string $pattern The pattern string to relace things into.
+	 * @param array $args The array of values to insert into the format string.
+	 * @return string The pattern string with placeholders replaced.
+	 */
+	private static function replaceNamedArguments($pattern, $args)
+	{
+		$map = array_flip(array_keys($args));
+		return preg_replace_callback('~({\s*)([\d\w]+)(\s*[,}])~u', function ($input) use ($map) {
+			$name = $input[2];
+			if (isset($map[$name])) {
+				return $input[1] . $map[$name] . $input[3];
+			}
+			else {
+				return "'" . $input[1] . $name . $input[3] . "'";
+			}
+		}, $pattern);
+	}
+}
+ 
\ No newline at end of file
diff --git a/framework/yii/i18n/data/plurals.php b/framework/yii/i18n/data/plurals.php
deleted file mode 100644
index cb51307..0000000
--- a/framework/yii/i18n/data/plurals.php
+++ /dev/null
@@ -1,627 +0,0 @@
-
-  array (
-    0 => '$n==0',
-    1 => '$n==1',
-    2 => '$n==2',
-    3 => 'in_array(fmod($n,100),range(3,10))',
-    4 => 'in_array(fmod($n,100),range(11,99))',
-  ),
-  'asa' =>
-  array (
-    0 => '$n==1',
-  ),
-  'af' =>
-  array (
-    0 => '$n==1',
-  ),
-  'bem' =>
-  array (
-    0 => '$n==1',
-  ),
-  'bez' =>
-  array (
-    0 => '$n==1',
-  ),
-  'bg' =>
-  array (
-    0 => '$n==1',
-  ),
-  'bn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'brx' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ca' =>
-  array (
-    0 => '$n==1',
-  ),
-  'cgg' =>
-  array (
-    0 => '$n==1',
-  ),
-  'chr' =>
-  array (
-    0 => '$n==1',
-  ),
-  'da' =>
-  array (
-    0 => '$n==1',
-  ),
-  'de' =>
-  array (
-    0 => '$n==1',
-  ),
-  'dv' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ee' =>
-  array (
-    0 => '$n==1',
-  ),
-  'el' =>
-  array (
-    0 => '$n==1',
-  ),
-  'en' =>
-  array (
-    0 => '$n==1',
-  ),
-  'eo' =>
-  array (
-    0 => '$n==1',
-  ),
-  'es' =>
-  array (
-    0 => '$n==1',
-  ),
-  'et' =>
-  array (
-    0 => '$n==1',
-  ),
-  'eu' =>
-  array (
-    0 => '$n==1',
-  ),
-  'fi' =>
-  array (
-    0 => '$n==1',
-  ),
-  'fo' =>
-  array (
-    0 => '$n==1',
-  ),
-  'fur' =>
-  array (
-    0 => '$n==1',
-  ),
-  'fy' =>
-  array (
-    0 => '$n==1',
-  ),
-  'gl' =>
-  array (
-    0 => '$n==1',
-  ),
-  'gsw' =>
-  array (
-    0 => '$n==1',
-  ),
-  'gu' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ha' =>
-  array (
-    0 => '$n==1',
-  ),
-  'haw' =>
-  array (
-    0 => '$n==1',
-  ),
-  'he' =>
-  array (
-    0 => '$n==1',
-  ),
-  'is' =>
-  array (
-    0 => '$n==1',
-  ),
-  'it' =>
-  array (
-    0 => '$n==1',
-  ),
-  'jmc' =>
-  array (
-    0 => '$n==1',
-  ),
-  'kaj' =>
-  array (
-    0 => '$n==1',
-  ),
-  'kcg' =>
-  array (
-    0 => '$n==1',
-  ),
-  'kk' =>
-  array (
-    0 => '$n==1',
-  ),
-  'kl' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ksb' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ku' =>
-  array (
-    0 => '$n==1',
-  ),
-  'lb' =>
-  array (
-    0 => '$n==1',
-  ),
-  'lg' =>
-  array (
-    0 => '$n==1',
-  ),
-  'mas' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ml' =>
-  array (
-    0 => '$n==1',
-  ),
-  'mn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'mr' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nah' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nb' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nd' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ne' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nl' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'no' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nr' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ny' =>
-  array (
-    0 => '$n==1',
-  ),
-  'nyn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'om' =>
-  array (
-    0 => '$n==1',
-  ),
-  'or' =>
-  array (
-    0 => '$n==1',
-  ),
-  'pa' =>
-  array (
-    0 => '$n==1',
-  ),
-  'pap' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ps' =>
-  array (
-    0 => '$n==1',
-  ),
-  'pt' =>
-  array (
-    0 => '$n==1',
-  ),
-  'rof' =>
-  array (
-    0 => '$n==1',
-  ),
-  'rm' =>
-  array (
-    0 => '$n==1',
-  ),
-  'rwk' =>
-  array (
-    0 => '$n==1',
-  ),
-  'saq' =>
-  array (
-    0 => '$n==1',
-  ),
-  'seh' =>
-  array (
-    0 => '$n==1',
-  ),
-  'sn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'so' =>
-  array (
-    0 => '$n==1',
-  ),
-  'sq' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ss' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ssy' =>
-  array (
-    0 => '$n==1',
-  ),
-  'st' =>
-  array (
-    0 => '$n==1',
-  ),
-  'sv' =>
-  array (
-    0 => '$n==1',
-  ),
-  'sw' =>
-  array (
-    0 => '$n==1',
-  ),
-  'syr' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ta' =>
-  array (
-    0 => '$n==1',
-  ),
-  'te' =>
-  array (
-    0 => '$n==1',
-  ),
-  'teo' =>
-  array (
-    0 => '$n==1',
-  ),
-  'tig' =>
-  array (
-    0 => '$n==1',
-  ),
-  'tk' =>
-  array (
-    0 => '$n==1',
-  ),
-  'tn' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ts' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ur' =>
-  array (
-    0 => '$n==1',
-  ),
-  'wae' =>
-  array (
-    0 => '$n==1',
-  ),
-  've' =>
-  array (
-    0 => '$n==1',
-  ),
-  'vun' =>
-  array (
-    0 => '$n==1',
-  ),
-  'xh' =>
-  array (
-    0 => '$n==1',
-  ),
-  'xog' =>
-  array (
-    0 => '$n==1',
-  ),
-  'zu' =>
-  array (
-    0 => '$n==1',
-  ),
-  'ak' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'am' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'bh' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'fil' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'tl' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'guw' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'hi' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'ln' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'mg' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'nso' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'ti' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'wa' =>
-  array (
-    0 => '($n==0||$n==1)',
-  ),
-  'ff' =>
-  array (
-    0 => '($n>=0&&$n<=2)&&$n!=2',
-  ),
-  'fr' =>
-  array (
-    0 => '($n>=0&&$n<=2)&&$n!=2',
-  ),
-  'kab' =>
-  array (
-    0 => '($n>=0&&$n<=2)&&$n!=2',
-  ),
-  'lv' =>
-  array (
-    0 => '$n==0',
-    1 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-  ),
-  'iu' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'kw' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'naq' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'se' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'sma' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'smi' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'smj' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'smn' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'sms' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-  ),
-  'ga' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==2',
-    2 => 'in_array($n,array(3,4,5,6))',
-    3 => 'in_array($n,array(7,8,9,10))',
-  ),
-  'ro' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==0||$n!=1&&in_array(fmod($n,100),range(1,19))',
-  ),
-  'mo' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==0||$n!=1&&in_array(fmod($n,100),range(1,19))',
-  ),
-  'lt' =>
-  array (
-    0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),range(11,19))',
-    1 => 'in_array(fmod($n,10),range(2,9))&&!in_array(fmod($n,100),range(11,19))',
-  ),
-  'be' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'bs' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'hr' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'ru' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'sh' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'sr' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'uk' =>
-  array (
-    0 => 'fmod($n,10)==1&&fmod($n,100)!=11',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => 'fmod($n,10)==0||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(11,12,13,14))',
-  ),
-  'cs' =>
-  array (
-    0 => '$n==1',
-    1 => 'in_array($n,array(2,3,4))',
-  ),
-  'sk' =>
-  array (
-    0 => '$n==1',
-    1 => 'in_array($n,array(2,3,4))',
-  ),
-  'pl' =>
-  array (
-    0 => '$n==1',
-    1 => 'in_array(fmod($n,10),array(2,3,4))&&!in_array(fmod($n,100),array(12,13,14))',
-    2 => '$n!=1&&in_array(fmod($n,10),array(0,1))||in_array(fmod($n,10),array(5,6,7,8,9))||in_array(fmod($n,100),array(12,13,14))',
-  ),
-  'sl' =>
-  array (
-    0 => 'fmod($n,100)==1',
-    1 => 'fmod($n,100)==2',
-    2 => 'in_array(fmod($n,100),array(3,4))',
-  ),
-  'mt' =>
-  array (
-    0 => '$n==1',
-    1 => '$n==0||in_array(fmod($n,100),range(2,10))',
-    2 => 'in_array(fmod($n,100),range(11,19))',
-  ),
-  'mk' =>
-  array (
-    0 => 'fmod($n,10)==1&&$n!=11',
-  ),
-  'cy' =>
-  array (
-    0 => '$n==0',
-    1 => '$n==1',
-    2 => '$n==2',
-    3 => '$n==3',
-    4 => '$n==6',
-  ),
-  'lag' =>
-  array (
-    0 => '$n==0',
-    1 => '($n>=0&&$n<=2)&&$n!=0&&$n!=2',
-  ),
-  'shi' =>
-  array (
-    0 => '($n>=0&&$n<=1)',
-    1 => 'in_array($n,range(2,10))',
-  ),
-  'br' =>
-  array (
-    0 => 'fmod($n,10)==1&&!in_array(fmod($n,100),array(11,71,91))',
-    1 => 'fmod($n,10)==2&&!in_array(fmod($n,100),array(12,72,92))',
-    2 => 'in_array(fmod($n,10),array(3,4,9))&&!in_array(fmod($n,100),array_merge(range(10,19),range(70,79),range(90,99)))',
-    3 => 'fmod($n,1000000)==0&&$n!=0',
-  ),
-  'ksh' =>
-  array (
-    0 => '$n==0',
-    1 => '$n==1',
-  ),
-  'tzm' =>
-  array (
-    0 => '($n==0||$n==1)||in_array($n,range(11,99))',
-  ),
-  'gv' =>
-  array (
-    0 => 'in_array(fmod($n,10),array(1,2))||fmod($n,20)==0',
-  ),
-);
diff --git a/framework/yii/i18n/data/plurals.xml b/framework/yii/i18n/data/plurals.xml
deleted file mode 100644
index 9227dc6..0000000
--- a/framework/yii/i18n/data/plurals.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-    
-    
-    
-        
-         
-        
-            n is 0
-            n is 1
-            n is 2
-            n mod 100 in 3..10
-            n mod 100 in 11..99
-        
-        
-            n is 1
-        
-        
-            n in 0..1
-        
-        
-            n within 0..2 and n is not 2
-        
-        
-            n is 0
-            n mod 10 is 1 and n mod 100 is not 11
-        
-        
-            n is 1
-            n is 2
-        
-         
-            n is 1
-            n is 2
-            n in 3..6
-            n in 7..10
-        
-        
-            n is 1
-            n is 0 OR n is not 1 AND n mod 100 in 1..19
-        
-        
-            n mod 10 is 1 and n mod 100 not in 11..19
-            n mod 10 in 2..9 and n mod 100 not in 11..19
-        
-        
-            n mod 10 is 1 and n mod 100 is not 11
-            n mod 10 in 2..4 and n mod 100 not in 12..14
-            n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14
-            
-        
-        
-            n is 1
-            n in 2..4
-        
-        
-            n is 1
-            n mod 10 in 2..4 and n mod 100 not in 12..14
-            n is not 1 and n mod 10 in 0..1 or n mod 10 in 5..9 or n mod 100 in 12..14
-            
-            
-        
-        
-            n mod 100 is 1
-            n mod 100 is 2
-            n mod 100 in 3..4
-        
-         
-            n is 1
-            n is 0 or n mod 100 in 2..10
-            n mod 100 in 11..19
-        
-         
-            n mod 10 is 1 and n is not 11
-        
-         
-            n is 0
-            n is 1
-            n is 2
-            n is 3
-            n is 6
-        
-        
-            n is 0
-            n within 0..2 and n is not 0 and n is not 2
-        
-        
-            n within 0..1
-            n in 2..10
-        
-         
-            n mod 10 is 1 and n mod 100 not in 11,71,91
-            n mod 10 is 2 and n mod 100 not in 12,72,92
-            n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99
-            n mod 1000000 is 0 and n is not 0
-        
-        
-            n is 0
-            n is 1
-        
-        
-            n in 0..1 or n in 11..99
-        
-        
-            n mod 10 in 1..2 or n mod 20 is 0
-        
-    
-
diff --git a/framework/yii/requirements/requirements.php b/framework/yii/requirements/requirements.php
index 005a205..571aa57 100644
--- a/framework/yii/requirements/requirements.php
+++ b/framework/yii/requirements/requirements.php
@@ -43,6 +43,8 @@ return array(
 		'mandatory' => false,
 		'condition' => $this->checkPhpExtensionVersion('intl', '1.0.2', '>='),
 		'by' => 'Internationalization support',
-		'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use IDN-feature of EmailValidator or UrlValidator or the yii\i18n\Formatter class.'
+		'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use advanced parameters formatting
+		in \Yii::t(), IDN-feature of
+		EmailValidator or UrlValidator or the yii\i18n\Formatter class.'
 	),
 );
diff --git a/tests/unit/framework/i18n/MessageFormatterTest.php b/tests/unit/framework/i18n/MessageFormatterTest.php
new file mode 100644
index 0000000..7595fe0
--- /dev/null
+++ b/tests/unit/framework/i18n/MessageFormatterTest.php
@@ -0,0 +1,47 @@
+
+ * @since 2.0
+ * @group i18n
+ */
+class MessageFormatterTest extends TestCase
+{
+	const N = 'n';
+	const N_VALUE = 42;
+	const SUBJECT = 'сабж';
+	const SUBJECT_VALUE = 'Answer to the Ultimate Question of Life, the Universe, and Everything';
+
+	public function testNamedArguments()
+	{
+		$expected = self::SUBJECT_VALUE.' is '.self::N_VALUE;
+
+		$result = MessageFormatter::formatMessage('en_US', '{'.self::SUBJECT.'} is {'.self::N.', number}', array(
+			self::N => self::N_VALUE,
+			self::SUBJECT => self::SUBJECT_VALUE,
+		));
+
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testInsufficientArguments()
+	{
+		$expected = '{'.self::SUBJECT.'} is '.self::N_VALUE;
+
+		$result = MessageFormatter::formatMessage('en_US', '{'.self::SUBJECT.'} is {'.self::N.', number}', array(
+			self::N => self::N_VALUE,
+		));
+
+		$this->assertEquals($expected, $result);
+	}
+}
\ No newline at end of file