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