‪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  public function ‪__construct(
68  protected ‪Locales $locales,
69  protected readonly ‪LocalizationFactory $localizationFactory,
70  protected readonly ‪FrontendInterface $runtimeCache
71  ) {}
72 
85  public function ‪init(‪Locale|string $languageKey): void
86  {
87  if ($languageKey instanceof ‪Locale) {
88  $this->locale = $languageKey;
89  } else {
90  $this->locale = $this->locales->createLocale($languageKey);
91  }
92  $this->lang = $this->‪getTypo3LanguageKey();
93  }
94 
102  protected function ‪getLLL(string $index, array $localLanguage): string
103  {
104  if (isset($localLanguage[$this->lang][$index])) {
105  $value = is_string($localLanguage[$this->lang][$index])
106  ? $localLanguage[‪$this->lang][$index]
107  : $localLanguage[‪$this->lang][$index][0]['target'];
108  } elseif (isset($localLanguage['default'][$index])) {
109  $value = is_string($localLanguage['default'][$index])
110  ? $localLanguage['default'][$index]
111  : $localLanguage['default'][$index][0]['target'];
112  } else {
113  $value = '';
114  }
115  return $value;
116  }
117 
131  public function ‪sL($input): string
132  {
133  $input = (string)$input;
134  // early return for empty input to avoid cache and language file reading on first hit.
135  if ($input === '') {
136  return $input;
137  }
138  // Use a constant non-localizable label
139  if (!str_starts_with(trim($input), 'LLL:')) {
140  return $input;
141  }
142 
143  $cacheIdentifier = 'labels_' . (string)$this->locale . '_' . md5($input);
144  $cacheEntry = $this->runtimeCache->get($cacheIdentifier);
145  if ($cacheEntry !== false) {
146  return $cacheEntry;
147  }
148  // Remove the LLL: prefix
149  $restStr = substr(trim($input), 4);
150  $extensionPrefix = '';
151  // ll-file referred to is found in an extension
152  if (‪PathUtility::isExtensionPath(trim($restStr))) {
153  $restStr = substr(trim($restStr), 4);
154  $extensionPrefix = 'EXT:';
155  }
156  $parts = explode(':', trim($restStr));
157  $parts[0] = $extensionPrefix . $parts[0];
158  $labelsFromFile = $this->‪readLLfile($parts[0]);
159  if (is_array($this->‪overrideLabels[$parts[0]] ?? null)) {
160  $labelsFromFile = array_replace_recursive($labelsFromFile, $this->‪overrideLabels[$parts[0]]);
161  }
162  ‪$output = $this->‪getLLL($parts[1] ?? '', $labelsFromFile);
163  $this->runtimeCache->set($cacheIdentifier, ‪$output);
164  return ‪$output;
165  }
166 
175  public function ‪includeLLFile(string $fileRef): array
176  {
177  $localLanguage = $this->‪readLLfile($fileRef);
178  if (!empty($localLanguage)) {
179  $this->labels = array_replace_recursive($this->labels, $localLanguage);
180  }
181  return $localLanguage;
182  }
183 
189  public function ‪translateLabel(array|string $input, string $fallback): string
190  {
191  if (is_array($input) && isset($input[$this->lang])) {
192  return $this->‪sL((string)$input[$this->lang]);
193  }
194  if (is_string($input)) {
195  return $this->‪sL($input);
196  }
197  return $this->‪sL($fallback);
198  }
199 
205  public function getLabelsFromResource(string $fileRef): array
206  {
207  ‪$labelArray = [];
208  $labelsFromFile = $this->‪readLLfile($fileRef);
209  foreach ($labelsFromFile['default'] as $key => $value) {
210  ‪$labelArray[$key] = $this->‪getLLL($key, $labelsFromFile);
211  }
213  }
214 
221  protected function ‪readLLfile(string $fileRef): array
222  {
223  $cacheIdentifier = 'labels_file_' . md5($fileRef . (string)$this->locale);
224  $cacheEntry = $this->runtimeCache->get($cacheIdentifier);
225  if (is_array($cacheEntry)) {
226  return $cacheEntry;
227  }
228 
229  $mainLanguageKey = $this->‪getTypo3LanguageKey();
230  $localLanguage = [];
231  $allLocales = array_merge([$mainLanguageKey], $this->locale->getDependencies());
232  $allLocales = array_reverse($allLocales);
233  foreach ($allLocales as ‪$locale) {
234  $tempLL = $this->localizationFactory->getParsedData($fileRef, ‪$locale);
235  $localLanguage['default'] = $tempLL['default'];
236  if (!isset($localLanguage[$mainLanguageKey])) {
237  $localLanguage[$mainLanguageKey] = $localLanguage['default'];
238  }
239  if ($mainLanguageKey !== 'default') {
240  // Fallback as long as TYPO3 supports "da_DK" and "da-DK"
241  if ((!isset($tempLL[‪$locale]) || $tempLL[‪$locale] === []) && str_contains(‪$locale, '-')) {
242  $underscoredLocale = str_replace('-', '_', ‪$locale);
243  $tempLL = $this->localizationFactory->getParsedData($fileRef, $underscoredLocale);
244  if (isset($tempLL[$underscoredLocale])) {
245  $tempLL[‪$locale] = $tempLL[$underscoredLocale];
246  }
247  }
248  if (isset($tempLL[‪$locale])) {
249  // Merge current language labels onto labels from previous language
250  // This way we have a labels with fall back applied
251  ArrayUtility::mergeRecursiveWithOverrule($localLanguage[$mainLanguageKey], $tempLL[‪$locale], true, false);
252  }
253  }
254  }
255 
256  $this->runtimeCache->set($cacheIdentifier, $localLanguage);
257  return $localLanguage;
258  }
259 
264  public function ‪overrideLabels(string $fileRef, array ‪$labels): void
265  {
266  $localLanguage = [
267  'default' => ‪$labels['default'] ?? [],
268  ];
269  $mainLanguageKey = $this->‪getTypo3LanguageKey();
270  if ($mainLanguageKey !== 'default') {
271  $allLocales = array_merge([$mainLanguageKey], $this->locale->getDependencies());
272  $allLocales = array_reverse($allLocales);
273  foreach ($allLocales as $language) {
274  // Populate the initial values with default, if no labels for the current language are given
275  if (!isset($localLanguage[$mainLanguageKey])) {
276  $localLanguage[$mainLanguageKey] = $localLanguage['default'];
277  }
278  if (isset(‪$labels[$language])) {
279  $localLanguage[$mainLanguageKey] = array_replace_recursive($localLanguage[$mainLanguageKey], ‪$labels[$language]);
280  }
281  }
282  }
283  $this->‪overrideLabels[$fileRef] = $localLanguage;
284  }
285 
286  public function ‪getLocale(): ?‪Locale
287  {
288  return ‪$this->locale;
289  }
290 
291  private function ‪getTypo3LanguageKey(): string
292  {
293  if ($this->locale === null) {
294  return 'default';
295  }
296  if ($this->locale->getName() === 'en') {
297  return 'default';
298  }
299  return $this->locale->getName();
300  }
301 }
‪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:175
‪TYPO3\CMS\Core\Localization\LanguageService\getLLL
‪string getLLL(string $index, array $localLanguage)
Definition: LanguageService.php:102
‪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\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Core\Localization\LanguageService\init
‪init(Locale|string $languageKey)
Definition: LanguageService.php:85
‪TYPO3\CMS\Core\Localization\LanguageService\translateLabel
‪translateLabel(array|string $input, string $fallback)
Definition: LanguageService.php:189
‪TYPO3\CMS\Core\Localization\LanguageService\$labelArray
‪foreach($labelsFromFile['default'] as $key=> $value) return $labelArray
Definition: LanguageService.php:209
‪TYPO3\CMS\Core\Localization
Definition: CacheWarmer.php:18
‪TYPO3\CMS\Core\Localization\LanguageService\getLocale
‪getLocale()
Definition: LanguageService.php:286
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪sL($input)
Definition: LanguageService.php:131
‪TYPO3\CMS\Core\Localization\LanguageService\__construct
‪__construct(protected Locales $locales, protected readonly LocalizationFactory $localizationFactory, protected readonly FrontendInterface $runtimeCache)
Definition: LanguageService.php:67
‪$output
‪$output
Definition: annotationChecker.php:114
‪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:264
‪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:291
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Localization\LanguageService\readLLfile
‪array readLLfile(string $fileRef)
Definition: LanguageService.php:221