2015-08-18 00:00:26 +00: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 ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Translation\Exception\InvalidArgumentException ;
2015-08-18 00:00:26 +00:00
/**
* MessageSelector .
*
* @ author Fabien Potencier < fabien @ symfony . com >
* @ author Bernhard Schussek < bschussek @ gmail . com >
*/
class MessageSelector
{
/**
* Given a message with different plural translations separated by a
* pipe ( | ), this method returns the correct portion of the message based
* on the given number , locale and the pluralization rules in the message
* itself .
*
* The message supports two different types of pluralization rules :
*
* interval : { 0 } There are no apples | { 1 } There is one apple | ] 1 , Inf ] There are % count % apples
* indexed : There is one apple | There are % count % apples
*
* The indexed solution can also contain labels ( e . g . one : There is one apple ) .
* This is purely for making the translations more clear - it does not
* affect the functionality .
*
* The two methods can also be mixed :
* { 0 } There are no apples | one : There is one apple | more : There are % count % apples
*
* @ param string $message The message being translated
* @ param int $number The number of items represented for the message
* @ param string $locale The locale to use for choosing
*
* @ return string
*
2018-11-23 12:29:20 +00:00
* @ throws InvalidArgumentException
2015-08-18 00:00:26 +00:00
*/
public function choose ( $message , $number , $locale )
{
2018-11-23 12:29:20 +00:00
$parts = array ();
if ( preg_match ( '/^\|++$/' , $message )) {
$parts = explode ( '|' , $message );
} elseif ( preg_match_all ( '/(?:\|\||[^\|])++/' , $message , $matches )) {
$parts = $matches [ 0 ];
}
2015-08-18 00:00:26 +00:00
$explicitRules = array ();
$standardRules = array ();
foreach ( $parts as $part ) {
2018-11-23 12:29:20 +00:00
$part = trim ( str_replace ( '||' , '|' , $part ));
2015-08-18 00:00:26 +00:00
2015-08-27 19:03:05 +00:00
if ( preg_match ( '/^(?P<interval>' . Interval :: getIntervalRegexp () . ')\s*(?P<message>.*?)$/xs' , $part , $matches )) {
2015-08-18 00:00:26 +00:00
$explicitRules [ $matches [ 'interval' ]] = $matches [ 'message' ];
} elseif ( preg_match ( '/^\w+\:\s*(.*?)$/' , $part , $matches )) {
$standardRules [] = $matches [ 1 ];
} else {
$standardRules [] = $part ;
}
}
// try to match an explicit rule, then fallback to the standard ones
foreach ( $explicitRules as $interval => $m ) {
if ( Interval :: test ( $number , $interval )) {
return $m ;
}
}
$position = PluralizationRules :: get ( $number , $locale );
if ( ! isset ( $standardRules [ $position ])) {
// when there's exactly one rule given, and that rule is a standard
// rule, use this rule
2018-11-23 12:29:20 +00:00
if ( 1 === \count ( $parts ) && isset ( $standardRules [ 0 ])) {
2015-08-18 00:00:26 +00:00
return $standardRules [ 0 ];
}
2018-11-23 12:29:20 +00:00
throw new InvalidArgumentException ( sprintf ( 'Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").' , $message , $locale , $number ));
2015-08-18 00:00:26 +00:00
}
return $standardRules [ $position ];
}
}