7 * Figure out which of $langs is the closest to $lang.
9 * @param string $preferredLang
10 * The user's preferred language.
11 * Ex: `en`, `fr`, or `fr_CA`.
12 * @param array $availLangs
13 * List of available languages.
14 * Ex: ['en_US' => 'English (US)', 'fr_CA' => 'French (Canadian)'].
15 * @param string $default
16 * The locale to use if none other can be determined.
21 public static function pickClosest($preferredLang, $availLangs, $default = 'en_US') {
22 // Perhaps we have this exact language?
23 if (isset($availLangs[$preferredLang])) {
24 return $preferredLang;
27 list ($first) = explode('_', $preferredLang);
29 // Do we have a hard-coded preference? Use this for real oddballs.
33 if (isset($overrides[$preferredLang]) && isset($availLangs[$overrides[$preferredLang]])) {
34 return $overrides[$preferredLang];
37 // Perhaps we have the canonical variant (e.g. `fr` => `fr_FR`)?
38 $canon = $first . '_' . strtoupper($first);
39 if (isset($availLangs[$canon])) {
43 // Is there anything else that looks remotely close? (e.g. `cy` => `cy_GB`)
45 foreach ($availLangs as $availLang => $availLabel) {
46 if (strpos($availLang, $first) === 0) {