Merge branch 'bugfix/language-negotiation-safari-7818'

fixes #7818
This commit is contained in:
Eric Lippmann 2015-08-31 16:46:32 +02:00
commit e78f833232

View File

@ -195,13 +195,13 @@ class Translator
* *
* @param string $locale The locale code to split, or null to split the current locale * @param string $locale The locale code to split, or null to split the current locale
* *
* @return stdClass An object with a 'language' and 'country' attribute * @return object An object with a 'language' and 'country' attribute
*/ */
public static function splitLocaleCode($locale = null) public static function splitLocaleCode($locale = null)
{ {
$matches = array(); $matches = array();
$locale = $locale !== null ? $locale : setlocale(LC_ALL, 0); $locale = $locale !== null ? $locale : setlocale(LC_ALL, 0);
if (preg_match('@([a-z]{2})[_-]([A-Z]{2})@', $locale, $matches)) { if (preg_match('@([a-z]{2})[_-]([a-z]{2})@i', $locale, $matches)) {
list($languageCode, $countryCode) = array_slice($matches, 1); list($languageCode, $countryCode) = array_slice($matches, 1);
} elseif ($locale === 'C') { } elseif ($locale === 'C') {
list($languageCode, $countryCode) = preg_split('@[_-]@', static::DEFAULT_LOCALE, 2); list($languageCode, $countryCode) = preg_split('@[_-]@', static::DEFAULT_LOCALE, 2);
@ -272,36 +272,40 @@ class Translator
} }
$requestedLocales[] = str_replace('-', '_', $headerValue); $requestedLocales[] = str_replace('-', '_', $headerValue);
} }
$requestedLocales = array_combine(
array_map('strtolower', array_values($requestedLocales)),
array_values($requestedLocales)
);
$availableLocales = static::getAvailableLocaleCodes();
$availableLocales = array_combine(
array_map('strtolower', array_values($availableLocales)),
array_values($availableLocales)
);
$similarMatch = null; $similarMatch = null;
$availableLocales = static::getAvailableLocaleCodes();
$perfectMatch = array_shift((array_intersect($requestedLocales, $availableLocales))); foreach ($requestedLocales as $requestedLocaleLowered => $requestedLocale) {
foreach ($requestedLocales as $requestedLocale) { $localeObj = static::splitLocaleCode($requestedLocaleLowered);
if ($perfectMatch === $requestedLocale) {
// The perfect match must be preferred when reached before a similar match is found if (isset($availableLocales[$requestedLocaleLowered])
return $perfectMatch; && (! $similarMatch || static::splitLocaleCode($similarMatch)->language === $localeObj->language)
) {
// Prefer perfect match only if no similar match has been found yet or the perfect match is more precise
// than the similar match
return $availableLocales[$requestedLocaleLowered];
} }
$similarMatches = array();
$localeObj = static::splitLocaleCode($requestedLocale); if (! $similarMatch) {
foreach ($availableLocales as $availableLocale) { foreach ($availableLocales as $availableLocaleLowered => $availableLocale) {
if (static::splitLocaleCode($availableLocale)->language === $localeObj->language) { if (static::splitLocaleCode($availableLocaleLowered)->language === $localeObj->language) {
$similarMatches[] = $availableLocale; $similarMatch = $availableLocaleLowered;
break;
}
} }
} }
if (!empty($similarMatches)) {
$similarMatch = array_shift($similarMatches); // There is no "best" similar match, just use the first
break;
}
} }
if (!$perfectMatch && $similarMatch) { return $similarMatch ? $availableLocales[$similarMatch] : static::DEFAULT_LOCALE;
return $similarMatch;
} elseif ($similarMatch && static::splitLocaleCode($similarMatch)->language === static::splitLocaleCode($perfectMatch)->language) {
return $perfectMatch;
} elseif ($similarMatch) {
return $similarMatch;
}
return static::DEFAULT_LOCALE;
} }
} }