‪TYPO3CMS  10.4
LanguageService.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 
24 
42 {
45 
46  protected ‪$deprecatedPublicProperties = [
47  'LL_files_cache' => 'The runtime cache variable is only used for internal purposes, and should never be accessed from the outside. Accessing this property will stop working in TYPO3 v11.0.',
48  'LL_labels_cache' => 'The runtime cache variable is only used for internal purposes, and should never be accessed from the outside. Accessing this property will stop working in TYPO3 v11.0.'
49  ];
50 
51  protected ‪$deprecatedPublicMethods = [
52  'debugLL' => 'Should never be called directly. use the "debugKey" to actually access the method.',
53  'getLLL' => 'Use "getLL()" or "sL()" instead as API methods.',
54  ];
55 
61  public ‪$lang = 'default';
62 
68  public ‪$debugKey = false;
69 
75  protected ‪$LL_files_cache = [];
76 
82  protected ‪$LL_labels_cache = [];
83 
90  protected ‪$languageDependencies = [];
91 
97  protected ‪$languageFileCache = [];
98 
102  protected ‪$labels = [];
103 
107  protected ‪$locales;
108 
112  protected ‪$localizationFactory;
113 
118  {
119  $this->locales = ‪$locales;
120  $this->localizationFactory = ‪$localizationFactory;
121  $this->debugKey = (bool)‪$GLOBALS['TYPO3_CONF_VARS']['BE']['languageDebug'];
122  }
123 
133  public function ‪init($languageKey)
134  {
135  // Find the requested language in this list based on the $languageKey
136  // Language is found. Configure it:
137  if (in_array($languageKey, $this->locales->getLocales(), true)) {
138  // The current language key
139  $this->lang = $languageKey;
140  $this->languageDependencies[] = $languageKey;
141  foreach ($this->locales->getLocaleDependencies($languageKey) as $language) {
142  $this->languageDependencies[] = $language;
143  }
144  }
145  }
146 
153  protected function ‪debugLL($value)
154  {
155  return $this->debugKey ? '[' . $value . ']' : '';
156  }
157 
165  public function ‪getLL($index)
166  {
167  return $this->‪getLLL($index, !empty(‪$GLOBALS['LOCAL_LANG']) ? ‪$GLOBALS['LOCAL_LANG'] : $this->labels);
168  }
169 
177  protected function ‪getLLL($index, $localLanguage)
178  {
179  // Get Local Language. Special handling for all extensions that
180  // read PHP LL files and pass arrays here directly.
181  if (isset($localLanguage[$this->lang][$index])) {
182  $value = is_string($localLanguage[$this->lang][$index])
183  ? $localLanguage[‪$this->lang][$index]
184  : $localLanguage[‪$this->lang][$index][0]['target'];
185  } elseif (isset($localLanguage['default'][$index])) {
186  $value = is_string($localLanguage['default'][$index])
187  ? $localLanguage['default'][$index]
188  : $localLanguage['default'][$index][0]['target'];
189  } else {
190  $value = '';
191  }
192  return $value . $this->‪debugLL($index);
193  }
194 
205  public function ‪sL($input)
206  {
207  $identifier = $input . '_' . (int)$this->debugKey;
208  if (isset($this->LL_labels_cache[$this->lang][$identifier])) {
209  return $this->LL_labels_cache[‪$this->lang][$identifier];
210  }
211  if (strpos(trim($input), 'LLL:') === 0) {
212  $restStr = substr(trim($input), 4);
213  $extPrfx = '';
214  // ll-file referred to is found in an extension.
215  if (strpos(trim($restStr), 'EXT:') === 0) {
216  $restStr = substr(trim($restStr), 4);
217  $extPrfx = 'EXT:';
218  }
219  $parts = explode(':', trim($restStr));
220  $parts[0] = $extPrfx . $parts[0];
221  // Getting data if not cached
222  if (!isset($this->LL_files_cache[$parts[0]])) {
223  $this->LL_files_cache[$parts[0]] = $this->‪readLLfile($parts[0]);
224  }
225  ‪$output = $this->‪getLLL($parts[1], $this->LL_files_cache[$parts[0]]);
226  } else {
227  // Use a constant non-localizable label
228  ‪$output = $input;
229  }
230  ‪$output .= $this->‪debugLL($input);
231  $this->LL_labels_cache[‪$this->lang][$identifier] = ‪$output;
232  return ‪$output;
233  }
234 
243  public function ‪loadSingleTableDescription($table)
244  {
245  // First the 'table' cannot already be loaded in [columns]
246  // and secondly there must be a references to locallang files available in [refs]
247  if (is_array(‪$GLOBALS['TCA_DESCR'][$table]) && !isset(‪$GLOBALS['TCA_DESCR'][$table]['columns']) && is_array(‪$GLOBALS['TCA_DESCR'][$table]['refs'])) {
248  // Init $TCA_DESCR for $table-key
249  ‪$GLOBALS['TCA_DESCR'][$table]['columns'] = [];
250  // Get local-lang for each file in $TCA_DESCR[$table]['refs'] as they are ordered.
251  foreach (‪$GLOBALS['TCA_DESCR'][$table]['refs'] as $llfile) {
252  $localLanguage = $this->‪includeLanguageFileRaw($llfile);
253  // Traverse all keys
254  if (is_array($localLanguage['default'])) {
255  foreach ($localLanguage['default'] as $lkey => $lVal) {
256  // Exploding by '.':
257  // 0-n => fieldname,
258  // n+1 => type from (alttitle, description, details, syntax, image_descr,image,seeAlso),
259  // n+2 => special instruction, if any
260  $keyParts = explode('.', $lkey);
261  $keyPartsCount = count($keyParts);
262  // Check if last part is special instruction
263  // Only "+" is currently supported
264  $specialInstruction = $keyParts[$keyPartsCount - 1] === '+';
265  if ($specialInstruction) {
266  array_pop($keyParts);
267  }
268  // If there are more than 2 parts, get the type from the last part
269  // and merge back the other parts with a dot (.)
270  // Otherwise just get type and field name straightaway
271  if ($keyPartsCount > 2) {
272  $type = array_pop($keyParts);
273  $fieldName = implode('.', $keyParts);
274  } else {
275  $fieldName = $keyParts[0];
276  $type = $keyParts[1];
277  }
278  // Detecting 'hidden' labels, converting to normal fieldname
279  if ($fieldName === '_') {
280  $fieldName = '';
281  }
282  if ($fieldName !== '' && $fieldName[0] === '_') {
283  $fieldName = substr($fieldName, 1);
284  }
285  // Append label
286  $label = $lVal[0]['target'] ?: $lVal[0]['source'];
287  if ($specialInstruction) {
288  ‪$GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] .= LF . $label;
289  } else {
290  // Substitute label
291  ‪$GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] = $label;
292  }
293  }
294  }
295  }
296  }
297  }
298 
308  public function ‪includeLLFile($fileRef, $setGlobal = null, $mergeLocalOntoDefault = null)
309  {
310  if ($setGlobal !== null) {
311  trigger_error('LanguageService->includeLLFile() with the second argument set will be removed in TYPO3 v11.0, use "includeLLFile()" with only the file reference.', E_USER_DEPRECATED);
312  } else {
313  $setGlobal = true;
314  }
315  if ($mergeLocalOntoDefault !== null) {
316  trigger_error('LanguageService->includeLLFile() with the third argument set will be removed in TYPO3 v11.0, use "includeLLFile()" with only the file reference.', E_USER_DEPRECATED);
317  } else {
318  $mergeLocalOntoDefault = false;
319  }
320  $globalLanguage = [];
321  // Get default file
322  $localLanguage = $this->‪readLLfile($fileRef);
323  if (is_array($localLanguage) && !empty($localLanguage)) {
324  // it depends on, whether we should return the result or set it in the global $LOCAL_LANG array
325  if ($setGlobal) {
326  $globalLanguage = (array)(‪$GLOBALS['LOCAL_LANG'] ?? $this->labels ?: []);
327  ‪ArrayUtility::mergeRecursiveWithOverrule($globalLanguage, $localLanguage);
328  } else {
329  $globalLanguage = $localLanguage;
330  }
331  // Merge local onto default
332  if ($mergeLocalOntoDefault && $this->lang !== 'default' && is_array($globalLanguage[$this->lang]) && is_array($globalLanguage['default'])) {
333  // array_merge can be used so far the keys are not
334  // numeric - which we assume they are not...
335  $globalLanguage['default'] = array_merge($globalLanguage['default'], $globalLanguage[$this->lang]);
336  unset($globalLanguage[$this->lang]);
337  }
338  }
339  // Return value if not global is set.
340  if (!$setGlobal) {
341  return $globalLanguage;
342  }
343  $this->labels = $globalLanguage;
344  ‪$GLOBALS['LOCAL_LANG'] = $globalLanguage;
345  return $localLanguage;
346  }
347 
355  protected function ‪includeLanguageFileRaw($fileRef)
356  {
357  ‪$labels = $this->‪readLLfile($fileRef);
358  if (is_array(‪$labels) && !empty(‪$labels)) {
359  // Merge local onto default
360  if ($this->lang !== 'default' && is_array(‪$labels[$this->lang]) && is_array(‪$labels['default'])) {
361  // array_merge can be used so far the keys are not
362  // numeric - which we assume they are not...
363  ‪$labels['default'] = array_merge(‪$labels['default'], ‪$labels[$this->lang]);
364  unset(‪$labels[$this->lang]);
365  }
366  }
367  return is_array(‪$labels) ? ‪$labels : [];
368  }
369 
376  protected function ‪readLLfile($fileRef)
377  {
378  if (isset($this->languageFileCache[$fileRef . $this->lang])) {
379  return $this->languageFileCache[$fileRef . ‪$this->lang];
380  }
381 
382  if ($this->lang !== 'default') {
383  $languages = array_reverse($this->languageDependencies);
384  } else {
385  $languages = ['default'];
386  }
387  $localLanguage = [];
388  foreach ($languages as $language) {
389  $tempLL = $this->localizationFactory->getParsedData($fileRef, $language);
390  $localLanguage['default'] = $tempLL['default'];
391  if (!isset($localLanguage[$this->lang])) {
392  $localLanguage[‪$this->lang] = $localLanguage['default'];
393  }
394  if ($this->lang !== 'default' && isset($tempLL[$language])) {
395  // Merge current language labels onto labels from previous language
396  // This way we have a labels with fall back applied
397  ‪ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], true, false);
398  }
399  }
400  $this->languageFileCache[$fileRef . ‪$this->lang] = $localLanguage;
401 
402  return $localLanguage;
403  }
404 
414  public function ‪getLabelsWithPrefix($prefix, $strip = '')
415  {
416  trigger_error('LanguageService->getLabelsWithPrefix() will be removed in TYPO3 v11.0. Prefixing labels was used for various Backend-related JavaScript calls, which is not supported anymore. Prefixes should be applied to the label keys / ids directly instead.', E_USER_DEPRECATED);
417  $extraction = [];
418  if (!empty(‪$GLOBALS['LOCAL_LANG']['default'])) {
419  ‪$labels = array_merge((array)‪$GLOBALS['LOCAL_LANG']['default'], (array)‪$GLOBALS['LOCAL_LANG'][$this->lang]);
420  } else {
421  ‪$labels = array_merge((array)$this->labels['default'], (array)$this->labels[$this->lang]);
422  }
423  // Regular expression to strip the selection prefix and possibly something from the label name:
424  $labelPattern = '#^' . preg_quote($prefix, '#') . '(' . preg_quote($strip, '#') . ')?#';
425  // Iterate through all locallang labels:
426  foreach (‪$labels as $label => $value) {
427  if (strpos($label, $prefix) === 0) {
428  $key = preg_replace($labelPattern, '', $label);
429  $extraction[$key] = $value;
430  }
431  }
432  return $extraction;
433  }
434 
441  public static function ‪create(string $locale): self
442  {
443  return GeneralUtility::makeInstance(LanguageServiceFactory::class)->create($locale);
444  }
445 
446  public static function ‪createFromUserPreferences(?‪AbstractUserAuthentication $user): self
447  {
448  if ($user && ($user->uc['lang'] ?? false)) {
449  return static::create($user->uc['lang']);
450  }
451  return static::create('default');
452  }
453 
454  public static function ‪createFromSiteLanguage(SiteLanguage $language): self
455  {
456  return static::create($language->getTypo3Language());
457  }
458 }
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪array includeLLFile($fileRef, $setGlobal=null, $mergeLocalOntoDefault=null)
Definition: LanguageService.php:297
‪TYPO3\CMS\Core\Localization\LanguageService\$lang
‪string $lang
Definition: LanguageService.php:58
‪TYPO3\CMS\Core\Localization\LanguageService\$languageFileCache
‪array $languageFileCache
Definition: LanguageService.php:89
‪TYPO3\CMS\Core\Localization\LocalizationFactory
Definition: LocalizationFactory.php:28
‪TYPO3\CMS\Core\Localization\LanguageService\getLabelsWithPrefix
‪array getLabelsWithPrefix($prefix, $strip='')
Definition: LanguageService.php:403
‪TYPO3\CMS\Core\Localization\LanguageService\$LL_files_cache
‪array $LL_files_cache
Definition: LanguageService.php:70
‪TYPO3\CMS\Core\Localization\LanguageService\$localizationFactory
‪LocalizationFactory $localizationFactory
Definition: LanguageService.php:101
‪TYPO3\CMS\Core\Localization\LanguageService\$labels
‪string[][] $labels
Definition: LanguageService.php:93
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:30
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Core\Localization\LanguageService\readLLfile
‪array readLLfile($fileRef)
Definition: LanguageService.php:365
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Core\Localization
‪TYPO3\CMS\Core\Localization\LanguageService\loadSingleTableDescription
‪loadSingleTableDescription($table)
Definition: LanguageService.php:232
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Core\Localization\LanguageService\createFromUserPreferences
‪static createFromUserPreferences(?AbstractUserAuthentication $user)
Definition: LanguageService.php:435
‪TYPO3\CMS\Core\Localization\LanguageService\$debugKey
‪bool $debugKey
Definition: LanguageService.php:64
‪TYPO3\CMS\Core\Localization\LanguageService\__construct
‪__construct(Locales $locales, LocalizationFactory $localizationFactory)
Definition: LanguageService.php:106
‪TYPO3\CMS\Core\Localization\LanguageService\getLLL
‪string getLLL($index, $localLanguage)
Definition: LanguageService.php:166
‪TYPO3\CMS\Core\Localization\LanguageService\init
‪init($languageKey)
Definition: LanguageService.php:122
‪TYPO3\CMS\Core\Localization\LanguageService\debugLL
‪string debugLL($value)
Definition: LanguageService.php:142
‪TYPO3\CMS\Core\Localization\LanguageService\$LL_labels_cache
‪array $LL_labels_cache
Definition: LanguageService.php:76
‪TYPO3\CMS\Core\Localization\LanguageService\createFromSiteLanguage
‪static createFromSiteLanguage(SiteLanguage $language)
Definition: LanguageService.php:443
‪TYPO3\CMS\Core\Localization\LanguageService\includeLanguageFileRaw
‪array includeLanguageFileRaw($fileRef)
Definition: LanguageService.php:344
‪TYPO3\CMS\Core\Compatibility\PublicMethodDeprecationTrait
Definition: PublicMethodDeprecationTrait.php:70
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Localization\LanguageService\$deprecatedPublicMethods
‪$deprecatedPublicMethods
Definition: LanguageService.php:49
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait
Definition: PublicPropertyDeprecationTrait.php:68
‪TYPO3\CMS\Core\Localization\LanguageService\$locales
‪Locales $locales
Definition: LanguageService.php:97
‪TYPO3\CMS\Core\Localization\LanguageService\$languageDependencies
‪array $languageDependencies
Definition: LanguageService.php:83
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:154
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Localization\LanguageService\$deprecatedPublicProperties
‪$deprecatedPublicProperties
Definition: LanguageService.php:44
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication
Definition: AbstractUserAuthentication.php:51
‪TYPO3\CMS\Core\Localization\LanguageService\create
‪static static create(string $locale)
Definition: LanguageService.php:430
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\getTypo3Language
‪string getTypo3Language()
Definition: SiteLanguage.php:254