Browse Source
* 'master' of github.com:yiisoft/yii2: (27 commits) Fixed typos fixes #995 Fixed option merging in Console::prompt() changed default button style typo fix. Refactored getModule and hasModule. Added intl check to tests, better error reporting, credited Aura.Intl for the most complex test pattern Better MessageFormatter tests GII sub-modules support - see #871 Module::getModule and Module::hasModule support for sub-modules - see #983 removed needFix method Removed intl version check since it's very inconsistent and it seems bundled versions are always the same ones for the same PHP versions Fixes PHP 5.5 weird placeholder replacememt in case no arguments are provided at all (https://bugs.php.net/bug.php?id=65920). changed plural format for BaseListView applied new style of Yii::t params to all occurences fixed I18N handling of special param values and broken message tags adjusted I18N to be consistent with intl message formatting improved unit tests for ICU message formatter fixed regex for multiline patterns intl message parser now handles too many or too less args ...tags/2.0.0-beta
Carsten Brandt
11 years ago
28 changed files with 759 additions and 1023 deletions
@ -1,114 +0,0 @@ |
|||||||
<?php |
|
||||||
/** |
|
||||||
* @link http://www.yiiframework.com/ |
|
||||||
* @copyright Copyright (c) 2008 Yii Software LLC |
|
||||||
* @license http://www.yiiframework.com/license/ |
|
||||||
*/ |
|
||||||
|
|
||||||
namespace yii\build\controllers; |
|
||||||
|
|
||||||
use yii\console\Exception; |
|
||||||
use yii\console\Controller; |
|
||||||
|
|
||||||
/** |
|
||||||
* http://www.unicode.org/cldr/charts/supplemental/language_plural_rules.html |
|
||||||
* @author Qiang Xue <qiang.xue@gmail.com> |
|
||||||
* @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 "<?php\n";
|
|
||||||
echo <<<EOD |
|
||||||
/** |
|
||||||
* Plural rules. |
|
||||||
* |
|
||||||
* This file is automatically generated by the "yii locale/plural" command under the "build" folder. |
|
||||||
* Do not modify it directly. |
|
||||||
* |
|
||||||
* The original plural rule data used for generating this file has the following copyright terms: |
|
||||||
* |
|
||||||
* Copyright © 1991-2007 Unicode, Inc. All rights reserved. |
|
||||||
* Distributed under the Terms of Use in http://www.unicode.org/copyright.html. |
|
||||||
* |
|
||||||
* @revision $revision (of the original plural file) |
|
||||||
* @link http://www.yiiframework.com/ |
|
||||||
* @copyright Copyright (c) 2008 Yii Software LLC |
|
||||||
* @license http://www.yiiframework.com/license/ |
|
||||||
*/ |
|
||||||
EOD; |
|
||||||
echo "\nreturn " . var_export($allRules, true) . ';'; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,230 @@ |
|||||||
|
Internationalization |
||||||
|
==================== |
||||||
|
|
||||||
|
Internationalization (I18N) refers to the process of designing a software application so that it can be adapted to |
||||||
|
various languages and regions without engineering changes. For Web applications, this is of particular importance |
||||||
|
because the potential users may be worldwide. |
||||||
|
|
||||||
|
Locale and Language |
||||||
|
------------------- |
||||||
|
|
||||||
|
There are two languages defined in Yii application: [[\yii\base\Application::$sourceLanguage|source language]] and |
||||||
|
[[\yii\base\Application::$language|target language]]. |
||||||
|
|
||||||
|
Source language is the language original application messages are written in such as: |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'I am a message!'); |
||||||
|
``` |
||||||
|
|
||||||
|
> **Tip**: Default is English and it's not recommended to change it. The reason is that it's easier to find people translating from |
||||||
|
> English to any language than from non-English to non-English. |
||||||
|
|
||||||
|
Target language is what's currently used. It's defined in application configuration like the following: |
||||||
|
|
||||||
|
```php |
||||||
|
// ... |
||||||
|
return array( |
||||||
|
'id' => 'applicationID', |
||||||
|
'basePath' => dirname(__DIR__), |
||||||
|
'language' => 'ru_RU' // ← here! |
||||||
|
``` |
||||||
|
|
||||||
|
Later you can easily change it in runtime: |
||||||
|
|
||||||
|
```php |
||||||
|
\Yii::$app->language = 'zh_CN'; |
||||||
|
``` |
||||||
|
|
||||||
|
Basic message translation |
||||||
|
------------------------- |
||||||
|
|
||||||
|
Yii basic message translation in its basic variant works without additional PHP extension. What it does is finding a |
||||||
|
translation of the message from source language into target language. Message itself is specified as the second |
||||||
|
`\Yii::t` method parameter: |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'This is a string to translate!'); |
||||||
|
``` |
||||||
|
|
||||||
|
Yii tries to load approprite translation from one of the message sources defined via `i18n` component configuration. |
||||||
|
|
||||||
|
TBD: https://github.com/yiisoft/yii2/issues/930 |
||||||
|
|
||||||
|
### Named placeholders |
||||||
|
|
||||||
|
You can add parameters to a translation message that will be substituted with the corresponding value after translation. |
||||||
|
The format for this is to use curly brackets around the parameter name as you can see in the following example: |
||||||
|
|
||||||
|
```php |
||||||
|
$username = 'Alexander'; |
||||||
|
echo \Yii::t('app', 'Hello, {username}!', array( |
||||||
|
'username' => $username, |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
Note that the parameter assignment is without the brackets. |
||||||
|
|
||||||
|
### Positional placeholders |
||||||
|
|
||||||
|
```php |
||||||
|
$sum = 42; |
||||||
|
echo \Yii::t('app', 'Balance: {0}', $sum); |
||||||
|
``` |
||||||
|
|
||||||
|
> **Tip**: Try keep message strings meaningful and avoid using too many positional parameters. Remember that |
||||||
|
> translator has source string only so it should be obvious about what will replace each placeholder. |
||||||
|
|
||||||
|
Advanced placeholder formatting |
||||||
|
------------------------------- |
||||||
|
|
||||||
|
In order to use advanced features you need to install and enable [intl](http://www.php.net/manual/en/intro.intl.php) PHP |
||||||
|
extension. After installing and enabling it you will be able to use extended syntax for placeholders. Either short form |
||||||
|
`{placeholderName, argumentType}` that means default setting or full form `{placeholderName, argumentType, argumentStyle}` |
||||||
|
that allows you to specify formatting style. |
||||||
|
|
||||||
|
Full reference is [available at ICU website](http://icu-project.org/apiref/icu4c/classMessageFormat.html) but since it's |
||||||
|
a bit crypric we have our own reference below. |
||||||
|
|
||||||
|
### Numbers |
||||||
|
|
||||||
|
```php |
||||||
|
$sum = 42; |
||||||
|
echo \Yii::t('app', 'Balance: {0, number}', $sum); |
||||||
|
``` |
||||||
|
|
||||||
|
You can specify one of the built-in styles (`integer`, `currency`, `percent`): |
||||||
|
|
||||||
|
```php |
||||||
|
$sum = 42; |
||||||
|
echo \Yii::t('app', 'Balance: {0, number, currency}', $sum); |
||||||
|
``` |
||||||
|
|
||||||
|
Or specify custom pattern: |
||||||
|
|
||||||
|
```php |
||||||
|
$sum = 42; |
||||||
|
echo \Yii::t('app', 'Balance: {0, number, ,000,000000}', $sum); |
||||||
|
``` |
||||||
|
|
||||||
|
[Formatting reference](http://icu-project.org/apiref/icu4c/classicu_1_1DecimalFormat.html). |
||||||
|
|
||||||
|
### Dates |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'Today is {0, date}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
Built in formats (`short`, `medium`, `long`, `full`): |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'Today is {0, date, short}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
Custom pattern: |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'Today is {0, date, YYYY-MM-dd}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
[Formatting reference](http://icu-project.org/apiref/icu4c/classicu_1_1SimpleDateFormat.html). |
||||||
|
|
||||||
|
### Time |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'It is {0, time}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
Built in formats (`short`, `medium`, `long`, `full`): |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'It is {0, time, short}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
Custom pattern: |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'It is {0, date, HH:mm}', time()); |
||||||
|
``` |
||||||
|
|
||||||
|
[Formatting reference](http://icu-project.org/apiref/icu4c/classicu_1_1SimpleDateFormat.html). |
||||||
|
|
||||||
|
|
||||||
|
### Spellout |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', '{n,number} is spelled as {n, spellout}', array( |
||||||
|
'n' => 42, |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
### Ordinal |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'You are {n, ordinal} visitor here!', array( |
||||||
|
'n' => 42, |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
Will produce "You are 42nd visitor here!". |
||||||
|
|
||||||
|
### Duration |
||||||
|
|
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'You are here for {n, duration} already!', array( |
||||||
|
'n' => 42, |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
Will produce "You are here for 47 sec. already!". |
||||||
|
|
||||||
|
### Plurals |
||||||
|
|
||||||
|
Different languages have different ways to inflect plurals. Some rules are very complex so it's very handy that this |
||||||
|
functionality is provided without the need to specify inflection rule. Instead it only requires your input of inflected |
||||||
|
word in certain situations. |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', 'There {n, plural, =0{are no cats} =1{is one cat} other{are # cats}}!', array( |
||||||
|
'n' => 0, |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
Will give us "There are no cats!". |
||||||
|
|
||||||
|
In the plural rule arguments above `=0` means exactly zero, `=1` stands for exactly one `other` is for any other number. |
||||||
|
`#` is replaced with the `n` argument value. It's not that simple for languages other than English. Here's an example |
||||||
|
for Russian: |
||||||
|
|
||||||
|
``` |
||||||
|
Здесь {n, plural, =0{котов нет} =1{есть один кот} one{# кот} few{# кота} many{# котов} other{# кота}}! |
||||||
|
``` |
||||||
|
|
||||||
|
In the above it worth mentioning that `=1` matches exactly `n = 1` while `one` matches `21` or `101`. |
||||||
|
|
||||||
|
To learn which inflection forms you should specify for your language you can referer to |
||||||
|
[rules reference at unicode.org](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html). |
||||||
|
|
||||||
|
### Selections |
||||||
|
|
||||||
|
You can select phrases based on keywords. The pattern in this case specifies how to map keywords to phrases and |
||||||
|
provides a default phrase. |
||||||
|
|
||||||
|
```php |
||||||
|
echo \Yii::t('app', '{name} is {gender} and {gender, select, female{she} male{he} other{it}} loves Yii!', array( |
||||||
|
'name' => 'Snoopy', |
||||||
|
'gender' => 'dog', |
||||||
|
)); |
||||||
|
``` |
||||||
|
|
||||||
|
Will produce "Snoopy is dog and it loves Yii!". |
||||||
|
|
||||||
|
In the expression `female` and `male` are possible values. `other` handler values that do not match. Strings inside |
||||||
|
brackets are sub-expressions so could be just a string or a string with more placeholders. |
||||||
|
|
||||||
|
Formatters |
||||||
|
---------- |
||||||
|
|
||||||
|
In order to use formatters you need to install and enable [intl](http://www.php.net/manual/en/intro.intl.php) PHP |
||||||
|
extension. |
@ -0,0 +1,117 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\i18n; |
||||||
|
|
||||||
|
/** |
||||||
|
* MessageFormatter is an enhanced version of PHP intl class that no matter which PHP and ICU versions are used: |
||||||
|
* |
||||||
|
* - 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). |
||||||
|
* |
||||||
|
* @author Alexander Makarov <sam@rmcreative.ru> |
||||||
|
* @author Carsten Brandt <mail@cebe.cc> |
||||||
|
* @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) |
||||||
|
{ |
||||||
|
if ($args === array()) { |
||||||
|
return $this->getPattern(); |
||||||
|
} |
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0', '<')) { |
||||||
|
$pattern = self::replaceNamedArguments($this->getPattern(), $args); |
||||||
|
$this->setPattern($pattern); |
||||||
|
$args = array_values($args); |
||||||
|
} |
||||||
|
return parent::format($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) |
||||||
|
{ |
||||||
|
if ($args === array()) { |
||||||
|
return $pattern; |
||||||
|
} |
||||||
|
|
||||||
|
if (version_compare(PHP_VERSION, '5.5.0', '<')) { |
||||||
|
$pattern = self::replaceNamedArguments($pattern, $args); |
||||||
|
$args = array_values($args); |
||||||
|
} |
||||||
|
return parent::formatMessage($locale, $pattern, $args); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Replace named placeholders with numeric placeholders and quote unused. |
||||||
|
* |
||||||
|
* @param string $pattern The pattern string to replace 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)); |
||||||
|
|
||||||
|
// parsing pattern based on ICU grammar: |
||||||
|
// http://icu-project.org/apiref/icu4c/classMessageFormat.html#details |
||||||
|
$parts = explode('{', $pattern); |
||||||
|
$c = count($parts); |
||||||
|
$pattern = $parts[0]; |
||||||
|
$d = 0; |
||||||
|
$stack = array(); |
||||||
|
for($i = 1; $i < $c; $i++) { |
||||||
|
if (preg_match('~^(\s*)([\d\w]+)(\s*)([},])(\s*)(.*)$~us', $parts[$i], $matches)) { |
||||||
|
// if we are not inside a plural or select this is a message |
||||||
|
if (!isset($stack[$d]) || $stack[$d] != 'plural' && $stack[$d] != 'select') { |
||||||
|
$d++; |
||||||
|
// replace normal arg if it is available |
||||||
|
if (isset($map[$matches[2]])) { |
||||||
|
$q = ''; |
||||||
|
$pattern .= '{' . $matches[1] . $map[$matches[2]] . $matches[3]; |
||||||
|
} else { |
||||||
|
// quote unused args |
||||||
|
$q = ($matches[4] == '}') ? "'" : ""; |
||||||
|
$pattern .= "$q{" . $matches[1] . $matches[2] . $matches[3]; |
||||||
|
} |
||||||
|
$pattern .= ($term = $matches[4] . $q . $matches[5] . $matches[6]); |
||||||
|
// store type of current level |
||||||
|
$stack[$d] = ($matches[4] == ',') ? substr($matches[6], 0, 6) : 'none'; |
||||||
|
// if it's plural or select, the next bracket is NOT begin of a message then! |
||||||
|
if ($stack[$d] == 'plural' || $stack[$d] == 'select') { |
||||||
|
$i++; |
||||||
|
$d -= substr_count($term, '}'); |
||||||
|
} else { |
||||||
|
$d -= substr_count($term, '}'); |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
$pattern .= '{' . $parts[$i]; |
||||||
|
$d += 1 - substr_count($parts[$i], '}'); |
||||||
|
} |
||||||
|
return $pattern; |
||||||
|
} |
||||||
|
} |
@ -1,627 +0,0 @@ |
|||||||
<?php |
|
||||||
/** |
|
||||||
* Plural rules. |
|
||||||
* |
|
||||||
* This file is automatically generated by the "yii locale/plural" command under the "build" folder. |
|
||||||
* Do not modify it directly. |
|
||||||
* |
|
||||||
* The original plural rule data used for generating this file has the following copyright terms: |
|
||||||
* |
|
||||||
* Copyright © 1991-2007 Unicode, Inc. All rights reserved. |
|
||||||
* Distributed under the Terms of Use in http://www.unicode.org/copyright.html. |
|
||||||
* |
|
||||||
* @revision 6008 (of the original plural file) |
|
||||||
* @link http://www.yiiframework.com/ |
|
||||||
* @copyright Copyright (c) 2008 Yii Software LLC |
|
||||||
* @license http://www.yiiframework.com/license/ |
|
||||||
*/ |
|
||||||
return array ( |
|
||||||
'ar' => |
|
||||||
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', |
|
||||||
), |
|
||||||
); |
|
@ -1,109 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8" ?> |
|
||||||
<!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd"> |
|
||||||
<supplementalData> |
|
||||||
<version number="$Revision: 6008 $"/> |
|
||||||
<generation date="$Date: 2011-07-12 13:18:01 -0500 (Tue, 12 Jul 2011) $"/> |
|
||||||
<plurals> |
|
||||||
<!-- if locale is known to have no plurals, there are no rules --> |
|
||||||
<pluralRules locales="az bm bo dz fa id ig ii hu ja jv ka kde kea km kn ko lo ms my sah ses sg th to tr vi wo yo zh"/> |
|
||||||
<pluralRules locales="ar"> |
|
||||||
<pluralRule count="zero">n is 0</pluralRule> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="two">n is 2</pluralRule> |
|
||||||
<pluralRule count="few">n mod 100 in 3..10</pluralRule> |
|
||||||
<pluralRule count="many">n mod 100 in 11..99</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="asa af bem bez bg bn brx ca cgg chr da de dv ee el en eo es et eu fi fo fur fy gl gsw gu ha haw he is it jmc kaj kcg kk kl ksb ku lb lg mas ml mn mr nah nb nd ne nl nn no nr ny nyn om or pa pap ps pt rof rm rwk saq seh sn so sq ss ssy st sv sw syr ta te teo tig tk tn ts ur wae ve vun xh xog zu"> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="ak am bh fil tl guw hi ln mg nso ti wa"> |
|
||||||
<pluralRule count="one">n in 0..1</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="ff fr kab"> |
|
||||||
<pluralRule count="one">n within 0..2 and n is not 2</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="lv"> |
|
||||||
<pluralRule count="zero">n is 0</pluralRule> |
|
||||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="iu kw naq se sma smi smj smn sms"> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="two">n is 2</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="ga"> <!-- http://unicode.org/cldr/trac/ticket/3915 --> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="two">n is 2</pluralRule> |
|
||||||
<pluralRule count="few">n in 3..6</pluralRule> |
|
||||||
<pluralRule count="many">n in 7..10</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="ro mo"> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="few">n is 0 OR n is not 1 AND n mod 100 in 1..19</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="lt"> |
|
||||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11..19</pluralRule> |
|
||||||
<pluralRule count="few">n mod 10 in 2..9 and n mod 100 not in 11..19</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="be bs hr ru sh sr uk"> |
|
||||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 is not 11</pluralRule> |
|
||||||
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule> |
|
||||||
<pluralRule count="many">n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14</pluralRule> |
|
||||||
<!-- others are fractions --> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="cs sk"> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="few">n in 2..4</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="pl"> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="few">n mod 10 in 2..4 and n mod 100 not in 12..14</pluralRule> |
|
||||||
<pluralRule count="many">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</pluralRule> |
|
||||||
<!-- others are fractions --> |
|
||||||
<!-- and n mod 100 not in 22..24 from Tamplin --> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="sl"> |
|
||||||
<pluralRule count="one">n mod 100 is 1</pluralRule> |
|
||||||
<pluralRule count="two">n mod 100 is 2</pluralRule> |
|
||||||
<pluralRule count="few">n mod 100 in 3..4</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="mt"> <!-- from Tamplin's data --> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="few">n is 0 or n mod 100 in 2..10</pluralRule> |
|
||||||
<pluralRule count="many">n mod 100 in 11..19</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="mk"> <!-- from Tamplin's data --> |
|
||||||
<pluralRule count="one">n mod 10 is 1 and n is not 11</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="cy"> <!-- from http://www.saltcymru.org/wordpress/?p=99&lang=en --> |
|
||||||
<pluralRule count="zero">n is 0</pluralRule> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
<pluralRule count="two">n is 2</pluralRule> |
|
||||||
<pluralRule count="few">n is 3</pluralRule> |
|
||||||
<pluralRule count="many">n is 6</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="lag"> |
|
||||||
<pluralRule count="zero">n is 0</pluralRule> |
|
||||||
<pluralRule count="one">n within 0..2 and n is not 0 and n is not 2</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="shi"> |
|
||||||
<pluralRule count="one">n within 0..1</pluralRule> |
|
||||||
<pluralRule count="few">n in 2..10</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="br"> <!-- from http://unicode.org/cldr/trac/ticket/2886 --> |
|
||||||
<pluralRule count="one">n mod 10 is 1 and n mod 100 not in 11,71,91</pluralRule> |
|
||||||
<pluralRule count="two">n mod 10 is 2 and n mod 100 not in 12,72,92</pluralRule> |
|
||||||
<pluralRule count="few">n mod 10 in 3..4,9 and n mod 100 not in 10..19,70..79,90..99</pluralRule> |
|
||||||
<pluralRule count="many">n mod 1000000 is 0 and n is not 0</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="ksh"> |
|
||||||
<pluralRule count="zero">n is 0</pluralRule> |
|
||||||
<pluralRule count="one">n is 1</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="tzm"> |
|
||||||
<pluralRule count="one">n in 0..1 or n in 11..99</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
<pluralRules locales="gv"> |
|
||||||
<pluralRule count="one">n mod 10 in 1..2 or n mod 20 is 0</pluralRule> |
|
||||||
</pluralRules> |
|
||||||
</plurals> |
|
||||||
</supplementalData> |
|
@ -0,0 +1,9 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
return array( |
||||||
|
'The dog runs fast.' => 'Der Hund rennt schnell.', |
||||||
|
'His speed is about {n} km/h.' => 'Seine Geschwindigkeit beträgt {n} km/h.', |
||||||
|
'His name is {name} and his speed is about {n, number} km/h.' => 'Er heißt {name} und ist {n, number} km/h schnell.', |
||||||
|
); |
@ -0,0 +1,7 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
return array( |
||||||
|
'The dog runs fast.' => 'Der Hund rennt schell.', |
||||||
|
); |
@ -0,0 +1,85 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yiiunit\framework\i18n; |
||||||
|
|
||||||
|
use yii\base\Model; |
||||||
|
use yii\i18n\I18N; |
||||||
|
use yii\i18n\MessageFormatter; |
||||||
|
use yii\i18n\PhpMessageSource; |
||||||
|
use yiiunit\TestCase; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Carsten Brandt <mail@cebe.cc> |
||||||
|
* @since 2.0 |
||||||
|
* @group i18n |
||||||
|
*/ |
||||||
|
class I18NTest extends TestCase |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var I18N |
||||||
|
*/ |
||||||
|
public $i18n; |
||||||
|
|
||||||
|
protected function setUp() |
||||||
|
{ |
||||||
|
parent::setUp(); |
||||||
|
$this->mockApplication(); |
||||||
|
$this->i18n = new I18N(array( |
||||||
|
'translations' => array( |
||||||
|
'test' => new PhpMessageSource(array( |
||||||
|
'basePath' => '@yiiunit/data/i18n/messages', |
||||||
|
)) |
||||||
|
) |
||||||
|
)); |
||||||
|
} |
||||||
|
|
||||||
|
public function testTranslate() |
||||||
|
{ |
||||||
|
$msg = 'The dog runs fast.'; |
||||||
|
$this->assertEquals('The dog runs fast.', $this->i18n->translate('test', $msg, array(), 'en_US')); |
||||||
|
$this->assertEquals('Der Hund rennt schnell.', $this->i18n->translate('test', $msg, array(), 'de_DE')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testTranslateParams() |
||||||
|
{ |
||||||
|
$msg = 'His speed is about {n} km/h.'; |
||||||
|
$params = array( |
||||||
|
'n' => 42, |
||||||
|
); |
||||||
|
$this->assertEquals('His speed is about 42 km/h.', $this->i18n->translate('test', $msg, $params, 'en_US')); |
||||||
|
$this->assertEquals('Seine Geschwindigkeit beträgt 42 km/h.', $this->i18n->translate('test', $msg, $params, 'de_DE')); |
||||||
|
|
||||||
|
$msg = 'His name is {name} and his speed is about {n, number} km/h.'; |
||||||
|
$params = array( |
||||||
|
'n' => 42, |
||||||
|
'name' => 'DA VINCI', // http://petrix.com/dognames/d.html |
||||||
|
); |
||||||
|
$this->assertEquals('His name is DA VINCI and his speed is about 42 km/h.', $this->i18n->translate('test', $msg, $params, 'en_US')); |
||||||
|
$this->assertEquals('Er heißt DA VINCI und ist 42 km/h schnell.', $this->i18n->translate('test', $msg, $params, 'de_DE')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSpecialParams() |
||||||
|
{ |
||||||
|
$msg = 'His speed is about {0} km/h.'; |
||||||
|
|
||||||
|
$this->assertEquals('His speed is about 0 km/h.', $this->i18n->translate('test', $msg, 0, 'en_US')); |
||||||
|
$this->assertEquals('His speed is about 42 km/h.', $this->i18n->translate('test', $msg, 42, 'en_US')); |
||||||
|
$this->assertEquals('His speed is about {0} km/h.', $this->i18n->translate('test', $msg, null, 'en_US')); |
||||||
|
$this->assertEquals('His speed is about {0} km/h.', $this->i18n->translate('test', $msg, array(), 'en_US')); |
||||||
|
|
||||||
|
$msg = 'His name is {name} and he is {age} years old.'; |
||||||
|
$model = new ParamModel(); |
||||||
|
$this->assertEquals('His name is peer and he is 5 years old.', $this->i18n->translate('test', $msg, $model, 'en_US')); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class ParamModel extends Model |
||||||
|
{ |
||||||
|
public $name = 'peer'; |
||||||
|
public $age = 5; |
||||||
|
} |
@ -0,0 +1,177 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yiiunit\framework\i18n; |
||||||
|
|
||||||
|
use yii\i18n\MessageFormatter; |
||||||
|
use yiiunit\TestCase; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Alexander Makarov <sam@rmcreative.ru> |
||||||
|
* @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'; |
||||||
|
|
||||||
|
protected function setUp() |
||||||
|
{ |
||||||
|
if (!extension_loaded("intl")) { |
||||||
|
$this->markTestSkipped("intl not installed. Skipping."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function patterns() |
||||||
|
{ |
||||||
|
return array( |
||||||
|
array( |
||||||
|
'{'.self::SUBJECT.'} is {'.self::N.', number}', // pattern |
||||||
|
self::SUBJECT_VALUE.' is '.self::N_VALUE, // expected |
||||||
|
array( // params |
||||||
|
self::N => self::N_VALUE, |
||||||
|
self::SUBJECT => self::SUBJECT_VALUE, |
||||||
|
) |
||||||
|
), |
||||||
|
|
||||||
|
// This one was provided by Aura.Intl. Thanks! |
||||||
|
array(<<<_MSG_ |
||||||
|
{gender_of_host, select, |
||||||
|
female {{num_guests, plural, offset:1 |
||||||
|
=0 {{host} does not give a party.} |
||||||
|
=1 {{host} invites {guest} to her party.} |
||||||
|
=2 {{host} invites {guest} and one other person to her party.} |
||||||
|
other {{host} invites {guest} and # other people to her party.}}} |
||||||
|
male {{num_guests, plural, offset:1 |
||||||
|
=0 {{host} does not give a party.} |
||||||
|
=1 {{host} invites {guest} to his party.} |
||||||
|
=2 {{host} invites {guest} and one other person to his party.} |
||||||
|
other {{host} invites {guest} and # other people to his party.}}} |
||||||
|
other {{num_guests, plural, offset:1 |
||||||
|
=0 {{host} does not give a party.} |
||||||
|
=1 {{host} invites {guest} to their party.} |
||||||
|
=2 {{host} invites {guest} and one other person to their party.} |
||||||
|
other {{host} invites {guest} and # other people to their party.}}}} |
||||||
|
_MSG_ |
||||||
|
, |
||||||
|
'ralph invites beep and 3 other people to his party.', |
||||||
|
array( |
||||||
|
'gender_of_host' => 'male', |
||||||
|
'num_guests' => 4, |
||||||
|
'host' => 'ralph', |
||||||
|
'guest' => 'beep' |
||||||
|
) |
||||||
|
), |
||||||
|
|
||||||
|
array( |
||||||
|
'{name} is {gender} and {gender, select, female{she} male{he} other{it}} loves Yii!', |
||||||
|
'Alexander is male and he loves Yii!', |
||||||
|
array( |
||||||
|
'name' => 'Alexander', |
||||||
|
'gender' => 'male', |
||||||
|
), |
||||||
|
), |
||||||
|
|
||||||
|
// verify pattern in select does not get replaced |
||||||
|
array( |
||||||
|
'{name} is {gender} and {gender, select, female{she} male{he} other{it}} loves Yii!', |
||||||
|
'Alexander is male and he loves Yii!', |
||||||
|
array( |
||||||
|
'name' => 'Alexander', |
||||||
|
'gender' => 'male', |
||||||
|
// following should not be replaced |
||||||
|
'he' => 'wtf', |
||||||
|
'she' => 'wtf', |
||||||
|
'it' => 'wtf', |
||||||
|
) |
||||||
|
), |
||||||
|
|
||||||
|
// verify pattern in select message gets replaced |
||||||
|
array( |
||||||
|
'{name} is {gender} and {gender, select, female{she} male{{he}} other{it}} loves Yii!', |
||||||
|
'Alexander is male and wtf loves Yii!', |
||||||
|
array( |
||||||
|
'name' => 'Alexander', |
||||||
|
'gender' => 'male', |
||||||
|
'he' => 'wtf', |
||||||
|
'she' => 'wtf', |
||||||
|
), |
||||||
|
), |
||||||
|
|
||||||
|
// some parser specific verifications |
||||||
|
array( |
||||||
|
'{gender} and {gender, select, female{she} male{{he}} other{it}} loves {nr, number} is {gender}!', |
||||||
|
'male and wtf loves 42 is male!', |
||||||
|
array( |
||||||
|
'nr' => 42, |
||||||
|
'gender' => 'male', |
||||||
|
'he' => 'wtf', |
||||||
|
'she' => 'wtf', |
||||||
|
), |
||||||
|
), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @dataProvider patterns |
||||||
|
*/ |
||||||
|
public function testNamedArgumentsStatic($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); |
||||||
|
$this->assertEquals($expected, $result, $formatter->getErrorMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
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, intl_get_error_message()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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', '')); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function testNoParams() |
||||||
|
{ |
||||||
|
$pattern = '{'.self::SUBJECT.'} is '.self::N; |
||||||
|
$result = MessageFormatter::formatMessage('en_US', $pattern, array()); |
||||||
|
$this->assertEquals($pattern, $result, intl_get_error_message()); |
||||||
|
|
||||||
|
$formatter = new MessageFormatter('en_US', $pattern); |
||||||
|
$result = $formatter->format(array()); |
||||||
|
$this->assertEquals($pattern, $result, $formatter->getErrorMessage()); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue