From 224b22a051051f6c2e494c3a2fb4adb42898e2d1 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Tue, 14 Jan 2014 19:24:18 +0100 Subject: Update to MediaWiki 1.22.1 --- languages/Language.php | 41 +++-- languages/classes/LanguageBe_tarask.php | 44 ----- languages/classes/LanguageGv.php | 55 ------ languages/classes/LanguageHr.php | 56 ------- languages/classes/LanguageKsh.php | 4 + languages/classes/LanguageRu.php | 57 +------ languages/classes/LanguageSr.php | 46 +---- languages/classes/LanguageSr_ec.php | 54 ------ languages/classes/LanguageSr_el.php | 54 ------ languages/classes/LanguageUk.php | 35 ---- languages/data/plurals-mediawiki.xml | 54 +++--- languages/data/plurals.xml | 251 ++++++++++++++++++---------- languages/messages/MessagesEn.php | 8 + languages/messages/MessagesQqq.php | 15 ++ languages/utils/CLDRPluralRuleEvaluator.php | 139 ++++++++++++--- 15 files changed, 380 insertions(+), 533 deletions(-) delete mode 100644 languages/classes/LanguageGv.php delete mode 100644 languages/classes/LanguageHr.php delete mode 100644 languages/classes/LanguageSr_ec.php delete mode 100644 languages/classes/LanguageSr_el.php (limited to 'languages') diff --git a/languages/Language.php b/languages/Language.php index c24dc180..11d91036 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -3633,17 +3633,10 @@ class Language { */ function convertPlural( $count, $forms ) { // Handle explicit n=pluralform cases - foreach ( $forms as $index => $form ) { - if ( preg_match( '/^\d+=/i', $form ) ) { - $pos = strpos( $form, '=' ); - if ( substr( $form, 0, $pos ) === (string)$count ) { - return substr( $form, $pos + 1 ); - } - unset( $forms[$index] ); - } + $forms = $this->handleExplicitPluralForms( $count, $forms ); + if ( is_string( $forms ) ) { + return $forms; } - - $forms = array_values( $forms ); if ( !count( $forms ) ) { return ''; } @@ -3653,6 +3646,34 @@ class Language { return $forms[$pluralForm]; } + /** + * Handles explicit plural forms for Language::convertPlural() + * + * In {{PLURAL:$1|0=nothing|one|many}}, 0=nothing will be returned if $1 equals zero. + * If an explicitly defined plural form matches the $count, then + * string value returned, otherwise array returned for further consideration + * by CLDR rules or overridden convertPlural(). + * + * @since 1.22.1 + * + * @param int $count non-localized number + * @param array $forms different plural forms + * + * @return array|string + */ + protected function handleExplicitPluralForms( $count, array $forms ) { + foreach ( $forms as $index => $form ) { + if ( preg_match( '/\d+=/i', $form ) ) { + $pos = strpos( $form, '=' ); + if ( substr( $form, 0, $pos ) === (string) $count ) { + return substr( $form, $pos + 1 ); + } + unset( $forms[$index] ); + } + } + return array_values( $forms ); + } + /** * Checks that convertPlural was given an array and pads it to requested * amount of forms by copying the last one. diff --git a/languages/classes/LanguageBe_tarask.php b/languages/classes/LanguageBe_tarask.php index 6497b50c..05b9550f 100644 --- a/languages/classes/LanguageBe_tarask.php +++ b/languages/classes/LanguageBe_tarask.php @@ -31,50 +31,6 @@ * @see http://be-x-old.wikipedia.org/wiki/Project_talk:LanguageBe_tarask.php */ class LanguageBe_tarask extends Language { - /** - * Plural form transformations - * - * $wordform1 - singular form (for 1, 21, 31, 41...) - * $wordform2 - plural form (for 2, 3, 4, 22, 23, 24, 32, 33, 34...) - * $wordform3 - plural form (for 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26...) - */ - - /** - * @param $count int - * @param $forms array - * - * @return string - */ - function convertPlural( $count, $forms ) { - if ( !count( $forms ) ) { - return ''; - } - - // If the actual number is not mentioned in the expression, then just two forms are enough: - // singular for $count == 1 - // plural for $count != 1 - // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}." - if ( count( $forms ) === 2 ) { - return $count == 1 ? $forms[0] : $forms[1]; - } - - // @todo FIXME: CLDR defines 4 plural forms instead of 3 - // http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - $forms = $this->preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } - /** * The Belarusian language uses apostrophe sign, * but the characters used for this could be both U+0027 and U+2019. diff --git a/languages/classes/LanguageGv.php b/languages/classes/LanguageGv.php deleted file mode 100644 index ba8a53ce..00000000 --- a/languages/classes/LanguageGv.php +++ /dev/null @@ -1,55 +0,0 @@ -preConvertPlural( $forms, 4 ); - - if ( $count > 0 && ( $count % 20 ) === 0 ) { - return $forms[0]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[1]; - case 2: return $forms[2]; - default: return $forms[3]; - } - } - } - -} diff --git a/languages/classes/LanguageHr.php b/languages/classes/LanguageHr.php deleted file mode 100644 index 910bc100..00000000 --- a/languages/classes/LanguageHr.php +++ /dev/null @@ -1,56 +0,0 @@ -preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } -} diff --git a/languages/classes/LanguageKsh.php b/languages/classes/LanguageKsh.php index 09c57279..d25ce714 100644 --- a/languages/classes/LanguageKsh.php +++ b/languages/classes/LanguageKsh.php @@ -189,6 +189,10 @@ class LanguageKsh extends Language { * @return string */ function convertPlural( $count, $forms ) { + $forms = $this->handleExplicitPluralForms( $count, $forms ); + if ( is_string( $forms ) ) { + return $forms; + } if ( !count( $forms ) ) { return ''; } diff --git a/languages/classes/LanguageRu.php b/languages/classes/LanguageRu.php index 11b42cf9..d3ac1d22 100644 --- a/languages/classes/LanguageRu.php +++ b/languages/classes/LanguageRu.php @@ -44,8 +44,9 @@ class LanguageRu extends Language { return $wgGrammarForms['ru'][$case][$word]; } - # These rules are not perfect, but they are currently only used for Wikimedia site names so it doesn't - # matter if they are wrong sometimes. Just add a special case for your site name if necessary. + # These rules are not perfect, but they are currently only used for Wikimedia + # site names so it doesn't matter if they are wrong sometimes. + # Just add a special case for your site name if necessary. # substr doesn't support Unicode and mb_substr has issues, # so break it to characters using preg_match_all and then use array_slice and join @@ -102,58 +103,6 @@ class LanguageRu extends Language { return $word; } - /** - * Plural form transformations - * - * $forms[0] - singular form (for 1, 21, 31, 41...) - * $forms[1] - paucal form (for 2, 3, 4, 22, 23, 24, 32, 33, 34...) - * $forms[2] - plural form (for 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26...) - * - * Examples: - * message with number - * "Сделано $1 {{PLURAL:$1|изменение|изменения|изменений}}" - * ("$1 change[s] were made) - * message without number - * "Действие не может быть выполнено по {{PLURAL:$1|следующей причине|следующим причинам}}:" - * ("The action cannot be performed for the following reason[s]") - * @param $count int - * @param $forms array - * - * @return string - */ - function convertPlural( $count, $forms ) { - if ( !count( $forms ) ) { - return ''; - } - - // If the actual number is not mentioned in the expression, then just two forms are enough: - // singular for $count === 1 - // plural for $count !== 1 - // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}." - if ( count( $forms ) === 2 ) { - return $count === 1 ? $forms[0] : $forms[1]; - } - - // @todo FIXME: CLDR defines 4 plural forms. Form with decimals missing. - // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru - $forms = $this->preConvertPlural( $forms, 3 ); - - if ( $count > 10 && (int)floor( ( $count % 100 ) / 10 ) === 1 ) { - return $forms[2]; - } - - switch ( $count % 10 ) { - case 1: - return $forms[0]; - case 2: - case 3: - case 4: - return $forms[1]; - default: - return $forms[2]; - } - } - /** * Four-digit number should be without group commas (spaces) * See manual of style at http://ru.wikipedia.org/wiki/Википедия:Оформление_статей diff --git a/languages/classes/LanguageSr.php b/languages/classes/LanguageSr.php index 6f0ff4b5..76cd8229 100644 --- a/languages/classes/LanguageSr.php +++ b/languages/classes/LanguageSr.php @@ -22,8 +22,6 @@ */ require_once __DIR__ . '/../LanguageConverter.php'; -require_once __DIR__ . '/LanguageSr_ec.php'; -require_once __DIR__ . '/LanguageSr_el.php'; /** * There are two levels of conversion for Serbian: the script level @@ -166,14 +164,16 @@ class SrConverter extends LanguageConverter { // regexp for roman numbers $roman = 'M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})'; - $reg = '/^' . $roman . '$|^' . $roman . $breaks . '|' . $breaks . $roman . '$|' . $breaks . $roman . $breaks . '/'; + $reg = '/^' . $roman . '$|^' . $roman . $breaks . '|' . $breaks + . $roman . '$|' . $breaks . $roman . $breaks . '/'; $matches = preg_split( $reg, $text, -1, PREG_SPLIT_OFFSET_CAPTURE ); $m = array_shift( $matches ); $this->loadTables(); if ( !isset( $this->mTables[$toVariant] ) ) { - throw new MWException( "Broken variant table: " . implode( ',', array_keys( $this->mTables ) ) ); + throw new MWException( "Broken variant table: " + . implode( ',', array_keys( $this->mTables ) ) ); } $ret = $this->mTables[$toVariant]->replace( $m[0] ); $mstart = $m[1] + strlen( $m[0] ); @@ -218,7 +218,7 @@ class SrConverter extends LanguageConverter { * * @ingroup Language */ -class LanguageSr extends LanguageSr_ec { +class LanguageSr extends Language { function __construct() { global $wgHooks; @@ -238,40 +238,4 @@ class LanguageSr extends LanguageSr_ec { $this->mConverter = new SrConverter( $this, 'sr', $variants, $variantfallbacks, $flags ); $wgHooks['PageContentSaveComplete'][] = $this->mConverter; } - - /** - * @param $count int - * @param $forms array - * - * @return string - */ - function convertPlural( $count, $forms ) { - if ( !count( $forms ) ) { - return ''; - } - - // If the actual number is not mentioned in the expression, then just two forms are enough: - // singular for $count == 1 - // plural for $count != 1 - // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}." - if ( count( $forms ) === 2 ) { - return $count == 1 ? $forms[0] : $forms[1]; - } - - // @todo FIXME: CLDR defines 4 plural forms. Form with decimals missing. - // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#ru - $forms = $this->preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } } diff --git a/languages/classes/LanguageSr_ec.php b/languages/classes/LanguageSr_ec.php deleted file mode 100644 index cb9e8191..00000000 --- a/languages/classes/LanguageSr_ec.php +++ /dev/null @@ -1,54 +0,0 @@ -preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } -} diff --git a/languages/classes/LanguageSr_el.php b/languages/classes/LanguageSr_el.php deleted file mode 100644 index 99d12935..00000000 --- a/languages/classes/LanguageSr_el.php +++ /dev/null @@ -1,54 +0,0 @@ -preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } -} diff --git a/languages/classes/LanguageUk.php b/languages/classes/LanguageUk.php index 4ad272ba..08041a92 100644 --- a/languages/classes/LanguageUk.php +++ b/languages/classes/LanguageUk.php @@ -86,41 +86,6 @@ class LanguageUk extends Language { return $word; } - /** - * @param $count int - * @param $forms array - * @return string - */ - function convertPlural( $count, $forms ) { - if ( !count( $forms ) ) { - return ''; - } - - // If the actual number is not mentioned in the expression, then just two forms are enough: - // singular for $count == 1 - // plural for $count != 1 - // For example, "This user belongs to {{PLURAL:$1|one group|several groups}}." - if ( count( $forms ) === 2 ) { - return $count == 1 ? $forms[0] : $forms[1]; - } - - // @todo FIXME: CLDR defines 4 plural forms. Form for decimals is missing/ - // See http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html#uk - $forms = $this->preConvertPlural( $forms, 3 ); - - if ( $count > 10 && floor( ( $count % 100 ) / 10 ) == 1 ) { - return $forms[2]; - } else { - switch ( $count % 10 ) { - case 1: return $forms[0]; - case 2: - case 3: - case 4: return $forms[1]; - default: return $forms[2]; - } - } - } - /** * Ukrainian numeric format is "12 345,67" but "1234,56" * diff --git a/languages/data/plurals-mediawiki.xml b/languages/data/plurals-mediawiki.xml index 70d45a3c..aafc393b 100644 --- a/languages/data/plurals-mediawiki.xml +++ b/languages/data/plurals-mediawiki.xml @@ -2,42 +2,44 @@ - - - n is 1 - n is 2 - n is not 0 AND n is not 10 AND n mod 10 is 0 - + - n mod 100 is 1 - n mod 100 is 2 - n mod 100 in 3..4 + n % 100 = 1 @integer 1, 101, 201, 301, … + n % 100 = 2 @integer 2, 102, 202, 302, … + n % 100 = 3..4 @integer 3~4, 103~104, … + @integer 5, 6, 7, 8, 9, 10, 105, 206, 307, … - + + - 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 % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, … + n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, … + n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, … + - n mod 10 is 1 - n mod 10 is 2 - n mod 10 in 3..4 + n % 10 = 1 @integer 1, 11, 21, 31, … + n % 10 = 2 @integer 2, 12, 22, 32, … + n % 10 = 3..4 @integer 3~4, 13~14, 23~24, … + @integer 5, 6, 7, 8, 9, 10, 15, 105, 206, 307, … - n in 0..1 + n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + - n mod 10 is 1 and n mod 100 is not 11 - n mod 10 is 2 and n mod 100 is not 12 - n is 0 or n mod 100 is 0 or n mod 100 in 10..19 + n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, … + n % 10 = 2 and n % 100 != 12 @integer 2, 22, 32, 42, 52, 62, 72, 82, 92, 102, 122, … + n = 0 or n % 100 = 0 or n % 100 = 10..19 @integer 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 100, 111,112, … + @integer 3, 4, 5, 6, 7, 8, 9, 20, 103, 104, … + + + v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, … + v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, … + @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … diff --git a/languages/data/plurals.xml b/languages/data/plurals.xml index d5a1cfe2..fd4eaf6b 100644 --- a/languages/data/plurals.xml +++ b/languages/data/plurals.xml @@ -1,119 +1,200 @@ + - - - + + + + - - 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 is 2 - n is not 0 AND n mod 10 is 0 - - - n is 1 - - - n in 0..1 - - - n within 0..2 and n is not 2 + n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000 + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000 + n % 100 = 3..10 @integer 3~10, 103~110, 1003, … @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 103.0, 1003.0, … + n % 100 = 11..99 @integer 11~26, 111, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, … + @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 1 and v = 0 @integer 1 + i = 2 and v = 0 @integer 2 + v = 0 and n != 0..10 and n % 10 = 0 @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, … + @integer 0, 3~17, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 0,1 @integer 0, 1 @decimal 0.0~1.5 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - n is 0 - n mod 10 is 1 and n mod 100 is not 11 + n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19 @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.0, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, … + @integer 2~9, 22~29, 102, 1002, … @decimal 0.2~0.9, 1.2~1.9, 10.2, 100.2, 1000.2, … - 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 = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000 + @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000 + n = 3..6 @integer 3~6 @decimal 3.0, 4.0, 5.0, 6.0, 3.00, 4.00, 5.00, 6.00, 3.000, 4.000, 5.000, 6.000, 3.0000, 4.0000, 5.0000, 6.0000 + n = 7..10 @integer 7~10 @decimal 7.0, 8.0, 9.0, 10.0, 7.00, 8.00, 9.00, 10.00, 7.000, 8.000, 9.000, 10.000, 7.0000, 8.0000, 9.0000, 10.0000 + @integer 0, 11~25, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 1 and v = 0 @integer 1 + v != 0 or n = 0 or n != 1 and n % 100 = 1..19 @integer 0, 2~16, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @integer 20~35, 100, 1000, 10000, 100000, 1000000, … - 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 % 10 = 1 and n % 100 != 11..19 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, … + n % 10 = 2..9 and n % 100 != 11..19 @integer 2~9, 22~29, 102, 1002, … @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 22.0, 102.0, 1002.0, … + f != 0 @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, … + @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - - 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 % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, … + n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, … + n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, … - n is 1 - n in 2..4 + i = 1 and v = 0 @integer 1 + i = 2..4 and v = 0 @integer 2~4 + v != 0 @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … - 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 - - + i = 1 and v = 0 @integer 1 + v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … + v = 0 and i != 1 and i % 10 = 0..1 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 12..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … + @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - 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 + v = 0 and i % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, … + v = 0 and i % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, … + v = 0 and i % 100 = 3..4 or v != 0 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … + + + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + n = 0 or n % 100 = 2..10 @integer 0, 2~10, 102~107, 1002, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 102.0, 1002.0, … + n % 100 = 11..19 @integer 11~19, 111~117, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, … + @integer 20~35, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + v = 0 and i % 10 = 1 or f % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, … + @integer 0, 2~10, 12~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.0, 1.2~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000 + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000 + n = 3 @integer 3 @decimal 3.0, 3.00, 3.000, 3.0000 + n = 6 @integer 6 @decimal 6.0, 6.00, 6.000, 6.0000 + @integer 4, 5, 7~20, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - n is 0 - n within 0..2 and n is not 0 and n is not 2 + n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000 + i = 0,1 and n != 0 @integer 1 @decimal 0.1~1.6 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - n within 0..1 - n in 2..10 + i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04 + n = 2..10 @integer 2~10 @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00 + @integer 11~26, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~1.9, 2.1~2.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - - 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 is not 0 and n mod 1000000 is 0 + + n % 10 = 1 and n % 100 != 11,71,91 @integer 1, 21, 31, 41, 51, 61, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 81.0, 101.0, 1001.0, … + n % 10 = 2 and n % 100 != 12,72,92 @integer 2, 22, 32, 42, 52, 62, 82, 102, 1002, … @decimal 2.0, 22.0, 32.0, 42.0, 52.0, 62.0, 82.0, 102.0, 1002.0, … + n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99 @integer 3, 4, 9, 23, 24, 29, 33, 34, 39, 43, 44, 49, 103, 1003, … @decimal 3.0, 4.0, 9.0, 23.0, 24.0, 29.0, 33.0, 34.0, 103.0, 1003.0, … + n != 0 and n % 1000000 = 0 @integer 1000000, … @decimal 1000000.0, 1000000.00, 1000000.000, … + @integer 0, 5~8, 10~20, 100, 1000, 10000, 100000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, … - n is 0 - n is 1 + n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000 + n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - n in 0..1 or n in 11..99 + n = 0..1 or n = 11..99 @integer 0, 1, 11~24 @decimal 0.0, 1.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0 + @integer 2~10, 100~106, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … - n mod 10 in 1..2 or n mod 20 is 0 + n % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 1.0, 11.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 101.0, 1001.0, … + n % 10 = 2 @integer 2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, … @decimal 2.0, 12.0, 22.0, 32.0, 42.0, 52.0, 62.0, 72.0, 102.0, 1002.0, … + n % 100 = 0,20,40,60 @integer 0, 20, 40, 60, 100, 120, 140, 160, 1000, 10000, 100000, 1000000, … @decimal 0.0, 20.0, 40.0, 60.0, 100.0, 120.0, 140.0, 160.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + @integer 3~10, 13~19, 23, 103, 1003, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.1, 1000.1, … - n in 1,11 - n in 2,12 - n in 3..10,13..19 + n = 1,11 @integer 1, 11 @decimal 1.0, 11.0, 1.00, 11.00, 1.000, 11.000, 1.0000 + n = 2,12 @integer 2, 12 @decimal 2.0, 12.0, 2.00, 12.00, 2.000, 12.000, 2.0000 + n = 3..10,13..19 @integer 3~10, 13~19 @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 3.00 + @integer 0, 20~34, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 0..1 and v = 0 @integer 0, 1 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 1 and v = 0 @integer 1 + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 1 and v = 0 or i = 0 and t = 1 @integer 1 @decimal 0.1, 0.01, 0.10, 0.001, 0.010, 0.100, 0.0001, 0.0010, 0.0100, 0.1000 + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 1 or t != 0 and i = 0,1 @integer 1 @decimal 0.1~1.6 + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0~3.4, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 1 and v = 0 @integer 1 + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1~1.6, 10.1, 100.1, 1000.1, … + @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + n = 0,1 or i = 0 and f = 1 @integer 0, 1 @decimal 0.0, 0.1, 1.0, 0.00, 0.01, 1.00, 0.000, 0.001, 1.000, 0.0000, 0.0001, 1.0000 + @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.2~0.9, 1.1~1.8, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, … + v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, … + @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + v = 0 and i % 10 = 1 and i % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … + v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … + @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … + + + v = 0 and i % 10 = 1 and i % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … + v = 0 and i % 10 = 2..4 and i % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … + v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … + @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, … diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index ffbc88ab..dca9779d 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2352,6 +2352,7 @@ You should check that file's deletion history before proceeding to re-upload it. 'php-uploaddisabledtext' => 'File uploads are disabled in PHP. Please check the file_uploads setting.', 'uploadscripted' => 'This file contains HTML or script code that may be erroneously interpreted by a web browser.', +'uploadinvalidxml' => 'The XML in the uploaded file could not be parsed.', 'uploadvirus' => 'The file contains a virus! Details: $1', 'uploadjava' => 'The file is a ZIP file that contains a Java .class file. @@ -4857,6 +4858,13 @@ You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU Gen 'version-software' => 'Installed software', 'version-software-product' => 'Product', 'version-software-version' => 'Version', +'version-db-mysql-url' => 'http://www.mysql.com/', # do not translate or duplicate this message to other languages +'version-db-mariadb-url' => 'http://mariadb.org/', # do not translate or duplicate this message to other languages +'version-db-percona-url' => 'http://www.percona.com/software/percona-server', # do not translate or duplicate this message to other languages +'version-db-postgres-url' => 'http://www.postgresql.org/', # do not translate or duplicate this message to other languages +'version-db-oracle-url' => 'http://www.oracle.com/database/', # do not translate or duplicate this message to other languages +'version-db-sqlite-url' => 'http://www.sqlite.org/', # do not translate or duplicate this message to other languages +'version-db-mssql-url' => 'http://www.microsoft.com/sql/', # do not translate or duplicate this message to other languages 'version-entrypoints' => 'Entry point URLs', 'version-entrypoints-header-entrypoint' => 'Entry point', 'version-entrypoints-header-url' => 'URL', diff --git a/languages/messages/MessagesQqq.php b/languages/messages/MessagesQqq.php index cdb8a914..e770db61 100644 --- a/languages/messages/MessagesQqq.php +++ b/languages/messages/MessagesQqq.php @@ -4064,6 +4064,7 @@ See also: * {{msg-mw|zip-wrong-format}} * {{msg-mw|uploadjava}} * {{msg-mw|uploadvirus}}', +'uploadinvalidxml' => 'Error message displayed when the uploaded file contains XML that cannot be properly parsed and checked.', 'uploadvirus' => 'Error message displayed when uploaded file contains a virus. Parameters: @@ -9922,6 +9923,20 @@ Used at the end of {{msg-mw|version-poweredby-credits}} on [[Special:Version]].' This message is followed by the list of installed software (MediaWiki, PHP and MySQL).', 'version-software-product' => 'Shown in [[Special:Version]]', 'version-software-version' => '{{Identical|Version}}', +'version-db-mysql-url' => '{{notranslate}} +URL of the website for [[wikipedia:MySQL|MySQL]].', +'version-db-mariadb-url' => '{{notranslate}} +URL of the website for [[wikipedia:MariaDB|MariaDB]].', +'version-db-percona-url' => '{{notranslate}} +URL of the website for Percona Server.', +'version-db-postgres-url' => '{{notranslate}} +URL of the website for [[wikipedia:PostgreSQL|PostgreSQL]].', +'version-db-oracle-url' => '{{notranslate}} +URL of the website for [[wikipedia:Oracle Database|Oracle Database]].', +'version-db-sqlite-url' => '{{notranslate}} +URL of the website for [[wikipedia:SQLite|SQLite]].', +'version-db-mssql-url' => '{{notranslate}} +URL of the website for [[wikipedia:Microsoft SQL Server|Microsoft SQL Server]].', 'version-entrypoints' => 'Header on [[Special:Version]] above a table that lists the URLs of various entry points in this MediaWiki installation. Entry points are the "places" where the wiki\'s content and information can be accessed in various ways, for instance the standard index.php which shows normal pages, histories etc.', 'version-entrypoints-header-entrypoint' => 'Header for the first column in the entry points table on [[Special:Version]]. See also {{msg-mw|Version-entrypoints}}', diff --git a/languages/utils/CLDRPluralRuleEvaluator.php b/languages/utils/CLDRPluralRuleEvaluator.php index d3a863b4..afe88a5b 100644 --- a/languages/utils/CLDRPluralRuleEvaluator.php +++ b/languages/utils/CLDRPluralRuleEvaluator.php @@ -2,7 +2,8 @@ /** * Parse and evaluate a plural rule. * - * http://unicode.org/reports/tr35/#Language_Plural_Rules + * UTS #35 Revision 33 + * http://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Language_Plural_Rules * * @author Niklas Laxstrom, Tim Starling * @@ -63,8 +64,42 @@ class CLDRPluralRuleEvaluator { /** * Evaluate a compiled set of rules returned by compile(). Do not allow * the user to edit the compiled form, or else PHP errors may result. + * + * @param string The number to be evaluated against the rules, in English, or it + * may be a type convertible to string. + * @param array The associative array of plural rules in pluralform => rule format. + * @return int The index of the plural form which passed the evaluation */ public static function evaluateCompiled( $number, array $rules ) { + // Calculate the values of the operand symbols + $number = strval( $number ); + if ( !preg_match( '/^ -? ( ([0-9]+) (?: \. ([0-9]+) )? )$/x', $number, $m ) ) { + wfDebug( __METHOD__.': invalid number input, returning "other"' ); + return count( $rules ); + } + if ( !isset( $m[3] ) ) { + $operandSymbols = array( + 'n' => intval( $m[1] ), + 'i' => intval( $m[1] ), + 'v' => 0, + 'w' => 0, + 'f' => 0, + 't' => 0 + ); + } else { + $absValStr = $m[1]; + $intStr = $m[2]; + $fracStr = $m[3]; + $operandSymbols = array( + 'n' => floatval( $absValStr ), + 'i' => intval( $intStr ), + 'v' => strlen( $fracStr ), + 'w' => strlen( rtrim( $fracStr, '0' ) ), + 'f' => intval( $fracStr ), + 't' => intval( rtrim( $fracStr, '0' ) ), + ); + } + // The compiled form is RPN, with tokens strictly delimited by // spaces, so this is a simple RPN evaluator. foreach ( $rules as $i => $rule ) { @@ -73,8 +108,8 @@ class CLDRPluralRuleEvaluator { $nine = ord( '9' ); foreach ( StringUtils::explode( ' ', $rule ) as $token ) { $ord = ord( $token ); - if ( $token === 'n' ) { - $stack[] = $number; + if ( isset( $operandSymbols[$token] ) ) { + $stack[] = $operandSymbols[$token]; } elseif ( $ord >= $zero && $ord <= $nine ) { $stack[] = intval( $token ); } else { @@ -88,8 +123,8 @@ class CLDRPluralRuleEvaluator { return $i; } } - // None of the provided rules match. The number belongs to caregory - // 'other' which comes last. + // None of the provided rules match. The number belongs to category + // 'other', which comes last. return count( $rules ); } @@ -227,8 +262,39 @@ class CLDRPluralRuleEvaluator_Range { * Helper class for converting rules to reverse polish notation (RPN). */ class CLDRPluralRuleConverter { - public $rule, $pos, $end; + /** + * The input string + * + * @var string + */ + public $rule; + + /** + * The current position + * + * @var int + */ + public $pos; + + /** + * The past-the-end position + * + * @var int + */ + public $end; + + /** + * The operator stack + * + * @var array + */ public $operators = array(); + + /** + * The operand stack + * + * @var array + */ public $operands = array(); /** @@ -257,14 +323,19 @@ class CLDRPluralRuleConverter { /** * Same for digits. Note that the grammar given in UTS #35 doesn't allow - * negative numbers or decimals. + * negative numbers or decimal separators. */ const NUMBER_CLASS = '0123456789'; + /** + * A character list of symbolic operands. + */ + const OPERAND_SYMBOLS = 'nivwft'; + /** * An anchored regular expression which matches a word at the current offset. */ - const WORD_REGEX = '/[a-zA-Z]+/A'; + const WORD_REGEX = '/[a-zA-Z@]+/A'; /** * Convert a rule to RPN. This is the only public entry point. @@ -365,17 +436,19 @@ class CLDRPluralRuleConverter { return $token; } - // Comma - if ( $this->rule[$this->pos] === ',' ) { - $token = $this->newOperator( ',', $this->pos, 1 ); - $this->pos ++; + // Two-character operators + $op2 = substr( $this->rule, $this->pos, 2 ); + if ( $op2 === '..' || $op2 === '!=' ) { + $token = $this->newOperator( $op2, $this->pos, 2 ); + $this->pos += 2; return $token; } - // Dot dot - if ( substr( $this->rule, $this->pos, 2 ) === '..' ) { - $token = $this->newOperator( '..', $this->pos, 2 ); - $this->pos += 2; + // Single-character operators + $op1 = $this->rule[$this->pos]; + if ( $op1 === ',' || $op1 === '=' || $op1 === '%' ) { + $token = $this->newOperator( $op1, $this->pos, 1 ); + $this->pos ++; return $token; } @@ -414,13 +487,21 @@ class CLDRPluralRuleConverter { return $token; } - // The special numerical keyword "n" - if ( $word1 === 'n' ) { - $token = $this->newNumber( 'n', $this->pos ); + // The single-character operand symbols + if ( strpos( self::OPERAND_SYMBOLS, $word1 ) !== false ) { + $token = $this->newNumber( $word1, $this->pos ); $this->pos ++; return $token; } + // Samples + if ( $word1 === '@integer' || $word1 === '@decimal' ) { + // Samples are like comments, they have no effect on rule evaluation. + // They run from the first sample indicator to the end of the string. + $this->pos = $this->end; + return false; + } + $this->error( 'unrecognised word' ); } @@ -551,8 +632,28 @@ class CLDRPluralRuleConverter_Operator extends CLDRPluralRuleConverter_Fragment 'r' => 'range', ); + /** + * Map for converting the new operators introduced in Rev 33 to the old forms + */ + static $aliasMap = array( + '%' => 'mod', + '!=' => 'not-in', + '=' => 'in' + ); + + /** + * Initialize a new instance of a CLDRPluralRuleConverter_Operator object + * + * @param CLDRPluralRuleConverter $parser The parser + * @param string $name The operator name + * @param int $pos The position + * @param int $pos The length + */ function __construct( $parser, $name, $pos, $length ) { parent::__construct( $parser, $pos, $length ); + if ( isset( self::$aliasMap[$name] ) ) { + $name = self::$aliasMap[$name]; + } $this->name = $name; } -- cgit v1.2.2