P粉4640884372023-07-29 09:18:13
You set your time zone to that of Paris. But you didn't set the locale. They are different things. The locale defines the language and formatting conventions, while the time zone sets the rules for converting UTC to local time and back again. What you define applies to Americans in Paris. This is a valid use case, especially in August!
Please try the following code:
$loc = IntlCalendar::createInstance( new DateTimeZone( 'Europe/Paris' ), 'fr_FR' );
echo $loc->getLocale( Locale::VALID_LOCALE );
P粉0546168672023-07-29 09:01:21
You can start by getting the associated country (and country code) from a given time zone:
$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 this information with the resources available in the ICU library to get the most likely language for 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); }
Please note that this does not apply to every user. This is a good default starting point, but you should always ask the user for their language preference.
$possibleLocale = getLanguage($countryCode) . '_' . $countryCode; // fr_FR