‪TYPO3CMS  ‪main
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 
21 
46 {
50  public string ‪$lang = 'default';
51 
52  protected ?‪Locale ‪$locale = null;
53 
57  protected array ‪$labels = [];
58 
62  protected array ‪$overrideLabels = [];
63 
67 
72  {
73  $this->locales = ‪$locales;
74  $this->localizationFactory = ‪$localizationFactory;
75  $this->runtimeCache = ‪$runtimeCache;
76  }
77 
90  public function ‪init(‪Locale|string $languageKey): void
91  {
92  if ($languageKey instanceof ‪Locale) {
93  $this->locale = $languageKey;
94  } else {
95  $this->locale = $this->locales->createLocale($languageKey);
96  }
97  $this->lang = $this->‪getTypo3LanguageKey();
98  }
99 
107  protected function ‪getLLL(string $index, array $localLanguage): string
108  {
109  if (isset($localLanguage[$this->lang][$index])) {
110  $value = is_string($localLanguage[$this->lang][$index])
111  ? $localLanguage[‪$this->lang][$index]
112  : $localLanguage[‪$this->lang][$index][0]['target'];
113  } elseif (isset($localLanguage['default'][$index])) {
114  $value = is_string($localLanguage['default'][$index])
115  ? $localLanguage['default'][$index]
116  : $localLanguage['default'][$index][0]['target'];
117  } else {
118  $value = '';
119  }
120  return $value;
121  }
122 
136  public function ‪sL($input): string
137  {
138  $input = (string)$input;
139  // early return for empty input to avoid cache and language file reading on first hit.
140  if ($input === '') {
141  return $input;
142  }
143  // Use a constant non-localizable label
144  if (!str_starts_with(trim($input), 'LLL:')) {
145  return $input;
146  }
147 
148  $cacheIdentifier = 'labels_' . (string)$this->locale . '_' . md5($input);
149  $cacheEntry = $this->runtimeCache->get($cacheIdentifier);
150  if ($cacheEntry !== false) {
151  return $cacheEntry;
152  }
153  // Remove the LLL: prefix
154  $restStr = substr(trim($input), 4);
155  $extensionPrefix = '';
156  // ll-file referred to is found in an extension
157  if (‪PathUtility::isExtensionPath(trim($restStr))) {
158  $restStr = substr(trim($restStr), 4);
159  $extensionPrefix = 'EXT:';
160  }
161  $parts = explode(':', trim($restStr));
162  $parts[0] = $extensionPrefix . $parts[0];
163  $labelsFromFile = $this->‪readLLfile($parts[0]);
164  if (is_array($this->‪overrideLabels[$parts[0]] ?? null)) {
165  $labelsFromFile = array_replace_recursive($labelsFromFile, $this->‪overrideLabels[$parts[0]]);
166  }
167  ‪$output = $this->‪getLLL($parts[1] ?? '', $labelsFromFile);
168  $this->runtimeCache->set($cacheIdentifier, ‪$output);
169  return ‪$output;
170  }
171 
180  public function ‪includeLLFile(string $fileRef): array
181  {
182  $localLanguage = $this->‪readLLfile($fileRef);
183  if (!empty($localLanguage)) {
184  $this->labels = array_replace_recursive($this->labels, $localLanguage);
185  }
186  return $localLanguage;
187  }
188 
194  public function ‪translateLabel(array|string $input, string $fallback): string
195  {
196  if (is_array($input) && isset($input[$this->lang])) {
197  return $this->‪sL((string)$input[$this->lang]);
198  }
199  if (is_string($input)) {
200  return $this->‪sL($input);
201  }
202  return $this->‪sL($fallback);
203  }
204 
210  public function getLabelsFromResource(string $fileRef): array
211  {
212  ‪$labelArray = [];
213  $labelsFromFile = $this->‪readLLfile($fileRef);
214  foreach ($labelsFromFile['default'] as $key => $value) {
215  ‪$labelArray[$key] = $this->‪getLLL($key, $labelsFromFile);
216  }
218  }
219 
226  protected function ‪readLLfile(string $fileRef): array
227  {
228  $cacheIdentifier = 'labels_file_' . md5($fileRef . (string)$this->locale);
229  $cacheEntry = $this->runtimeCache->get($cacheIdentifier);
230  if (is_array($cacheEntry)) {
231  return $cacheEntry;
232  }
233 
234  $mainLanguageKey = $this->‪getTypo3LanguageKey();
235  $localLanguage = [];
236  $allLocales = array_merge([$mainLanguageKey], $this->locale->getDependencies());
237  $allLocales = array_reverse($allLocales);
238  foreach ($allLocales as ‪$locale) {
239  $tempLL = $this->localizationFactory->getParsedData($fileRef, ‪$locale);
240  $localLanguage['default'] = $tempLL['default'];
241  if (!isset($localLanguage[$mainLanguageKey])) {
242  $localLanguage[$mainLanguageKey] = $localLanguage['default'];
243  }
244  if ($mainLanguageKey !== 'default') {
245  // Fallback as long as TYPO3 supports "da_DK" and "da-DK"
246  if ((!isset($tempLL[‪$locale]) || $tempLL[‪$locale] === []) && str_contains(‪$locale, '-')) {
247  $underscoredLocale = str_replace('-', '_', ‪$locale);
248  $tempLL = $this->localizationFactory->getParsedData($fileRef, $underscoredLocale);
249  if (isset($tempLL[$underscoredLocale])) {
250  $tempLL[‪$locale] = $tempLL[$underscoredLocale];
251  }
252  }
253  if (isset($tempLL[‪$locale])) {
254  // Merge current language labels onto labels from previous language
255  // This way we have a labels with fall back applied
256  ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$mainLanguageKey], $tempLL[‪$locale], true, false);
257  }
258  }
259  }
260 
261  $this->runtimeCache->set($cacheIdentifier, $localLanguage);
262  return $localLanguage;
263  }
264 
269  public function ‪overrideLabels(string $fileRef, array ‪$labels): void
270  {
271  $localLanguage = [
272  'default' => ‪$labels['default'] ?? [],
273  ];
274  $mainLanguageKey = $this->‪getTypo3LanguageKey();
275  if ($mainLanguageKey !== 'default') {
276  $allLocales = array_merge([$mainLanguageKey], $this->locale->getDependencies());
277  $allLocales = array_reverse($allLocales);
278  foreach ($allLocales as $language) {
279  // Populate the initial values with default, if no labels for the current language are given
280  if (!isset($localLanguage[$mainLanguageKey])) {
281  $localLanguage[$mainLanguageKey] = $localLanguage['default'];
282  }
283  if (isset(‪$labels[$language])) {
284  $localLanguage[$mainLanguageKey] = array_replace_recursive($localLanguage[$mainLanguageKey], ‪$labels[$language]);
285  }
286  }
287  }
288  $this->‪overrideLabels[$fileRef] = $localLanguage;
289  }
290 
291  public function ‪getLocale(): ?‪Locale
292  {
293  return ‪$this->locale;
294  }
295 
296  private function ‪getTypo3LanguageKey(): string
297  {
298  if ($this->locale === null) {
299  return 'default';
300  }
301  if ($this->locale->getName() === 'en') {
302  return 'default';
303  }
304  return $this->locale->getName();
305  }
306 }
‪TYPO3\CMS\Core\Localization\LanguageService\readLLfile
‪array< string, getLabelsFromResource(string $fileRef):array { $labelArray=[];$labelsFromFile=$this-> readLLfile($fileRef)
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪array includeLLFile(string $fileRef)
Definition: LanguageService.php:180
‪TYPO3\CMS\Core\Localization\LanguageService\getLLL
‪string getLLL(string $index, array $localLanguage)
Definition: LanguageService.php:107
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static isExtensionPath(string $path)
Definition: PathUtility.php:117
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Localization\LanguageService\$lang
‪string $lang
Definition: LanguageService.php:50
‪TYPO3\CMS\Core\Localization\LocalizationFactory
Definition: LocalizationFactory.php:31
‪TYPO3\CMS\Core\Localization\LanguageService\$localizationFactory
‪LocalizationFactory $localizationFactory
Definition: LanguageService.php:65
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Core\Localization\LanguageService\init
‪init(Locale|string $languageKey)
Definition: LanguageService.php:90
‪TYPO3\CMS\Core\Localization\LanguageService\translateLabel
‪translateLabel(array|string $input, string $fallback)
Definition: LanguageService.php:194
‪TYPO3\CMS\Core\Localization\LanguageService\$labelArray
‪foreach($labelsFromFile['default'] as $key=> $value) return $labelArray
Definition: LanguageService.php:214
‪TYPO3\CMS\Core\Localization
Definition: CacheWarmer.php:18
‪TYPO3\CMS\Core\Localization\LanguageService\$runtimeCache
‪FrontendInterface $runtimeCache
Definition: LanguageService.php:66
‪TYPO3\CMS\Core\Localization\LanguageService\getLocale
‪getLocale()
Definition: LanguageService.php:291
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪sL($input)
Definition: LanguageService.php:136
‪TYPO3\CMS\Core\Localization\LanguageService\__construct
‪__construct(Locales $locales, LocalizationFactory $localizationFactory, FrontendInterface $runtimeCache)
Definition: LanguageService.php:71
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Core\Localization\LanguageService\$labels
‪array $labels
Definition: LanguageService.php:57
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Core\Localization\LanguageService\overrideLabels
‪overrideLabels(string $fileRef, array $labels)
Definition: LanguageService.php:269
‪TYPO3\CMS\Core\Localization\LanguageService\$locale
‪Locale $locale
Definition: LanguageService.php:52
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪TYPO3\CMS\Core\Localization\LanguageService\$overrideLabels
‪array $overrideLabels
Definition: LanguageService.php:62
‪TYPO3\CMS\Core\Localization\Locale
Definition: Locale.php:30
‪TYPO3\CMS\Core\Localization\LanguageService\getTypo3LanguageKey
‪getTypo3LanguageKey()
Definition: LanguageService.php:296
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Localization\LanguageService\$locales
‪Locales $locales
Definition: LanguageService.php:64
‪TYPO3\CMS\Core\Localization\LanguageService\readLLfile
‪array readLLfile(string $fileRef)
Definition: LanguageService.php:226