I have the following code which I believe should output fr_FR
as the locale but for some reason is outputting en_US_POSIX
(it does this on any timezone). What have I done wrong?
$loc = IntlCalendar::createInstance(new DateTimeZone('Europe/Paris'));
echo $loc->getLocale(Locale::VALID_LOCALE);
For refs: https://www.php.net/manual/en/intlcalendar.createinstance.php and https://www.php.net/manual/en/intlcalendar.getlocale.php
As it appears this isn't the correct way (even though the code is valid) - is there a more suitable way to find a "default" locale for a given timezone?
You can start by getting the country (and country code) associated with a given timezone:
$userTimezone = new DateTimeZone('Europe/Paris');
$location = $userTimezone->getLocation();
/*
array(4) {
["country_code"]=> string(2) "FR"
["latitude"]=> float(48.866659999999996)
["longitude"]=> float(2.3333299999999895)
["comments"]=> string(0) ""
}
*/
$countryCode = $location['country_code'];
You can then combine that information with the resources available in the ICU library to get the most-likely language of a given country code:
// From @ausi's answer in https://stackoverflow.com/a/58512299/1456201
function getLanguage(string $country): string {
$subtags = \ResourceBundle::create('likelySubtags', 'ICUDATA', false);
$country = \Locale::canonicalize('und_'.$country);
$locale = $subtags->get($country) ?: $subtags->get('und');
return \Locale::getPrimaryLanguage($locale);
}
Note that that will not be correct for every user. It's a decent default starting place, but you should always ask the user what their language preference is.
$possibleLocale = getLanguage($countryCode) . '_' . $countryCode; // fr_FR