search

Home  >  Q&A  >  body text

In PHP, IntCalendar outputs wrong locale.

<p>I have the following code, which I believe is supposed to output fr_FR as the locale, but for some reason it outputs en_US_POSIX (regardless of time zone). What did i do wrong? </p> <pre class="brush:php;toolbar:false;">$loc = IntlCalendar::createInstance(new DateTimeZone('Europe/Paris')); echo $loc->getLocale(Locale::VALID_LOCALE);</pre> <p>Reference links: https://www.php.net/manual/en/intlcalendar.createinstance.php and https://www.php.net/manual/en/intlcalendar.getlocale.php<br /> ;<br />Looks like this isn't the right approach (although the code is valid) - is there a more suitable way to find the "default" locale for a given time zone? </p><p><br /></p>
P粉553428780P粉553428780490 days ago580

reply all(2)I'll reply

  • P粉464088437

    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 ); 

    reply
    0
  • P粉054616867

    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 

    reply
    0
  • Cancelreply