Normalize languages for negotiation to lowercase

refs #7818
This commit is contained in:
Eric Lippmann 2015-08-31 16:45:14 +02:00
parent 38ef8c7f11
commit 4a5d2784fb

View File

@ -201,7 +201,7 @@ class Translator
{ {
$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;
} }
} }