Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\Translation; Chris@0: Chris@0: /** Chris@0: * Returns the plural rules for a given locale. Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: */ Chris@0: class PluralizationRules Chris@0: { Chris@17: private static $rules = []; Chris@0: Chris@0: /** Chris@0: * Returns the plural position to use for the given locale and number. Chris@0: * Chris@0: * @param int $number The number Chris@0: * @param string $locale The locale Chris@0: * Chris@0: * @return int The plural position Chris@0: */ Chris@0: public static function get($number, $locale) Chris@0: { Chris@0: if ('pt_BR' === $locale) { Chris@0: // temporary set a locale for brazilian Chris@0: $locale = 'xbr'; Chris@0: } Chris@0: Chris@17: if (\strlen($locale) > 3) { Chris@17: $locale = substr($locale, 0, -\strlen(strrchr($locale, '_'))); Chris@0: } Chris@0: Chris@0: if (isset(self::$rules[$locale])) { Chris@17: $return = \call_user_func(self::$rules[$locale], $number); Chris@0: Chris@17: if (!\is_int($return) || $return < 0) { Chris@0: return 0; Chris@0: } Chris@0: Chris@0: return $return; Chris@0: } Chris@0: Chris@0: /* Chris@0: * The plural rules are derived from code of the Zend Framework (2010-09-25), Chris@0: * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). Chris@0: * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) Chris@0: */ Chris@0: switch ($locale) { Chris@0: case 'az': Chris@0: case 'bo': Chris@0: case 'dz': Chris@0: case 'id': Chris@0: case 'ja': Chris@0: case 'jv': Chris@0: case 'ka': Chris@0: case 'km': Chris@0: case 'kn': Chris@0: case 'ko': Chris@0: case 'ms': Chris@0: case 'th': Chris@0: case 'tr': Chris@0: case 'vi': Chris@0: case 'zh': Chris@0: return 0; Chris@0: Chris@0: case 'af': Chris@0: case 'bn': Chris@0: case 'bg': Chris@0: case 'ca': Chris@0: case 'da': Chris@0: case 'de': Chris@0: case 'el': Chris@0: case 'en': Chris@0: case 'eo': Chris@0: case 'es': Chris@0: case 'et': Chris@0: case 'eu': Chris@0: case 'fa': Chris@0: case 'fi': Chris@0: case 'fo': Chris@0: case 'fur': Chris@0: case 'fy': Chris@0: case 'gl': Chris@0: case 'gu': Chris@0: case 'ha': Chris@0: case 'he': Chris@0: case 'hu': Chris@0: case 'is': Chris@0: case 'it': Chris@0: case 'ku': Chris@0: case 'lb': Chris@0: case 'ml': Chris@0: case 'mn': Chris@0: case 'mr': Chris@0: case 'nah': Chris@0: case 'nb': Chris@0: case 'ne': Chris@0: case 'nl': Chris@0: case 'nn': Chris@0: case 'no': Chris@16: case 'oc': Chris@0: case 'om': Chris@0: case 'or': Chris@0: case 'pa': Chris@0: case 'pap': Chris@0: case 'ps': Chris@0: case 'pt': Chris@0: case 'so': Chris@0: case 'sq': Chris@0: case 'sv': Chris@0: case 'sw': Chris@0: case 'ta': Chris@0: case 'te': Chris@0: case 'tk': Chris@0: case 'ur': Chris@0: case 'zu': Chris@14: return (1 == $number) ? 0 : 1; Chris@0: Chris@0: case 'am': Chris@0: case 'bh': Chris@0: case 'fil': Chris@0: case 'fr': Chris@0: case 'gun': Chris@0: case 'hi': Chris@0: case 'hy': Chris@0: case 'ln': Chris@0: case 'mg': Chris@0: case 'nso': Chris@0: case 'xbr': Chris@0: case 'ti': Chris@0: case 'wa': Chris@14: return ((0 == $number) || (1 == $number)) ? 0 : 1; Chris@0: Chris@0: case 'be': Chris@0: case 'bs': Chris@0: case 'hr': Chris@0: case 'ru': Chris@17: case 'sh': Chris@0: case 'sr': Chris@0: case 'uk': Chris@14: return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); Chris@0: Chris@0: case 'cs': Chris@0: case 'sk': Chris@14: return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); Chris@0: Chris@0: case 'ga': Chris@14: return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); Chris@0: Chris@0: case 'lt': Chris@14: return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); Chris@0: Chris@0: case 'sl': Chris@14: return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); Chris@0: Chris@0: case 'mk': Chris@14: return (1 == $number % 10) ? 0 : 1; Chris@0: Chris@0: case 'mt': Chris@14: return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); Chris@0: Chris@0: case 'lv': Chris@14: return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); Chris@0: Chris@0: case 'pl': Chris@14: return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); Chris@0: Chris@0: case 'cy': Chris@14: return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); Chris@0: Chris@0: case 'ro': Chris@14: return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); Chris@0: Chris@0: case 'ar': Chris@14: return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); Chris@0: Chris@0: default: Chris@0: return 0; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Overrides the default plural rule for a given locale. Chris@0: * Chris@0: * @param callable $rule A PHP callable Chris@0: * @param string $locale The locale Chris@0: */ Chris@0: public static function set(callable $rule, $locale) Chris@0: { Chris@0: if ('pt_BR' === $locale) { Chris@0: // temporary set a locale for brazilian Chris@0: $locale = 'xbr'; Chris@0: } Chris@0: Chris@17: if (\strlen($locale) > 3) { Chris@17: $locale = substr($locale, 0, -\strlen(strrchr($locale, '_'))); Chris@0: } Chris@0: Chris@0: self::$rules[$locale] = $rule; Chris@0: } Chris@0: }