wp-cldr
  • Package
  • Class

Packages

  • wp-cldr

Classes

  • WP_CLDR
  1 <?php
  2 /**
  3  * WP_CLDR class for fetching localization data from Unicode's Common Locale Data Repository
  4  *
  5  * The wp-cldr plugin is comprised of the WP_CLDR class, a subset of the reference JSON files from Unicode, and unit tests.
  6  *
  7  * @link https://github.com/Automattic/wp-cldr
  8  *
  9  * @package wp-cldr
 10  */
 11 
 12 /**
 13  * Gives WordPress developers easy access to localized country, region, language, currency, and calendar info from the [Unicode Common Locale Data Repository](http://cldr.unicode.org/).
 14  *
 15  * Examples:
 16  *
 17  * The default locale is English:
 18  *
 19  * ```
 20  * $cldr = new WP_CLDR();
 21  * $territories_in_english = $cldr->get_territories();
 22  * ```
 23  *
 24  * You can override the default locale per-call by passing in a language slug in the second parameter:
 25  *
 26  * ```
 27  * $germany_in_arabic = $cldr->get_territory_name( 'DE' , 'ar_AR' );
 28  * ```
 29  *
 30  * Use a convenience parameter during instantiation to change the default locale:
 31  *
 32  * ```
 33  * $cldr = new WP_CLDR( 'fr' );
 34  * $germany_in_french = $cldr->get_territory_name( 'DE' );
 35  * $us_dollar_in_french = $cldr->get_currency_name( 'USD' );
 36  * $canadian_french_in_french = $cldr->get_language_name( 'fr-ca' );
 37  * $canadian_french_in_english = $cldr->get_language_name( 'fr-ca' , 'en' );
 38  * $german_in_german = $cldr->get_language_name( 'de_DE' , 'de-DE' );
 39  * $bengali_in_japanese = $cldr->get_language_name( 'bn_BD' , 'ja_JP' );
 40  * $us_dollar_symbol_in_simplified_chinese = $cldr->get_currency_symbol( 'USD', 'zh' );
 41  * $africa_in_french = $cldr->get_territory_name( '002' );
 42  * ```
 43  *
 44  * Switch locales after the object has been created:
 45  *
 46  * ```
 47  * $cldr->set_locale( 'en' );
 48  * $us_dollar_in_english = $cldr->get_currency_name( 'USD' );
 49  * ```
 50  *
 51  * Testing:
 52  *
 53  * The class includes a suite of PHPUnit tests. To run them, call `phpunit` from the plugin directory.
 54  *
 55  * @link http://cldr.unicode.org
 56  * @link https://github.com/unicode-cldr/cldr-json
 57  *
 58  * @autounit wp-cldr
 59  */
 60 class WP_CLDR {
 61     /**
 62      * The current locale.
 63      *
 64      * @var string
 65      */
 66     private $locale = 'en';
 67 
 68     /**
 69      * The in-memory array of localized values.
 70      *
 71      * @var array
 72      */
 73     private $localized = array();
 74 
 75     /**
 76      * Whether or not to use caching.
 77      *
 78      * @var bool
 79      */
 80     private $use_cache = true;
 81 
 82     /**
 83      * The cache group name to use for the WordPress object cache.
 84      */
 85     const CACHE_GROUP = 'wp-cldr';
 86 
 87     /**
 88      * The CLDR version, which the class uses to determine path to JSON files.
 89      */
 90     const CLDR_VERSION = '29.0.0';
 91 
 92     /**
 93      * Constructs a new instance of the class, including setting defaults for locale and caching.
 94      *
 95      * @param string $locale    Optional. A WordPress locale code.
 96      * @param bool   $use_cache Optional. Whether to use caching (primarily used to suppress caching for unit testing).
 97      */
 98     public function __construct( $locale = 'en', $use_cache = true ) {
 99         $this->use_cache = $use_cache;
100         $this->set_locale( $locale );
101     }
102 
103     /**
104      * Sets the locale.
105      *
106      * @param string $locale A WordPress locale code.
107      */
108     public function set_locale( $locale ) {
109         $this->locale = $locale;
110         $this->initialize_locale_bucket( $locale );
111     }
112 
113     /**
114      * Gets CLDR code for the equivalent WordPress locale code.
115      *
116      * @param string $wp_locale A WordPress locale code.
117      * @return string The equivalent CLDR locale code.
118      */
119     public static function get_cldr_locale( $wp_locale ) {
120 
121         // Some WordPress locales are significantly different from CLDR locales.
122         $wp2cldr = array(
123             'ary' => 'ar-MA',
124             'mya' => 'my',
125             'no' => 'nb',
126             'oci' => 'oc',
127             'tl' => 'fil',
128             'zh-cn' => 'zh-Hans',
129             'zh-hk' => 'zh-Hant',
130             'zh-sg' => 'zh-Hans',
131             'zh-tw' => 'zh-Hant',
132             'zh' => 'zh-Hans',
133         );
134 
135         // Convert underscores to dashes and everything to lowercase.
136         $cleaned_up_wp_locale = '';
137         $cleaned_up_wp_locale = str_replace( '_', '-', $wp_locale );
138         $cleaned_up_wp_locale = strtolower( $cleaned_up_wp_locale );
139 
140         // Check for an exact match in exceptions array.
141         if ( isset( $wp2cldr[ $cleaned_up_wp_locale ] ) ) {
142             return $wp2cldr[ $cleaned_up_wp_locale ];
143         }
144 
145         // Capitalize country code and initial letter of script code to match CLDR JSON file names.
146         $locale_components = explode( '-', $cleaned_up_wp_locale );
147         if ( isset( $locale_components[1] ) && 2 === strlen( $locale_components[1] ) ) {
148             $locale_components[1] = strtoupper( $locale_components[1] );
149             $cleaned_up_wp_locale = implode( '-', $locale_components );
150             return $cleaned_up_wp_locale;
151         }
152         if ( isset( $locale_components[1] ) && 2 < strlen( $locale_components[1] ) ) {
153             $locale_components[1] = ucfirst( $locale_components[1] );
154             $cleaned_up_wp_locale = implode( '-', $locale_components );
155             return $cleaned_up_wp_locale;
156         }
157 
158         return $cleaned_up_wp_locale;
159     }
160 
161     /**
162      * Gets the absolute path of a CLDR JSON file for a given WordPress locale and CLDR data item.
163      *
164      * @param string $cldr_locale A CLDR locale.
165      * @param string $bucket The CLDR data item.
166      * @return string An array with the CLDR data from the file, or an empty array if no match with any CLDR data files.
167      */
168     public static function get_cldr_json_path( $cldr_locale, $bucket ) {
169 
170         $base_path = __DIR__ . '/data/' . WP_CLDR::CLDR_VERSION;
171 
172         switch ( $cldr_locale ) {
173             case 'supplemental':
174                 $relative_path = 'supplemental';
175                 break;
176 
177             default:
178                 $relative_path = "main/$cldr_locale";
179                 break;
180         }
181 
182         return "$base_path/$relative_path/$bucket.json";
183     }
184 
185     /**
186      * Checks to see if there is an installed CLDR JSON file for a given CLDR locale and data item.
187      *
188      * @param string $cldr_locale The CLDR locale.
189      * @param string $bucket The CLDR data item.
190      * @return bool Whether or not the CLDR JSON file is available.
191      */
192     public static function is_cldr_json_available( $cldr_locale, $bucket ) {
193         $cldr_json_file_path = self::get_cldr_json_path( $cldr_locale, $bucket );
194         return is_readable( $cldr_json_file_path );
195     }
196 
197     /**
198      * Loads a CLDR JSON data file.
199      *
200      * @param string $cldr_locale The CLDR locale.
201      * @param string $bucket The CLDR data item.
202      * @return array An array with the CLDR data from the file, or an empty array if no match with any CLDR data files.
203      */
204     public static function get_cldr_json_file( $cldr_locale, $bucket ) {
205         $cldr_json_path = self::get_cldr_json_path( $cldr_locale, $bucket );
206 
207         if ( self::is_cldr_json_available( $cldr_locale, $bucket ) ) {
208             $json_raw = file_get_contents( $cldr_json_path );
209             $json_decoded = json_decode( $json_raw, true );
210             return $json_decoded;
211         }
212 
213         return array();
214     }
215 
216     /**
217      * Uses fallback logic to get the best available CLDR JSON locale for a given WordPress locale.
218      *
219      * @param string $locale A WordPress locale code.
220      * @param string $bucket The CLDR data item.
221      * @return string The best available CLDR JSON locale, or an empty string if no JSON locale is available.
222      */
223     public static function get_best_available_cldr_json_locale( $locale, $bucket ) {
224         $cldr_locale = self::get_cldr_locale( $locale );
225 
226         if ( self::is_cldr_json_available( $cldr_locale, $bucket ) ) {
227             return $cldr_locale;
228         }
229 
230         // If there's no language-country locale CLDR file, try falling back to a language-only CLDR file.
231         $language_only_cldr_locale = strtok( $cldr_locale, '-_' );
232         if ( self::is_cldr_json_available( $language_only_cldr_locale, $bucket ) ) {
233             return $language_only_cldr_locale;
234         }
235 
236         return '';
237     }
238 
239     /**
240      * Initializes a "bucket" of CLDR data items for a WordPress locale.
241      *
242      * @param string $locale Optional. The locale.
243      * @param string $bucket Optional. The CLDR data item.
244      * @return bool Whether or not the locale bucket was successfully initialized.
245      */
246     private function initialize_locale_bucket( $locale, $bucket = 'territories' ) {
247 
248         $cache_key = "cldr-$locale-$bucket";
249 
250         if ( $this->use_cache ) {
251             $cached_data = wp_cache_get( $cache_key, WP_CLDR::CACHE_GROUP );
252             if ( false !== $cached_data ) {
253                 $this->localized[ $locale ][ $bucket ] = $cached_data;
254                 return true;
255             }
256         }
257 
258         $cldr_locale = self::get_best_available_cldr_json_locale( $locale, $bucket );
259 
260         if ( empty( $cldr_locale ) ) {
261             return false;
262         }
263 
264         $json_file = self::get_cldr_json_file( $cldr_locale, $bucket );
265 
266         // Do some performance-enhancing pre-processing of data items, then put into cache
267         // organized by WordPress $locale instead of $cldr_locale (which isn't visible
268         // outside this method).
269         switch ( $bucket ) {
270             case 'territories':
271             case 'languages':
272                 $sorted_array = $json_file['main'][ $cldr_locale ]['localeDisplayNames'][ $bucket ];
273                 if ( function_exists( 'collator_create' ) ) {
274                     // Sort data according to locale collation rules.
275                     $coll = collator_create( $cldr_locale );
276                     collator_asort( $coll, $sorted_array, Collator::SORT_STRING );
277                 } else {
278                     asort( $sorted_array );
279                 }
280                 $this->localized[ $locale ][ $bucket ] = $sorted_array;
281                 break;
282 
283             case 'currencies':
284                 $this->localized[ $locale ][ $bucket ] = $json_file['main'][ $cldr_locale ]['numbers'][ $bucket ];
285                 break;
286 
287             case 'timeZoneNames':
288                 $this->localized[ $locale ][ $bucket ] = $json_file['main'][ $cldr_locale ]['dates'][ $bucket ];
289                 break;
290 
291             default:
292                 $this->localized[ $locale ][ $bucket ] = $json_file;
293                 break;
294         }
295 
296         if ( $this->use_cache ) {
297             wp_cache_set( $cache_key, $this->localized[ $locale ][ $bucket ], WP_CLDR::CACHE_GROUP );
298         }
299 
300         return true;
301     }
302 
303     /**
304      * Flushes the WordPress object cache for a single CLDR data item for a single locale.
305      *
306      * @param string $locale A WordPress locale code.
307      * @param string $bucket A CLDR data item.
308      */
309     public function flush_wp_cache_for_locale_bucket( $locale, $bucket ) {
310         $cache_key = "cldr-$locale-$bucket";
311         return wp_cache_delete( $cache_key, WP_CLDR::CACHE_GROUP );
312     }
313 
314     /**
315      * Clears the WordPress object cache for all CLDR data items across all locales.
316      */
317     public function flush_all_wp_caches() {
318         $this->localized = array();
319 
320         $locales = $this->get_languages();
321         $supported_buckets = array( 'territories', 'currencies', 'languages', 'weekData', 'telephoneCodeData' );
322         foreach ( array_keys( $locales ) as $locale ) {
323             foreach ( $supported_buckets as $bucket ) {
324                 $this->flush_wp_cache_for_locale_bucket( $locale, $bucket );
325             }
326         }
327     }
328 
329     /**
330      * Returns a bucket of CLDR data for a locale.
331      *
332      * @param string $locale A WordPress locale code.
333      * @param string $bucket A CLDR data item.
334      * @return array An associative array with the contents of the locale bucket.
335      */
336     private function get_locale_bucket( $locale, $bucket ) {
337         if ( empty( $locale ) ) {
338             $locale = $this->locale;
339         }
340 
341         // Check the in-memory array.
342         if ( isset( $this->localized[ $locale ][ $bucket ] ) ) {
343             return $this->localized[ $locale ][ $bucket ];
344         }
345 
346         // If it's not in memory, initialize the locale bucket which loads the in-memory array.
347         if ( $this->initialize_locale_bucket( $locale, $bucket ) ) {
348             return $this->localized[ $locale ][ $bucket ];
349         }
350 
351         // If the locale bucket cannot be initialized, fall back to English.
352         if ( isset( $this->localized['en'][ $bucket ] ) ) {
353             return $this->localized['en'][ $bucket ];
354         }
355         if ( $this->initialize_locale_bucket( 'en', $bucket ) ) {
356             return $this->localized['en'][ $bucket ];
357         }
358 
359         // Since everything else failed, return an empty array.
360         return array();
361     }
362 
363     /**
364      * Gets a localized country or region name.
365      *
366      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
367      * @link http://unstats.un.org/unsd/methods/m49/m49regin.htm UN M.49 region codes
368      *
369      * @param string $territory_code An ISO 3166-1 country code, or a UN M.49 region code.
370      * @param string $locale         Optional. A WordPress locale code.
371      * @return string The name of the territory in the provided locale.
372      */
373     public function get_territory_name( $territory_code, $locale = '' ) {
374         $territories_array = $this->get_territories( $locale );
375         if ( isset( $territories_array[ $territory_code ] ) ) {
376             return $territories_array[ $territory_code ];
377         }
378         return '';
379     }
380 
381     /**
382      * Gets a localized currency symbol.
383      *
384      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
385      *
386      * @param string $currency_code An ISO 4217 currency code.
387      * @param string $locale        Optional. A WordPress locale code.
388      * @return string The symbol for the currency in the provided locale.
389      */
390     public function get_currency_symbol( $currency_code, $locale = '' ) {
391         $currencies_array = $this->get_locale_bucket( $locale, 'currencies' );
392         if ( isset( $currencies_array[ $currency_code ]['symbol'] ) ) {
393             return $currencies_array[ $currency_code ]['symbol'];
394         }
395         return '';
396     }
397 
398     /**
399      * Gets a localized currency name.
400      *
401      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
402      *
403      * @param string $currency_code An ISO 4217 currency code.
404      * @param string $locale        Optional. A WordPress locale code.
405      * @return string The name of the currency in the provided locale.
406      */
407     public function get_currency_name( $currency_code, $locale = '' ) {
408         $currencies_array = $this->get_locale_bucket( $locale, 'currencies' );
409         if ( isset( $currencies_array[ $currency_code ]['displayName'] ) ) {
410             return $currencies_array[ $currency_code ]['displayName'];
411         }
412         return '';
413     }
414 
415     /**
416      * Gets a localized language name.
417      *
418      * @link http://www.iso.org/iso/language_codes ISO 639 language codes
419      *
420      * @param string $language_code An ISO 639 language code.
421      * @param string $locale        Optional. A WordPress locale code.
422      * @return string The name of the language in the provided locale.
423      */
424     public function get_language_name( $language_code, $locale = '' ) {
425         $languages = $this->get_languages( $locale );
426 
427         $cldr_matched_language_code = self::get_cldr_locale( $language_code );
428         if ( isset( $languages[ $cldr_matched_language_code ] ) ) {
429             return $languages[ $cldr_matched_language_code ];
430         }
431 
432         // If no match for a full language code (e.g. `en-NZ`), check for language code only (e.g. `en`).
433         $language_only_cldr_code = strtok( $cldr_matched_language_code, '-_' );
434         if ( isset( $languages[ $language_only_cldr_code ] ) ) {
435             return $languages[ $language_only_cldr_code ];
436         }
437 
438         return '';
439     }
440 
441     /**
442      * Gets all country and region names in a locale.
443      *
444      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
445      * @link http://unstats.un.org/unsd/methods/m49/m49regin.htm UN M.49 region codes
446      *
447      * @param string $locale Optional. A WordPress locale code.
448      * @return array An associative array of ISO 3166-1 alpha-2 country codes and UN M.49 region codes, along with localized names, from CLDR
449      */
450     public function get_territories( $locale = '' ) {
451         return $this->get_locale_bucket( $locale, 'territories' );
452     }
453 
454     /**
455      * Gets all language names in a locale.
456      *
457      * @link http://www.iso.org/iso/language_codes ISO 639 language codes
458      *
459      * @param string $locale Optional. A WordPress locale code.
460      * @return array An associative array of ISO 639 codes and localized language names from CLDR
461      */
462     public function get_languages( $locale = '' ) {
463         return $this->get_locale_bucket( $locale, 'languages' );
464     }
465 
466     /**
467      * Gets telephone code for a country.
468      *
469      * @link http://unicode.org/reports/tr35/tr35-info.html#Telephone_Code_Data CLDR Telephone Code Data
470      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
471      *
472      * @param string $country_code A two-letter ISO 3166 country code.
473      * @return string The telephone code for the provided country.
474      */
475     public function get_telephone_code( $country_code ) {
476         $json_file = $this->get_locale_bucket( 'supplemental', 'telephoneCodeData' );
477         if ( isset( $json_file['supplemental']['telephoneCodeData'][ $country_code ][0]['telephoneCountryCode'] ) ) {
478             return $json_file['supplemental']['telephoneCodeData'][ $country_code ][0]['telephoneCountryCode'];
479         }
480         return '';
481     }
482 
483     /**
484      * Gets the day which typically starts a calendar week in a country.
485      *
486      * @link http://unicode.org/reports/tr35/tr35-dates.html#Week_Data CLDR week data
487      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
488      *
489      * @param string $country_code A two-letter ISO 3166 country code.
490      * @return string The first three characters, in lowercase, of the English name for the day considered to be the start of the week.
491      */
492     public function get_first_day_of_week( $country_code ) {
493         $json_file = $this->get_locale_bucket( 'supplemental', 'weekData' );
494         if ( isset( $json_file['supplemental']['weekData']['firstDay'][ $country_code ] ) ) {
495             return $json_file['supplemental']['weekData']['firstDay'][ $country_code ];
496         }
497         return '';
498     }
499 
500     /**
501      * Gets the currency used in each country worldwide.
502      *
503      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
504      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
505      *
506      * @return array An associative array of ISO 3166 country codes and the ISO 4217 code for the currency currently used in each country.
507      */
508     public function get_currency_for_all_countries() {
509         $json_file = $this->get_locale_bucket( 'supplemental', 'currencyData' );
510 
511         // This CLDR item has a history of all the currencies ever used in a country
512         // so we need to loop through them to find one without a `_to` ending date
513         // and without a `_tender` flag which are always false indicating
514         // the currency wasn't legal tender.
515         $result = array();
516         if ( isset( $json_file['supplemental']['currencyData']['region'] ) ) {
517             foreach ( $json_file['supplemental']['currencyData']['region'] as $country_code => $currencies ) {
518                 foreach ( $currencies as $currency_dates ) {
519                     if ( ! array_key_exists( '_to', current( $currency_dates ) ) && ! array_key_exists( '_tender', current( $currency_dates ) ) ) {
520                         $result[ $country_code ] = key( $currency_dates );
521                     }
522                 }
523             }
524         }
525         return $result;
526     }
527 
528     /**
529      * Gets the currency currently used in a country.
530      *
531      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
532      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
533      *
534      * @param string $country_code A two-letter ISO 3166-1 country code.
535      * @return string The three-letter ISO 4217 code for the currency currently used in that country.
536      */
537     public function get_currency_for_country( $country_code ) {
538         $currency_for_all_countries = $this->get_currency_for_all_countries();
539         if ( isset( $currency_for_all_countries[ $country_code ] ) ) {
540             return $currency_for_all_countries[ $country_code ];
541         }
542         return '';
543     }
544 
545     /**
546      * Gets the countries that use each currency in use today.
547      *
548      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
549      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
550      *
551      * @return array An associative array of ISO 4217 currency codes and then an array of the ISO 3166 codes for countries which currently each currency.
552      */
553     public function get_countries_for_all_currencies() {
554         $result = array();
555         $currency_for_all_countries = $this->get_currency_for_all_countries();
556         if ( isset( $currency_for_all_countries ) ) {
557             foreach ( $currency_for_all_countries as $country_code => $currency_code ) {
558                 $result[ $currency_code ][] = $country_code;
559             }
560         }
561         return $result;
562     }
563 
564     /**
565      * Gets the countries that use a particular currency.
566      *
567      * @link http://www.iso.org/iso/currency_codes ISO 4217 currency codes
568      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
569      *
570      * @param string $currency_code A three-letter ISO 4217 currency code.
571      * @return array The ISO 3166 codes for the countries which currently the currency.
572      */
573     public function get_countries_for_currency( $currency_code ) {
574         $countries_for_all_currencies = $this->get_countries_for_all_currencies();
575         if ( isset( $countries_for_all_currencies[ $currency_code ] ) ) {
576             return $countries_for_all_currencies[ $currency_code ];
577         }
578         return array();
579     }
580 
581     /**
582      * Gets the countries contained by a region code.
583      *
584      * @link http://www.unicode.org/cldr/charts/latest/supplemental/territory_containment_un_m_49.html CLDR info page on territory containment
585      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
586      * @link http://unstats.un.org/unsd/methods/m49/m49regin.htm UN M.49 region codes
587      *
588      * @param string $region_code A UN M.49 region code or a two-letter ISO 3166-1 country code.
589      * @return array The countries included in that region, or the country if $region_code is a country.
590      */
591     public function get_territories_contained( $region_code ) {
592 
593         // If $region_code is a country code, return it.
594         if ( preg_match( '/^[A-Z]{2}$/', $region_code ) ) {
595             return array( $region_code );
596         }
597 
598         // If it's a region code, recursively find the contained country codes.
599         $result = array();
600         if ( preg_match( '/^\d{3}$/', $region_code ) ) {
601             $json_file = $this->get_locale_bucket( 'supplemental', 'territoryContainment' );
602             if ( isset( $json_file['supplemental']['territoryContainment'][ $region_code ]['_contains'] ) ) {
603                 foreach ( $json_file['supplemental']['territoryContainment'][ $region_code ]['_contains'] as $contained_region ) {
604                     $result = array_merge( $result, $this->get_territories_contained( $contained_region ) );
605                 }
606             }
607         }
608 
609         return $result;
610     }
611 
612     /**
613      * Gets the languages spoken in a country, in descending order of use.
614      *
615      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
616      * @link http://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html Detail on CLDR language information
617      *
618      * @param string $country_code A two-letter ISO 3166-1 country code.
619      * @return array An associative array with the key of a language code and the value of the percentage of population which speaks the language in that country.
620      */
621     public function get_languages_spoken( $country_code ) {
622         $json_file = $this->get_locale_bucket( 'supplemental', 'territoryInfo' );
623         $result = array();
624         if ( isset( $json_file['supplemental']['territoryInfo'][ $country_code ]['languagePopulation'] ) ) {
625             foreach ( $json_file['supplemental']['territoryInfo'][ $country_code ]['languagePopulation'] as $language => $info ) {
626                 $result[ $language ] = $info['_populationPercent'];
627             }
628             arsort( $result );
629         }
630         return $result;
631     }
632 
633     /**
634      * Gets the most widely spoken language spoken in a country.
635      *
636      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
637      * @link http://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html Detail on CLDR language information
638      * @link http://www.iso.org/iso/language_codes ISO 639 language codes
639      *
640      * @param string $country_code A two-letter ISO 3166-1 country code.
641      * @return string The ISO 639 code for the language most widely spoken in the country.
642      */
643     public function get_most_spoken_language( $country_code ) {
644         $languages_spoken = $this->get_languages_spoken( $country_code );
645         if ( ! empty( $languages_spoken ) ) {
646             return key( $languages_spoken );
647         }
648         return '';
649     }
650 
651     /**
652      * Gets GDP, population, and language information for a country.
653      *
654      * @link http://www.iso.org/iso/country_codes ISO 3166 country codes
655      * @link http://www.unicode.org/cldr/charts/latest/supplemental/territory_language_information.html CLDR's territory information
656      *
657      * @param string $country_code Optional. A two-letter ISO 3166-1 country code.
658      * @return array CLDR's territory information.
659      */
660     public function get_territory_info( $country_code ) {
661         $json_file = $this->get_locale_bucket( 'supplemental', 'territoryInfo' );
662         if ( isset( $json_file['supplemental']['territoryInfo'][ $country_code ] ) ) {
663             return $json_file['supplemental']['territoryInfo'][ $country_code ];
664         }
665         return array();
666     }
667 
668     /**
669      * Recursively builds an associative array of the time zone IDs and their localized display names.
670      *
671      * @link http://www.iana.org/time-zones IANA time zone
672      * @link http://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Names CLDR info on time zone names
673      *
674      * @param string $zones An array of time zone data from CLDR JSON files.
675      * @param string $id_start Optional. The start of the time zone ID (used for recursive calls).
676      * @return array An associative array of time zone IDs (e.g. `Europe/Istanbul`) and the localized exemplar city names.
677      */
678     private function build_cities_array( $zones, $id_start = '' ) {
679         $result = array();
680         foreach ( $zones as $id => $array ) {
681             if ( isset( $array['exemplarCity'] ) ) {
682                 $result[ $id_start . $id ] = $array['exemplarCity'];
683             } elseif ( is_array( $array ) ) {
684                 $result = array_merge( $result, $this->build_cities_array( $array, $id_start . $id . '/' ) );
685             }
686         }
687         return $result;
688     }
689 
690     /**
691      * Gets the time zone city names -- aka exemplars -- for a locale.
692      *
693      * @link http://www.iana.org/time-zones IANA time zone
694      * @link http://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Names CLDR info on time zone names
695      *
696      * @param string $locale Optional. A WordPress locale code.
697      * @return array As associative array of time zone IDs (e.g. `Europe/Istanbul`) and the localized exemplar city for each.
698      */
699     public function get_time_zone_cities( $locale = '' ) {
700         $time_zone_cities_json = $this->get_locale_bucket( $locale, 'timeZoneNames' );
701         if ( ! empty( $time_zone_cities_json['zone'] ) ) {
702             return $this->build_cities_array( $time_zone_cities_json['zone'] );
703         }
704         return array();
705     }
706 
707     /**
708      * Gets the time zone city name -- aka exemplar -- for a time zone ID.
709      *
710      * @link http://www.iana.org/time-zones IANA time zone
711      * @link http://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Names CLDR info on time zone names
712      *
713      * @param string $time_zone_id An IANA time zone ID (e.g. `Europe/Istanbul`).
714      * @param string $locale Optional. A WordPress locale code.
715      * @return string The localized name of the time zone exemplar city.
716      */
717     public function get_time_zone_city( $time_zone_id, $locale = '' ) {
718         $time_zone_cities = $this->get_time_zone_cities( $locale );
719         if ( ! empty( $time_zone_cities[ $time_zone_id ] ) ) {
720             return $time_zone_cities[ $time_zone_id ];
721         }
722         return '';
723     }
724 }
725 
wp-cldr API documentation generated by ApiGen