Textpattern | PHP Cross Reference | Content Management Systems |
Description: Handles locales.
1 <?php 2 3 /* 4 * Textpattern Content Management System 5 * http://textpattern.com 6 * 7 * Copyright (C) 2016 The Textpattern Development Team 8 * 9 * This file is part of Textpattern. 10 * 11 * Textpattern is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation, version 2. 14 * 15 * Textpattern is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with Textpattern. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 /** 25 * Handles locales. 26 * 27 * <code> 28 * echo Txp::get('Textpattern\L10n\Locale')->setLocale(LC_ALL, 'da-dk')->getLocale(); 29 * </code> 30 * 31 * @since 4.6.0 32 * @package L10n 33 */ 34 35 namespace Textpattern\L10n; 36 37 class Locale 38 { 39 /** 40 * An array of locale identifiers. 41 * 42 * @var array 43 */ 44 45 protected $locales = array( 46 'ar-dz' => array('ar_DZ.UTF-8', 'ar_DZ', 'ara', 'ar', 'arabic', 'ar_DZ.ISO_8859-6', 'Arabic_Saudi Arabia.1256'), 47 'bg-bg' => array('bg_BG.UTF-8', 'bg_BG', 'bg', 'bul', 'bulgarian', 'bg_BG.ISO_8859-5', 'Bulgarian_Bulgaria.1251'), 48 'bs-ba' => array('bs_BA.UTF-8', 'bs_BA', 'bs', 'bos', 'bosnian'), 49 'ca-es' => array('ca_ES.UTF-8', 'ca_ES', 'cat', 'ca', 'catalan', 'ca_ES.ISO_8859-1', 'Catalan_Spain.1252'), 50 'cs-cz' => array('cs_CZ.UTF-8', 'cs_CZ', 'ces', 'cze', 'cs', 'csy', 'czech', 'cs_CZ.ISO_8859-2', 'Czech_Czech Republic.1250'), 51 'da-dk' => array('da_DK.UTF-8', 'da_DK', 'da', 'dan', 'danish', 'da_DK.ISO_8859-1', 'Danish_Denmark.1252'), 52 'de-de' => array('de_DE.UTF-8', 'de_DE', 'de', 'deu', 'german', 'de_DE.ISO_8859-1', 'de_DE.ISO_8859-16', 'German_Germany.1252'), 53 'el-gr' => array('el_GR.UTF-8', 'el_GR', 'el', 'gre', 'greek', 'el_GR.ISO_8859-7', 'Greek_Greece.1253'), 54 'en-gb' => array('en_GB.UTF-8', 'en_GB', 'en_UK', 'eng', 'en', 'english-uk', 'english', 'en_GB.ISO_8859-1', 'C', 'English_UK.1252'), 55 'en-us' => array('en_US.UTF-8', 'en_US', 'english-us', 'eng', 'en', 'english', 'en_US.ISO_8859-1', 'English_USA.1252'), 56 'es-es' => array('es_ES.UTF-8', 'es_ES', 'esp', 'spanish', 'es_ES.ISO_8859-1', 'Spanish_Spain.1252'), 57 'et-ee' => array('et_EE.UTF-8', 'et_EE', 'et', 'est', 'estonian', 'et_EE.ISO_8859-1', 'et_EE.ISO_8859-15', 'Estonian_Estonia.1257'), 58 'fa-ir' => array('fa_IR.UTF-8', 'fa_IR', 'fa', 'persian', 'per', 'fas', 'farsi', 'Farsi_Iran.1256'), 59 'fi-fi' => array('fi_FI.UTF-8', 'fi_FI', 'fin', 'fi', 'finnish', 'fi_FI.ISO_8859-1', 'fi_FI.ISO-8859-15', 'fi_FI.ISO_8859-16', 'Finnish_Finland.1252'), 60 'fr-fr' => array('fr_FR.UTF-8', 'fr_FR', 'fra', 'fre', 'fr', 'french', 'fr_FR.ISO_8859-1', 'fr_FR.ISO-8859-15', 'fr_FR.ISO_8859-16', 'French_France.1252'), 61 'gl-gz' => array('gl_GZ.UTF-8', 'gl_GZ', 'glg', 'gl'), 62 'gl-es' => array('gl_ES.UTF-8', 'gl_ES', 'gle', 'gl', 'galician', 'galleco', 'gl_ES.ISO_8859-1', 'Galician_Spain.1252'), 63 'he-il' => array('he_IL.UTF-8', 'he_IL', 'heb', 'he', 'hebrew', 'he_IL.ISO_8859-8', 'Hebrew_Israel.1255'), 64 'hr-hr' => array('hr_HR.UTF-8', 'hr_HR', 'hr', 'hrv', 'croatian', 'hr_HR.ISO_8859-2', 'hr_HR.ISO_8859-16', 'Croatian_Croatia.1250'), 65 'hu-hu' => array('hu_HU.UTF-8', 'hu_HU', 'hun', 'hu', 'hungarian', 'hu_HU.ISO_8859-2', 'hu_HU.ISO_8859-16', 'Hungarian_Hungary.1250'), 66 'id-id' => array('id_ID.UTF-8', 'id_ID', 'id', 'ind', 'indonesian', 'id_ID.ISO_8859-1', 'Indonesian_indonesia.1252'), 67 'is-is' => array('is_IS.UTF-8', 'is_IS', 'is', 'ice', 'isl', 'icelandic', 'is_IS.ISO_8859-1', 'Icelandic_Iceland.1252'), 68 'it-it' => array('it_IT.UTF-8', 'it_IT', 'it', 'ita', 'italian', 'it_IT.ISO_8859-1', 'it_IT.ISO_8859-16', 'Italian_Italy.1252'), 69 'ja-jp' => array('ja_JP.UTF-8', 'ja_JP', 'ja', 'jpn', 'japanese', 'Japanese_Japan.932'), 70 'ko-kr' => array('ko_KR.UTF-8', 'ko_KR', 'ko', 'kor', 'korean', 'Korean_Korea.949'), 71 'lt-lt' => array('lt_LT.UTF-8', 'lt_LT', 'lt', 'lit', 'lithuanian', 'lt_LT.ISO_8859-4', 'Lithuanian_Lithuania.1257'), 72 'lv-lv' => array('lv_LV.UTF-8', 'lv_LV', 'lv', 'lav', 'latvian', 'lv_LV.ISO_8859-4', 'Latvian_Latvia.1257'), 73 'nl-nl' => array('nl_NL.UTF-8', 'nl_NL', 'dut', 'nla', 'nl', 'nld', 'dutch', 'nl_NL.ISO_8859-1', 'Dutch_Netherlands.1252'), 74 'nn-no' => array('nn_NO.UTF-8', 'nn_NO', 'no', 'nn', 'nor', 'nno', 'nb', 'nob', 'norwegian', 'no_NO.ISO_8859-1', 'Norwegian_Norway.1252'), 75 'no-no' => array('no_NO.UTF-8', 'no_NO', 'no', 'nor', 'norwegian', 'no_NO.ISO_8859-1', 'Norwegian_Norway.1252'), 76 'pl-pl' => array('pl_PL.UTF-8', 'pl_PL', 'pl', 'pol', 'polish', 'po_PO.ISO_8859-2', 'Polish_Poland.1250'), 77 'pt-br' => array('pt_BR.UTF-8', 'pt_BR', 'pt', 'ptb', 'portuguese-brazil', 'Portuguese_Brazil.1252'), 78 'pt-pt' => array('pt_PT.UTF-8', 'pt_PT', 'por', 'portuguese', 'pt_PT.ISO_8859-1', 'Portuguese_Portugal.1252'), 79 'ro-ro' => array('ro_RO.UTF-8', 'ro_RO', 'ron', 'rum', 'ro', 'romanian', 'ro_RO.ISO_8859-2', 'ro_RO.ISO_8859-16', 'Romanian_Romania.1250'), 80 'ru-ru' => array('ru_RU.UTF-8', 'ru_RU', 'ru', 'rus', 'russian', 'ru_RU.ISO_8859-5', 'Russian_Russia.1251'), 81 'sk-sk' => array('sk_SK.UTF-8', 'sk_SK', 'sk', 'slo', 'slk', 'slovak', 'sk_SK.ISO_8859-1', 'Slovak_Slovakia.1250'), 82 'sr-rs' => array('sr-RS.UTF-8', 'sr_RS', 'sr', 'sp', 'srb', 'serbian', 'Serbian (Cyrillic)_Serbia and Montenegro.1251'), 83 'sr-sp' => array('sr-SP.UTF-8', 'sr_SP', 'sr', 'sp', 'srb', 'serbian', 'Serbian (Cyrillic)_Serbia and Montenegro.1251'), 84 'sv-se' => array('sv_SE.UTF-8', 'sv_SE', 'sv', 'swe', 'sve', 'swedish', 'sv_SE.ISO_8859-1', 'Swedish_Sweden.1252'), 85 'th-th' => array('th_TH.UTF-8', 'th_TH', 'th', 'tha', 'thai', 'th_TH.ISO_8859-11', 'Thai_Thailand.874'), 86 'tr-tr' => array('tr_TR.UTF-8', 'tr_TR', 'tr', 'tur', 'turkish', 'tr_TR.ISO_8859-3', 'tr_TR.ISO_8859-9', 'Turkish_Turkey.1254'), 87 'uk-ua' => array('uk_UA.UTF-8', 'uk_UA', 'uk', 'ukr', 'ukrainian', 'uk_UA.ISO_8859-5', 'Ukrainian_Ukraine.1251'), 88 'ur-in' => array('ur_IN.UTF-8', 'ur_IN', 'ur', 'urd', 'urdu'), 89 'vi-vn' => array('vi_VN.UTF-8', 'vi_VN', 'vi', 'vie', 'vietnamese', 'Vietnamese_Viet Nam.1258'), 90 'zh-cn' => array('zh_CN.UTF-8', 'zh_CN', 'chinese-simplified', 'Chinese_China.936'), 91 'zh-tw' => array('zh_TW.UTF-8', 'zh_TW', 'chinese-traditional', 'Chinese_Taiwan.950'), 92 ); 93 94 /** 95 * Sets the locale. 96 * 97 * This method wraps around system setlocale. It takes an IETF language code 98 * and sets the locale accordingly. 99 * 100 * The following would set the locale to English: 101 * 102 * <code> 103 * Txp::get('Textpattern\L10n\Locale')->setLocale(LC_ALL, 'en-GB'); 104 * </code> 105 * 106 * This would format currencies according to the French localisation: 107 * 108 * <code> 109 * Txp::get('Textpattern\L10n\Locale')->setLocale(LC_MONETARY, 'fr-FR'); 110 * echo money_format('%i', 51.99); 111 * </code> 112 * 113 * The '51.99' would be returned as '51,99 EUR' if you have up to date 114 * French locale installed on your system. 115 * 116 * If an array of locales is provided, the first one that works is used. 117 * 118 * @param int $category The localisation category to change 119 * @param string|array $locale The language code 120 * @return Locale 121 * @throws \Exception 122 * @see setlocale() 123 */ 124 125 public function setLocale($category, $locale) 126 { 127 foreach ((array)$locale as $name) { 128 $code = strtolower($name); 129 130 if (isset($this->locales[$code])) { 131 if (@setlocale($category, $this->locales[$code])) { 132 return $this; 133 } 134 } 135 } 136 137 if (@setlocale($category, $name)) { 138 return $this; 139 } 140 141 throw new \Exception(gTxt('invalid_argument', array('{name}' => 'locale'))); 142 } 143 144 /** 145 * Gets the current locale. 146 * 147 * <code> 148 * echo Txp::get('Textpattern\L10n\Locale')->getLocale(LC_ALL); 149 * </code> 150 * 151 * @param int $category The localisation category 152 * @return mixed 153 */ 154 155 public function getLocale($category = LC_ALL) 156 { 157 return @setlocale($category, '0'); 158 } 159 160 /** 161 * Gets a locale identifier for the given language code. 162 * 163 * This method takes an IETF language code and returns a locale for it that 164 * works on the current system. 165 * 166 * The following returns 'en_GB.UTF-8': 167 * 168 * <code> 169 * echo Txp::get('Textpattern\L10n\Locale')->getLanguageLocale('en-GB'); 170 * </code> 171 * 172 * Returns the current locale name if the system doesn't have anything 173 * more appropriate. 174 * 175 * @param string $language The language 176 * @return string|bool Locale code, or FALSE on error 177 */ 178 179 public function getLanguageLocale($language) 180 { 181 $locale = false; 182 183 if ($original = $this->getLocale(LC_TIME)) { 184 $locale = $original; 185 186 try { 187 $locale = $this->setLocale(LC_TIME, $language)->getLocale(LC_TIME); 188 $this->setLocale(LC_TIME, $original); 189 } catch (\Exception $e) { 190 } 191 } 192 193 return $locale; 194 } 195 196 /** 197 * Gets a language code for the given locale identifier. 198 * 199 * This method supports various different formats used by different host 200 * platform. These formats include IETF language tag, POSIX locale name and 201 * language name in English. 202 * 203 * All these will return 'en-GB': 204 * 205 * <code> 206 * echo Txp::get('Textpattern\L10n\Locale')->getLocaleLanguage('en_GB.UTF-8'); 207 * echo Txp::get('Textpattern\L10n\Locale')->getLocaleLanguage('en-gb'); 208 * echo Txp::get('Textpattern\L10n\Locale')->getLocaleLanguage('english'); 209 * echo Txp::get('Textpattern\L10n\Locale')->getLocaleLanguage('c'); 210 * echo Txp::get('Textpattern\L10n\Locale')->getLocaleLanguage('English_UK.1252'); 211 * </code> 212 * 213 * If the specified locale isn't supported, FALSE will be returned. 214 * 215 * @param string $locale The locale identifier 216 * @return string|bool The language code, or FALSE on failure 217 */ 218 219 public function getLocaleLanguage($locale) 220 { 221 $code = strtolower($locale); 222 223 foreach ($this->locales as $lang => $data) { 224 if ($lang === $code || in_array($code, array_map('strtolower', $data), true)) { 225 return $lang; 226 } 227 } 228 229 if (strpos($locale, '.')) { 230 return join('.', array_slice(explode('.', $locale), 0, 1)); 231 } 232 233 return false; 234 } 235 236 /** 237 * Gets the character set from the current locale. 238 * 239 * This method exports the character set from the current locale string as 240 * returned by the OS. 241 * 242 * <code> 243 * echo Txp::get('Textpattern\L10n\Locale')->getCharset(); 244 * </code> 245 * 246 * @param int $category The localisation category 247 * @return string|bool The character set, or FALSE on failure 248 */ 249 250 public function getCharset($category = LC_ALL) 251 { 252 if (($locale = $this->getLocale($category)) && strpos($locale, '.')) { 253 list($language, $charset) = explode('.', $locale); 254 255 if (IS_WIN && is_numeric($charset)) { 256 return 'Windows-'.$charset; 257 } 258 259 return $charset; 260 } 261 262 return false; 263 } 264 265 /** 266 * Gets the language from the current locale. 267 * 268 * <code> 269 * echo Txp::get('Textpattern\L10n\Locale')->getLanguage(); 270 * </code> 271 * 272 * @param int $category The localisation category 273 * @return string|bool The language code, or FALSE on failure 274 */ 275 276 public function getLanguage($category = LC_ALL) 277 { 278 if ($locale = $this->getLocale($category)) { 279 if (($lang = $this->getLocaleLanguage($locale)) !== false) { 280 return $lang; 281 } 282 } 283 284 return false; 285 } 286 287 /** 288 * Gets locale identifiers mapped to the given language. 289 * 290 * Returns all locale identifiers that match the given language or locale 291 * code. For instance providing 'en', will return both en-US and en-GB 292 * locale identifiers. 293 * 294 * <code> 295 * print_r(Txp::get('Textpattern\L10n\Locale')->getLocaleIdentifiers('english')); 296 * print_r(Txp::get('Textpattern\L10n\Locale')->getLocaleIdentifiers('en')); 297 * print_r(Txp::get('Textpattern\L10n\Locale')->getLocaleIdentifiers('en-gb')); 298 * </code> 299 * 300 * @param string $locale The locale or language code 301 * @return array|bool An array of identifiers, or FALSE if not supported 302 */ 303 304 public function getLocaleIdentifiers($locale) 305 { 306 if (isset($this->locales[strtolower($locale)])) { 307 return array_merge($this->locales[$locale], array($locale)); 308 } 309 310 $code = strtolower($locale); 311 $matches = array(); 312 313 foreach ($this->locales as $lang => $data) { 314 if ($lang === $code || in_array($code, array_map('strtolower', $data), true)) { 315 $matches = array_merge($matches, $data, array($lang, $locale)); 316 } 317 } 318 319 if ($matches) { 320 return array_unique($matches); 321 } 322 323 return false; 324 } 325 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title