TYPO3 CMS  TYPO3_8-7
LanguageService.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Lang;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
22 
32 {
38  public $lang = 'default';
39 
46  public $charSet = 'utf-8';
47 
53  public $debugKey = false;
54 
62  public $moduleLabels = [];
63 
69  public $LL_files_cache = [];
70 
76  public $LL_labels_cache = [];
77 
84  public $csConvObj;
85 
94 
101  protected $languageDependencies = [];
102 
108  protected $languageFileCache = [];
109 
113  public function __construct()
114  {
115  // Initialize the conversion object
116  $this->csConvObj = GeneralUtility::makeInstance(CharsetConverter::class);
117  // Initialize the localization factory object
118  $this->parserFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
119  if ($GLOBALS['TYPO3_CONF_VARS']['BE']['languageDebug']) {
120  $this->debugKey = true;
121  }
122  }
123 
133  public function init($languageKey)
134  {
135  // Find the requested language in this list based on the $languageKey
137  $locales = GeneralUtility::makeInstance(Locales::class);
138  // Language is found. Configure it:
139  if (in_array($languageKey, $locales->getLocales())) {
140  // The current language key
141  $this->lang = $languageKey;
142  $this->languageDependencies[] = $languageKey;
143  foreach ($locales->getLocaleDependencies($languageKey) as $language) {
144  $this->languageDependencies[] = $language;
145  }
146  }
147  }
148 
155  public function getParserFactory()
156  {
158  return $this->parserFactory;
159  }
160 
169  public function addModuleLabels($arr, $prefix)
170  {
172  if (is_array($arr)) {
173  foreach ($arr as $k => $larr) {
174  if (!isset($this->moduleLabels[$k])) {
175  $this->moduleLabels[$k] = [];
176  }
177  if (is_array($larr)) {
178  foreach ($larr as $l => $v) {
179  $this->moduleLabels[$k][$prefix . $l] = $v;
180  }
181  }
182  }
183  }
184  }
185 
199  public function makeEntities($str)
200  {
202  // Convert string back again, but using the full entity conversion:
203  return $this->csConvObj->utf8_to_entities($str);
204  }
205 
212  public function debugLL($value)
213  {
214  return $this->debugKey ? '[' . $value . ']' : '';
215  }
216 
225  public function getLL($index, $hsc = false)
226  {
227  return $this->getLLL($index, $GLOBALS['LOCAL_LANG'], $hsc);
228  }
229 
238  public function getLLL($index, $localLanguage, $hsc = false)
239  {
240  // @deprecated since TYPO3 v8, will be removed in TYPO3 v9
241  if ($hsc) {
243  'Calling getLLL() with argument \'hsc\' has been deprecated.'
244  );
245  }
246 
247  // Get Local Language. Special handling for all extensions that
248  // read PHP LL files and pass arrays here directly.
249  if (isset($localLanguage[$this->lang][$index])) {
250  $value = is_string($localLanguage[$this->lang][$index])
251  ? $localLanguage[$this->lang][$index]
252  : $localLanguage[$this->lang][$index][0]['target'];
253  } elseif (isset($localLanguage['default'][$index])) {
254  $value = is_string($localLanguage['default'][$index])
255  ? $localLanguage['default'][$index]
256  : $localLanguage['default'][$index][0]['target'];
257  } else {
258  $value = '';
259  }
260  if ($hsc) {
261  $value = htmlspecialchars($value);
262  }
263  return $value . $this->debugLL($index);
264  }
265 
277  public function sL($input, $hsc = false)
278  {
279  // @deprecated since TYPO3 v8, will be removed in TYPO3 v9
280  if ($hsc) {
282  'Calling sL() with argument \'hsc\' has been deprecated.'
283  );
284  }
285 
286  $identifier = $input . '_' . (int)$hsc . '_' . (int)$this->debugKey;
287  if (isset($this->LL_labels_cache[$this->lang][$identifier])) {
288  return $this->LL_labels_cache[$this->lang][$identifier];
289  }
290  if (strpos($input, 'LLL:') === 0) {
291  $restStr = trim(substr($input, 4));
292  $extPrfx = '';
293  // ll-file referred to is found in an extension.
294  if (strpos($restStr, 'EXT:') === 0) {
295  $restStr = trim(substr($restStr, 4));
296  $extPrfx = 'EXT:';
297  }
298  $parts = explode(':', $restStr);
299  $parts[0] = $extPrfx . $parts[0];
300  // Getting data if not cached
301  if (!isset($this->LL_files_cache[$parts[0]])) {
302  $this->LL_files_cache[$parts[0]] = $this->readLLfile($parts[0]);
303  }
304  $output = $this->getLLL($parts[1], $this->LL_files_cache[$parts[0]]);
305  } else {
306  // Use a constant non-localizable label
307  $output = $input;
308  }
309  if ($hsc) {
310  $output = htmlspecialchars($output, ENT_COMPAT, 'UTF-8', false);
311  }
312  $output .= $this->debugLL($input);
313  $this->LL_labels_cache[$this->lang][$identifier] = $output;
314  return $output;
315  }
316 
324  public function loadSingleTableDescription($table)
325  {
326  // First the 'table' cannot already be loaded in [columns]
327  // and secondly there must be a references to locallang files available in [refs]
328  if (is_array($GLOBALS['TCA_DESCR'][$table]) && !isset($GLOBALS['TCA_DESCR'][$table]['columns']) && is_array($GLOBALS['TCA_DESCR'][$table]['refs'])) {
329  // Init $TCA_DESCR for $table-key
330  $GLOBALS['TCA_DESCR'][$table]['columns'] = [];
331  // Get local-lang for each file in $TCA_DESCR[$table]['refs'] as they are ordered.
332  foreach ($GLOBALS['TCA_DESCR'][$table]['refs'] as $llfile) {
333  $localLanguage = $this->includeLLFile($llfile, false, true);
334  // Traverse all keys
335  if (is_array($localLanguage['default'])) {
336  foreach ($localLanguage['default'] as $lkey => $lVal) {
337  // Exploding by '.':
338  // 0-n => fieldname,
339  // n+1 => type from (alttitle, description, details, syntax, image_descr,image,seeAlso),
340  // n+2 => special instruction, if any
341  $keyParts = explode('.', $lkey);
342  $keyPartsCount = count($keyParts);
343  // Check if last part is special instruction
344  // Only "+" is currently supported
345  $specialInstruction = $keyParts[$keyPartsCount - 1] === '+';
346  if ($specialInstruction) {
347  array_pop($keyParts);
348  }
349  // If there are more than 2 parts, get the type from the last part
350  // and merge back the other parts with a dot (.)
351  // Otherwise just get type and field name straightaway
352  if ($keyPartsCount > 2) {
353  $type = array_pop($keyParts);
354  $fieldName = implode('.', $keyParts);
355  } else {
356  $fieldName = $keyParts[0];
357  $type = $keyParts[1];
358  }
359  // Detecting 'hidden' labels, converting to normal fieldname
360  if ($fieldName === '_') {
361  $fieldName = '';
362  }
363  if ($fieldName !== '' && $fieldName[0] === '_') {
364  $fieldName = substr($fieldName, 1);
365  }
366  // Append label
367  $label = $lVal[0]['target'] ? :
368  $lVal[0]['source'];
369  if ($specialInstruction) {
370  $GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] .= LF . $label;
371  } else {
372  // Substitute label
373  $GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] = $label;
374  }
375  }
376  }
377  }
378  }
379  }
380 
390  public function includeLLFile($fileRef, $setGlobal = true, $mergeLocalOntoDefault = false)
391  {
392  $globalLanguage = [];
393  // Get default file
394  $localLanguage = $this->readLLfile($fileRef);
395  if (is_array($localLanguage) && !empty($localLanguage)) {
396  // it depends on, whether we should return the result or set it in the global $LOCAL_LANG array
397  if ($setGlobal) {
398  $globalLanguage = (array)$GLOBALS['LOCAL_LANG'];
399  ArrayUtility::mergeRecursiveWithOverrule($globalLanguage, $localLanguage);
400  } else {
401  $globalLanguage = $localLanguage;
402  }
403  // Merge local onto default
404  if ($mergeLocalOntoDefault && $this->lang !== 'default' && is_array($globalLanguage[$this->lang]) && is_array($globalLanguage['default'])) {
405  // array_merge can be used so far the keys are not
406  // numeric - which we assume they are not...
407  $globalLanguage['default'] = array_merge($globalLanguage['default'], $globalLanguage[$this->lang]);
408  unset($globalLanguage[$this->lang]);
409  }
410  }
411  // Return value if not global is set.
412  if (!$setGlobal) {
413  return $globalLanguage;
414  }
415  $GLOBALS['LOCAL_LANG'] = $globalLanguage;
416  return null;
417  }
418 
425  protected function readLLfile($fileRef)
426  {
427  if (isset($this->languageFileCache[$fileRef . $this->lang])) {
428  return $this->languageFileCache[$fileRef . $this->lang];
429  }
430 
432  $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
433 
434  if ($this->lang !== 'default') {
435  $languages = array_reverse($this->languageDependencies);
436  } else {
437  $languages = ['default'];
438  }
439  $localLanguage = [];
440  foreach ($languages as $language) {
441  $tempLL = $languageFactory->getParsedData($fileRef, $language, 'utf-8');
442  $localLanguage['default'] = $tempLL['default'];
443  if (!isset($localLanguage[$this->lang])) {
444  $localLanguage[$this->lang] = $localLanguage['default'];
445  }
446  if ($this->lang !== 'default' && isset($tempLL[$language])) {
447  // Merge current language labels onto labels from previous language
448  // This way we have a labels with fall back applied
449  ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$this->lang], $tempLL[$language], true, false);
450  }
451  }
452  $this->languageFileCache[$fileRef . $this->lang] = $localLanguage;
453 
454  return $localLanguage;
455  }
456 
465  public function overrideLL($index, $value, $overrideDefault = true)
466  {
468  if (!isset($GLOBALS['LOCAL_LANG'])) {
469  $GLOBALS['LOCAL_LANG'] = [];
470  }
471  $GLOBALS['LOCAL_LANG'][$this->lang][$index][0]['target'] = $value;
472  if ($overrideDefault) {
473  $GLOBALS['LOCAL_LANG']['default'][$index][0]['target'] = $value;
474  }
475  }
476 
485  public function getLabelsWithPrefix($prefix, $strip = '')
486  {
487  $extraction = [];
488  $labels = array_merge((array)$GLOBALS['LOCAL_LANG']['default'], (array)$GLOBALS['LOCAL_LANG'][$this->lang]);
489  // Regular expression to strip the selection prefix and possibly something from the label name:
490  $labelPattern = '#^' . preg_quote($prefix, '#') . '(' . preg_quote($strip, '#') . ')?#';
491  // Iterate through all locallang labels:
492  foreach ($labels as $label => $value) {
493  if (strpos($label, $prefix) === 0) {
494  $key = preg_replace($labelPattern, '', $label);
495  $extraction[$key] = $value;
496  }
497  }
498  return $extraction;
499  }
500 }
overrideLL($index, $value, $overrideDefault=true)
static makeInstance($className,... $constructorArguments)
getLabelsWithPrefix($prefix, $strip='')
includeLLFile($fileRef, $setGlobal=true, $mergeLocalOntoDefault=false)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
getLLL($index, $localLanguage, $hsc=false)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
$locales
Definition: be_users.php:6