123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- <?php
-
- namespace Illuminate\Translation;
-
- use Illuminate\Support\Str;
-
- class MessageSelector
- {
- /**
- * Select a proper translation string based on the given number.
- *
- * @param string $line
- * @param int $number
- * @param string $locale
- * @return mixed
- */
- public function choose($line, $number, $locale)
- {
- $segments = explode('|', $line);
-
- if (($value = $this->extract($segments, $number)) !== null) {
- return trim($value);
- }
-
- $segments = $this->stripConditions($segments);
-
- $pluralIndex = $this->getPluralIndex($locale, $number);
-
- if (count($segments) == 1 || ! isset($segments[$pluralIndex])) {
- return $segments[0];
- }
-
- return $segments[$pluralIndex];
- }
-
- /**
- * Extract a translation string using inline conditions.
- *
- * @param array $segments
- * @param int $number
- * @return mixed
- */
- private function extract($segments, $number)
- {
- foreach ($segments as $part) {
- if (! is_null($line = $this->extractFromString($part, $number))) {
- return $line;
- }
- }
- }
-
- /**
- * Get the translation string if the condition matches.
- *
- * @param string $part
- * @param int $number
- * @return mixed
- */
- private function extractFromString($part, $number)
- {
- preg_match('/^[\{\[]([^\[\]\{\}]*)[\}\]](.*)/s', $part, $matches);
-
- if (count($matches) !== 3) {
- return;
- }
-
- $condition = $matches[1];
-
- $value = $matches[2];
-
- if (Str::contains($condition, ',')) {
- list($from, $to) = explode(',', $condition, 2);
-
- if ($to == '*' && $number >= $from) {
- return $value;
- } elseif ($from == '*' && $number <= $to) {
- return $value;
- } elseif ($number >= $from && $number <= $to) {
- return $value;
- }
- }
-
- return $condition == $number ? $value : null;
- }
-
- /**
- * Strip the inline conditions from each segment, just leaving the text.
- *
- * @param array $segments
- * @return array
- */
- private function stripConditions($segments)
- {
- return collect($segments)->map(function ($part) {
- return preg_replace('/^[\{\[]([^\[\]\{\}]*)[\}\]]/', '', $part);
- })->all();
- }
-
- /**
- * Get the index to use for pluralization.
- *
- * 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)
- *
- * @param string $locale
- * @param int $number
- * @return int
- */
- public function getPluralIndex($locale, $number)
- {
- switch ($locale) {
- case 'az':
- case 'az_AZ':
- case 'bo':
- case 'bo_CN':
- case 'bo_IN':
- case 'dz':
- case 'dz_BT':
- case 'id':
- case 'id_ID':
- case 'ja':
- case 'ja_JP':
- case 'jv':
- case 'ka':
- case 'ka_GE':
- case 'km':
- case 'km_KH':
- case 'kn':
- case 'kn_IN':
- case 'ko':
- case 'ko_KR':
- case 'ms':
- case 'ms_MY':
- case 'th':
- case 'th_TH':
- case 'tr':
- case 'tr_CY':
- case 'tr_TR':
- case 'vi':
- case 'vi_VN':
- case 'zh':
- case 'zh_CN':
- case 'zh_HK':
- case 'zh_SG':
- case 'zh_TW':
- return 0;
- case 'af':
- case 'af_ZA':
- case 'bn':
- case 'bn_BD':
- case 'bn_IN':
- case 'bg':
- case 'bg_BG':
- case 'ca':
- case 'ca_AD':
- case 'ca_ES':
- case 'ca_FR':
- case 'ca_IT':
- case 'da':
- case 'da_DK':
- case 'de':
- case 'de_AT':
- case 'de_BE':
- case 'de_CH':
- case 'de_DE':
- case 'de_LI':
- case 'de_LU':
- case 'el':
- case 'el_CY':
- case 'el_GR':
- case 'en':
- case 'en_AG':
- case 'en_AU':
- case 'en_BW':
- case 'en_CA':
- case 'en_DK':
- case 'en_GB':
- case 'en_HK':
- case 'en_IE':
- case 'en_IN':
- case 'en_NG':
- case 'en_NZ':
- case 'en_PH':
- case 'en_SG':
- case 'en_US':
- case 'en_ZA':
- case 'en_ZM':
- case 'en_ZW':
- case 'eo':
- case 'eo_US':
- case 'es':
- case 'es_AR':
- case 'es_BO':
- case 'es_CL':
- case 'es_CO':
- case 'es_CR':
- case 'es_CU':
- case 'es_DO':
- case 'es_EC':
- case 'es_ES':
- case 'es_GT':
- case 'es_HN':
- case 'es_MX':
- case 'es_NI':
- case 'es_PA':
- case 'es_PE':
- case 'es_PR':
- case 'es_PY':
- case 'es_SV':
- case 'es_US':
- case 'es_UY':
- case 'es_VE':
- case 'et':
- case 'et_EE':
- case 'eu':
- case 'eu_ES':
- case 'eu_FR':
- case 'fa':
- case 'fa_IR':
- case 'fi':
- case 'fi_FI':
- case 'fo':
- case 'fo_FO':
- case 'fur':
- case 'fur_IT':
- case 'fy':
- case 'fy_DE':
- case 'fy_NL':
- case 'gl':
- case 'gl_ES':
- case 'gu':
- case 'gu_IN':
- case 'ha':
- case 'ha_NG':
- case 'he':
- case 'he_IL':
- case 'hu':
- case 'hu_HU':
- case 'is':
- case 'is_IS':
- case 'it':
- case 'it_CH':
- case 'it_IT':
- case 'ku':
- case 'ku_TR':
- case 'lb':
- case 'lb_LU':
- case 'ml':
- case 'ml_IN':
- case 'mn':
- case 'mn_MN':
- case 'mr':
- case 'mr_IN':
- case 'nah':
- case 'nb':
- case 'nb_NO':
- case 'ne':
- case 'ne_NP':
- case 'nl':
- case 'nl_AW':
- case 'nl_BE':
- case 'nl_NL':
- case 'nn':
- case 'nn_NO':
- case 'no':
- case 'om':
- case 'om_ET':
- case 'om_KE':
- case 'or':
- case 'or_IN':
- case 'pa':
- case 'pa_IN':
- case 'pa_PK':
- case 'pap':
- case 'pap_AN':
- case 'pap_AW':
- case 'pap_CW':
- case 'ps':
- case 'ps_AF':
- case 'pt':
- case 'pt_BR':
- case 'pt_PT':
- case 'so':
- case 'so_DJ':
- case 'so_ET':
- case 'so_KE':
- case 'so_SO':
- case 'sq':
- case 'sq_AL':
- case 'sq_MK':
- case 'sv':
- case 'sv_FI':
- case 'sv_SE':
- case 'sw':
- case 'sw_KE':
- case 'sw_TZ':
- case 'ta':
- case 'ta_IN':
- case 'ta_LK':
- case 'te':
- case 'te_IN':
- case 'tk':
- case 'tk_TM':
- case 'ur':
- case 'ur_IN':
- case 'ur_PK':
- case 'zu':
- case 'zu_ZA':
- return ($number == 1) ? 0 : 1;
- case 'am':
- case 'am_ET':
- case 'bh':
- case 'fil':
- case 'fil_PH':
- case 'fr':
- case 'fr_BE':
- case 'fr_CA':
- case 'fr_CH':
- case 'fr_FR':
- case 'fr_LU':
- case 'gun':
- case 'hi':
- case 'hi_IN':
- case 'hy':
- case 'hy_AM':
- case 'ln':
- case 'ln_CD':
- case 'mg':
- case 'mg_MG':
- case 'nso':
- case 'nso_ZA':
- case 'ti':
- case 'ti_ER':
- case 'ti_ET':
- case 'wa':
- case 'wa_BE':
- case 'xbr':
- return (($number == 0) || ($number == 1)) ? 0 : 1;
- case 'be':
- case 'be_BY':
- case 'bs':
- case 'bs_BA':
- case 'hr':
- case 'hr_HR':
- case 'ru':
- case 'ru_RU':
- case 'ru_UA':
- case 'sr':
- case 'sr_ME':
- case 'sr_RS':
- case 'uk':
- case 'uk_UA':
- 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 'cs_CZ':
- case 'sk':
- case 'sk_SK':
- return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);
- case 'ga':
- case 'ga_IE':
- return ($number == 1) ? 0 : (($number == 2) ? 1 : 2);
- case 'lt':
- case 'lt_LT':
- return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
- case 'sl':
- case 'sl_SI':
- return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3));
- case 'mk':
- case 'mk_MK':
- return ($number % 10 == 1) ? 0 : 1;
- case 'mt':
- case 'mt_MT':
- return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));
- case 'lv':
- case 'lv_LV':
- return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2);
- case 'pl':
- case 'pl_PL':
- return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);
- case 'cy':
- case 'cy_GB':
- return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3));
- case 'ro':
- case 'ro_RO':
- return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);
- case 'ar':
- case 'ar_AE':
- case 'ar_BH':
- case 'ar_DZ':
- case 'ar_EG':
- case 'ar_IN':
- case 'ar_IQ':
- case 'ar_JO':
- case 'ar_KW':
- case 'ar_LB':
- case 'ar_LY':
- case 'ar_MA':
- case 'ar_OM':
- case 'ar_QA':
- case 'ar_SA':
- case 'ar_SD':
- case 'ar_SS':
- case 'ar_SY':
- case 'ar_TN':
- case 'ar_YE':
- 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;
- }
- }
- }
|