‪TYPO3CMS  10.4
Locales.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
22 
30 {
36  protected ‪$languages = [
37  'default' => 'English',
38  'af' => 'Afrikaans',
39  'ar' => 'Arabic',
40  'bs' => 'Bosnian',
41  'bg' => 'Bulgarian',
42  'ca' => 'Catalan',
43  'ch' => 'Chinese (Simple)',
44  'cs' => 'Czech',
45  'da' => 'Danish',
46  'de' => 'German',
47  'el' => 'Greek',
48  'eo' => 'Esperanto',
49  'es' => 'Spanish',
50  'et' => 'Estonian',
51  'eu' => 'Basque',
52  'fa' => 'Persian',
53  'fi' => 'Finnish',
54  'fo' => 'Faroese',
55  'fr' => 'French',
56  'fr_CA' => 'French (Canada)',
57  'gl' => 'Galician',
58  'he' => 'Hebrew',
59  'hi' => 'Hindi',
60  'hr' => 'Croatian',
61  'hu' => 'Hungarian',
62  'is' => 'Icelandic',
63  'it' => 'Italian',
64  'ja' => 'Japanese',
65  'ka' => 'Georgian',
66  'kl' => 'Greenlandic',
67  'km' => 'Khmer',
68  'ko' => 'Korean',
69  'lt' => 'Lithuanian',
70  'lv' => 'Latvian',
71  'mi' => 'Maori',
72  'mk' => 'Macedonian',
73  'ms' => 'Malay',
74  'nl' => 'Dutch',
75  'no' => 'Norwegian',
76  'pl' => 'Polish',
77  'pt' => 'Portuguese',
78  'pt_BR' => 'Brazilian Portuguese',
79  'ro' => 'Romanian',
80  'ru' => 'Russian',
81  'rw' => 'Kinyarwanda',
82  'sk' => 'Slovak',
83  'sl' => 'Slovenian',
84  'sq' => 'Albanian',
85  'sr' => 'Serbian',
86  'sv' => 'Swedish',
87  'th' => 'Thai',
88  'tr' => 'Turkish',
89  'uk' => 'Ukrainian',
90  'vi' => 'Vietnamese',
91  'zh' => 'Chinese (Trad)'
92  ];
93 
99  protected ‪$isoReverseMapping = [
100  'bs' => 'ba', // Bosnian
101  'cs' => 'cz', // Czech
102  'da' => 'dk', // Danish
103  'el' => 'gr', // Greek
104  'fr_CA' => 'qc', // French (Canada)
105  'gl' => 'ga', // Galician
106  'ja' => 'jp', // Japanese
107  'ka' => 'ge', // Georgian
108  'kl' => 'gl', // Greenlandic
109  'ko' => 'kr', // Korean
110  'ms' => 'my', // Malay
111  'pt_BR' => 'br', // Portuguese (Brazil)
112  'sl' => 'si', // Slovenian
113  'sv' => 'se', // Swedish
114  'uk' => 'ua', // Ukrainian
115  'vi' => 'vn', // Vietnamese
116  'zh' => 'hk', // Chinese (China)
117  'zh_CN' => 'ch', // Chinese (Simplified)
118  'zh_HK' => 'hk', // Chinese (Simplified Hong Kong)
119  'zh_Hans_CN' => 'ch' // Chinese (Simplified Han)
120  ];
121 
128  protected ‪$localeDependencies = [
129  'pt_BR' => ['pt'],
130  'fr_CA' => ['fr']
131  ];
132 
133  public function ‪__construct()
134  {
135  // Allow user-defined locales
136  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['localization']['locales']['user'] ?? [] as $locale => $name) {
137  if (!isset($this->languages[$locale])) {
138  $this->languages[$locale] = $name;
139  }
140  // Initializes the locale dependencies with TYPO3 supported locales
141  if (strlen($locale) === 5) {
142  $this->localeDependencies[$locale] = [substr($locale, 0, 2)];
143  }
144  }
145  // Merge user-provided locale dependencies
146  if (is_array(‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['localization']['locales']['dependencies'] ?? null)) {
147  $this->localeDependencies = array_replace_recursive(
148  $this->localeDependencies,
149  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['localization']['locales']['dependencies']
150  );
151  }
152  }
153 
159  public static function ‪initialize(): ‪Locales
160  {
161  trigger_error('Locales::initialize() will be removed in TYPO3 v11.0, fetch the instance of a class via GeneralUtility::makeInstance() or DependencyInjection', E_USER_DEPRECATED);
162  return new self();
163  }
164 
170  public function ‪getLocales()
171  {
172  return array_keys($this->languages);
173  }
174 
180  public function ‪getLanguages()
181  {
182  return ‪$this->languages;
183  }
184 
190  public function ‪getIsoMapping()
191  {
192  return array_flip($this->isoReverseMapping);
193  }
194 
201  public function ‪getLocaleDependencies($locale)
202  {
203  $dependencies = [];
204  if (isset($this->localeDependencies[$locale])) {
205  $dependencies = $this->localeDependencies[$locale];
206  // Search for dependencies recursively
207  ‪$localeDependencies = $dependencies;
208  foreach (‪$localeDependencies as $dependency) {
209  if (isset($this->localeDependencies[$dependency])) {
210  $dependencies = array_merge($dependencies, $this->‪getLocaleDependencies($dependency));
211  }
212  }
213  }
214  return $dependencies;
215  }
216 
224  public function ‪getPreferredClientLanguage($languageCodesList)
225  {
226  $allLanguageCodesFromLocales = ['en' => 'default'];
227  foreach ($this->isoReverseMapping as $isoLang => $typo3Lang) {
228  $isoLang = str_replace('_', '-', $isoLang);
229  $allLanguageCodesFromLocales[$isoLang] = $typo3Lang;
230  }
231  foreach ($this->‪getLocales() as $locale) {
232  $locale = str_replace('_', '-', $locale);
233  $allLanguageCodesFromLocales[$locale] = $locale;
234  }
235  $selectedLanguage = 'default';
236  $preferredLanguages = ‪GeneralUtility::trimExplode(',', $languageCodesList);
237  // Order the preferred languages after they key
238  $sortedPreferredLanguages = [];
239  foreach ($preferredLanguages as $preferredLanguage) {
240  $quality = 1.0;
241  if (strpos($preferredLanguage, ';q=') !== false) {
242  [$preferredLanguage, $quality] = explode(';q=', $preferredLanguage);
243  }
244  $sortedPreferredLanguages[$preferredLanguage] = $quality;
245  }
246  // Loop through the languages, with the highest priority first
247  arsort($sortedPreferredLanguages, SORT_NUMERIC);
248  foreach ($sortedPreferredLanguages as $preferredLanguage => $quality) {
249  if (isset($allLanguageCodesFromLocales[$preferredLanguage])) {
250  $selectedLanguage = $allLanguageCodesFromLocales[$preferredLanguage];
251  break;
252  }
253  // Strip the country code from the end
254  [$preferredLanguage, ] = explode('-', $preferredLanguage);
255  if (isset($allLanguageCodesFromLocales[$preferredLanguage])) {
256  $selectedLanguage = $allLanguageCodesFromLocales[$preferredLanguage];
257  break;
258  }
259  }
260  if (!$selectedLanguage || $selectedLanguage === 'en') {
261  $selectedLanguage = 'default';
262  }
263  return $selectedLanguage;
264  }
265 
273  public static function ‪setSystemLocaleFromSiteLanguage(SiteLanguage $siteLanguage): bool
274  {
275  $locale = $siteLanguage->getLocale();
276  // No locale was given, so return false
277  if (!$locale) {
278  return false;
279  }
280  return ‪self::setLocale($locale, $locale);
281  }
282 
292  protected static function ‪setLocale(string $locale, string $localeStringForTrigger): bool
293  {
294  $incomingLocale = $locale;
295  $availableLocales = ‪GeneralUtility::trimExplode(',', $locale, true);
296  // If LC_NUMERIC is set e.g. to 'de_DE' PHP parses float values locale-aware resulting in strings with comma
297  // as decimal point which causes problems with value conversions - so we set all locale types except LC_NUMERIC
298  // @see https://bugs.php.net/bug.php?id=53711
299  $locale = setlocale(LC_COLLATE, ...$availableLocales);
300  if ($locale) {
301  // As str_* methods are locale aware and turkish has no upper case I
302  // Class autoloading and other checks depending on case changing break with turkish locale LC_CTYPE
303  // @see http://bugs.php.net/bug.php?id=35050
304  if (strpos($locale, 'tr') !== 0) {
305  setlocale(LC_CTYPE, ...$availableLocales);
306  }
307  setlocale(LC_MONETARY, ...$availableLocales);
308  setlocale(LC_TIME, ...$availableLocales);
309  } else {
310  // Retry again without the "utf-8" POSIX platform suffix if this is given.
311  if (str_contains($incomingLocale, '.')) {
312  [$localeWithoutModifier] = explode('.', $incomingLocale);
313  return ‪self::setLocale($localeWithoutModifier, $incomingLocale);
314  }
315  if ($localeStringForTrigger === $locale) {
316  GeneralUtility::makeInstance(LogManager::class)
317  ->getLogger(__CLASS__)
318  ->error('Locale "' . htmlspecialchars($localeStringForTrigger) . '" not found.');
319  } else {
320  GeneralUtility::makeInstance(LogManager::class)
321  ->getLogger(__CLASS__)
322  ->error('Locale "' . htmlspecialchars($localeStringForTrigger) . '" and "' . htmlspecialchars($incomingLocale) . '" not found.');
323  }
324  return false;
325  }
326  return true;
327  }
328 }
‪TYPO3\CMS\Core\Localization\Locales\setSystemLocaleFromSiteLanguage
‪static bool setSystemLocaleFromSiteLanguage(SiteLanguage $siteLanguage)
Definition: Locales.php:270
‪TYPO3\CMS\Core\Localization\Locales\initialize
‪static Locales initialize()
Definition: Locales.php:156
‪TYPO3\CMS\Core\Localization\Locales\setLocale
‪static setLocale(string $locale, string $localeStringForTrigger)
Definition: Locales.php:289
‪TYPO3\CMS\Core\Localization\Locales\$localeDependencies
‪array $localeDependencies
Definition: Locales.php:125
‪TYPO3\CMS\Core\Localization\Locales\getLocaleDependencies
‪array getLocaleDependencies($locale)
Definition: Locales.php:198
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:30
‪TYPO3\CMS\Core\Localization\Locales\__construct
‪__construct()
Definition: Locales.php:130
‪TYPO3\CMS\Core\Localization
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Core\Localization\Locales\getIsoMapping
‪array getIsoMapping()
Definition: Locales.php:187
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getLocale
‪string getLocale()
Definition: SiteLanguage.php:206
‪TYPO3\CMS\Core\Localization\Locales\getPreferredClientLanguage
‪string getPreferredClientLanguage($languageCodesList)
Definition: Locales.php:221
‪TYPO3\CMS\Core\Localization\Locales\getLanguages
‪array getLanguages()
Definition: Locales.php:177
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Core\Localization\Locales\$isoReverseMapping
‪array $isoReverseMapping
Definition: Locales.php:97
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:30
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Localization\Locales\$languages
‪array $languages
Definition: Locales.php:35
‪TYPO3\CMS\Core\Localization\Locales\getLocales
‪array getLocales()
Definition: Locales.php:167