‪TYPO3CMS  10.4
LocalizationUtilityTest.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 
18 use Prophecy\Argument;
29 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
30 
34 class ‪LocalizationUtilityTest extends UnitTestCase
35 {
42 
48  protected ‪$LOCAL_LANG = [];
49 
54  protected ‪$languageFilePath = '';
55 
59  protected function ‪setUp(): void
60  {
61  parent::setUp();
62  $this->languageFilePath = $this->‪getLanguageFilePath('core');
63  $this->LOCAL_LANG = [
64  $this->languageFilePath => [
65  'default' => [
66  'key1' => [
67  [
68  'source' => 'English label for key1',
69  'target' => 'English label for key1',
70  ]
71  ],
72  'key2' => [
73  [
74  'source' => 'English label for key2',
75  'target' => 'English label for key2',
76  ]
77  ],
78  'key3' => [
79  [
80  'source' => 'English label for key3',
81  'target' => 'English label for key3',
82  ]
83  ],
84  'key4' => [
85  [
86  'source' => 'English label for key4',
87  'target' => 'English label for key4',
88  ]
89  ],
90  'keyWithPlaceholder' => [
91  [
92  'source' => 'English label with number %d',
93  'target' => 'English label with number %d',
94  ]
95  ],
96  ],
97  'dk' => [
98  'key1' => [
99  [
100  'source' => 'English label for key1',
101  'target' => 'Dansk label for key1',
102  ]
103  ],
104  // not translated in dk => no target (llxml)
105  'key2' => [
106  [
107  'source' => 'English label for key2',
108  ]
109  ],
110  'key3' => [
111  [
112  'source' => 'English label for key3',
113  ]
114  ],
115  // not translated in dk => empty target (xliff)
116  'key4' => [
117  [
118  'source' => 'English label for key4',
119  'target' => '',
120  ]
121  ],
122  // not translated in dk => empty target (xliff)
123  'key5' => [
124  [
125  'source' => 'English label for key5',
126  'target' => '',
127  ]
128  ],
129  'keyWithPlaceholder' => [
130  [
131  'source' => 'English label with number %d',
132  ]
133  ],
134  ],
135  // fallback language for labels which are not translated in dk
136  'dk_alt' => [
137  'key1' => [
138  [
139  'source' => 'English label for key1',
140  ]
141  ],
142  'key2' => [
143  [
144  'source' => 'English label for key2',
145  'target' => 'Dansk alternative label for key2',
146  ]
147  ],
148  'key3' => [
149  [
150  'source' => 'English label for key3',
151  ]
152  ],
153  // not translated in dk_alt => empty target (xliff)
154  'key4' => [
155  [
156  'source' => 'English label for key4',
157  'target' => '',
158  ]
159  ],
160  'key5' => [
161  [
162  'source' => 'English label for key5',
163  'target' => 'Dansk alternative label for key5',
164  ]
165  ],
166  'keyWithPlaceholder' => [
167  [
168  'source' => 'English label with number %d',
169  ]
170  ],
171  ],
172 
173  ],
174  ];
175 
176  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
177 
178  $this->configurationManagerInterfaceProphecy = $this->prophesize(ConfigurationManagerInterface::class);
179  $property = $reflectionClass->getProperty('configurationManager');
180  $property->setAccessible(true);
181  $property->setValue($this->configurationManagerInterfaceProphecy->reveal());
182 
183  $localizationFactoryProphecy = $this->prophesize(LocalizationFactory::class);
184  GeneralUtility::setSingletonInstance(LocalizationFactory::class, $localizationFactoryProphecy->reveal());
185  $localizationFactoryProphecy->getParsedData(Argument::cetera(), 'foo')->willReturn([]);
186  }
187 
191  protected function ‪tearDown(): void
192  {
193  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
194 
195  $property = $reflectionClass->getProperty('configurationManager');
196  $property->setAccessible(true);
197  $property->setValue(null);
198 
199  $property = $reflectionClass->getProperty('LOCAL_LANG');
200  $property->setAccessible(true);
201  $property->setValue([]);
202 
203  GeneralUtility::purgeInstances();
204 
205  parent::tearDown();
206  }
207 
212  protected function ‪getLanguageFilePath(string $extensionName): string
213  {
214  return 'EXT:' . $extensionName . '/Resources/Private/Language/locallang.xlf';
215  }
216 
220  public function ‪implodeTypoScriptLabelArrayWorks()
221  {
222  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
223  $method = $reflectionClass->getMethod('flattenTypoScriptLabelArray');
224  $method->setAccessible(true);
225 
226  $expected = [
227  'key1' => 'value1',
228  'key2' => 'value2',
229  'key3' => 'value3',
230  'key3.subkey1' => 'subvalue1',
231  'key3.subkey2.subsubkey' => 'val'
232  ];
233  $input = [
234  'key1' => 'value1',
235  'key2' => 'value2',
236  'key3' => [
237  '_typoScriptNodeValue' => 'value3',
238  'subkey1' => 'subvalue1',
239  'subkey2' => [
240  'subsubkey' => 'val'
241  ]
242  ]
243  ];
244  $result = $method->invoke(null, $input);
245  self::assertEquals($expected, $result);
246  }
247 
252  {
253  self::assertNull(‪LocalizationUtility::translate('', 'extbase'));
254  }
255 
260  {
261  self::assertNull(‪LocalizationUtility::translate('', 'extbase', ['argument']));
262  }
263 
267  public function ‪translateDataProvider(): array
268  {
269  return [
270  'get translated key' =>
271  ['key1', 'dk', 'Dansk label for key1'],
272 
273  'fallback to English when translation is missing for key' =>
274  ['key2', 'dk', 'English label for key2'],
275 
276  'fallback to English for non existing language' =>
277  ['key2', 'xx', 'English label for key2'],
278 
279  'replace placeholder with argument' =>
280  ['keyWithPlaceholder', 'default', 'English label with number 100', [], [100]],
281 
282  'get translated key from primary language' =>
283  ['key1', 'dk', 'Dansk label for key1', ['dk_alt']],
284 
285  'fallback to alternative language if translation is missing(llxml)' =>
286  ['key2', 'dk', 'Dansk alternative label for key2', ['dk_alt']],
287 
288  'fallback to alternative language if translation is missing(xlif)' =>
289  ['key5', 'dk', 'Dansk alternative label for key5', ['dk_alt']],
290 
291  'fallback to English for label not translated in dk and dk_alt(llxml)' =>
292  ['key3', 'dk', 'English label for key3', ['dk_alt']],
293 
294  'fallback to English for label not translated in dk and dk_alt(xlif)' =>
295  ['key4', 'dk', 'English label for key4', ['dk_alt']],
296  ];
297  }
298 
308  public function ‪translateTestWithBackendUserLanguage($key, $languageKey, $expected, array $altLanguageKeys = [], array $arguments = null)
309  {
310  $this->configurationManagerInterfaceProphecy
311  ->getConfiguration('Framework', 'core', null)
312  ->willReturn([]);
313 
314  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
315 
316  $property = $reflectionClass->getProperty('LOCAL_LANG');
317  $property->setAccessible(true);
318  $property->setValue($this->LOCAL_LANG);
319 
320  $backendUserAuthenticationProphecy = $this->prophesize(BackendUserAuthentication::class);
321  ‪$GLOBALS['BE_USER'] = $backendUserAuthenticationProphecy->reveal();
322  $backendUserAuthenticationProphecy->uc = [
323  'lang' => $languageKey,
324  ];
326 
327  self::assertEquals($expected, ‪LocalizationUtility::translate($key, 'core', $arguments, null, $altLanguageKeys));
328  }
329 
339  public function ‪translateTestWithExplicitLanguageParameters($key, $languageKey, $expected, array $altLanguageKeys = [], array $arguments = null)
340  {
341  $this->configurationManagerInterfaceProphecy
342  ->getConfiguration('Framework', 'core', null)
343  ->willReturn([]);
344 
345  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
346 
347  $property = $reflectionClass->getProperty('LOCAL_LANG');
348  $property->setAccessible(true);
349  $property->setValue($this->LOCAL_LANG);
350  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
351  $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
352  $cacheManagerProphecy->getCache('l10n')->willReturn($cacheFrontendProphecy->reveal());
353  $cacheFrontendProphecy->get(Argument::cetera())->willReturn(false);
354  $cacheFrontendProphecy->set(Argument::cetera())->willReturn(null);
355  ‪$GLOBALS['LANG'] = new ‪LanguageService(new ‪Locales(), new ‪LocalizationFactory(new ‪LanguageStore(), $cacheManagerProphecy->reveal()));
356  self::assertEquals($expected, ‪LocalizationUtility::translate($key, 'core', $arguments, $languageKey, $altLanguageKeys));
357  }
358 
362  public function ‪loadTypoScriptLabelsProvider(): array
363  {
364  return [
365  'override labels with typoscript' => [
366  'LOCAL_LANG' => [
367  $this->‪getLanguageFilePath('core') => [
368  'dk' => [
369  'key1' => [
370  [
371  'source' => 'English label for key1',
372  'target' => 'Dansk label for key1 core',
373  ]
374  ],
375  'key2' => [
376  [
377  'source' => 'English label for key2',
378  ]
379  ],
380  'key3.subkey1' => [
381  [
382  'source' => 'English label for key3',
383  ]
384  ],
385  ],
386  ],
387  $this->‪getLanguageFilePath('backend') => [
388  'dk' => [
389  'key1' => [
390  [
391  'source' => 'English label for key1',
392  'target' => 'Dansk label for key1 backend',
393  ]
394  ],
395  'key2' => [
396  [
397  'source' => 'English label for key2',
398  ]
399  ],
400  'key3.subkey1' => [
401  [
402  'source' => 'English label for key3',
403  ]
404  ],
405  ],
406  ],
407  ],
408  'typoscript LOCAL_LANG' => [
409  '_LOCAL_LANG' => [
410  'dk' => [
411  'key1' => 'key1 value from TS core',
412  'key3' => [
413  'subkey1' => 'key3.subkey1 value from TS core',
414  // this key doesn't exist in xml files
415  'subkey2' => [
416  'subsubkey' => 'key3.subkey2.subsubkey value from TS core'
417  ]
418  ]
419  ]
420  ]
421  ],
422  'language key' => 'dk',
423  'expected' => [
424  'key1' => [
425  [
426  'source' => 'English label for key1',
427  'target' => 'key1 value from TS core',
428  ]
429  ],
430  'key2' => [
431  [
432  'source' => 'English label for key2',
433  ]
434  ],
435  'key3.subkey1' => [
436  [
437  'source' => 'English label for key3',
438  'target' => 'key3.subkey1 value from TS core',
439  ]
440  ],
441  'key3.subkey2.subsubkey' => [
442  [
443  'target' => 'key3.subkey2.subsubkey value from TS core',
444  ]
445  ],
446  ],
447  ]
448  ];
449  }
450 
461  public function ‪loadTypoScriptLabels(array ‪$LOCAL_LANG, array $typoScriptLocalLang, $languageKey, array $expected)
462  {
463  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
464 
465  $property = $reflectionClass->getProperty('LOCAL_LANG');
466  $property->setAccessible(true);
467  $property->setValue(‪$LOCAL_LANG);
468 
470  $this->configurationManagerInterfaceProphecy
471  ->getConfiguration($configurationType, 'core', null)
472  ->shouldBeCalled()
473  ->willReturn($typoScriptLocalLang);
474 
475  $method = $reflectionClass->getMethod('loadTypoScriptLabels');
476  $method->setAccessible(true);
477  $method->invoke(null, 'core', $this->languageFilePath);
478 
479  $property = $reflectionClass->getProperty('LOCAL_LANG');
480  $property->setAccessible(true);
481  $result = $property->getValue();
482 
483  self::assertEquals($expected, $result[$this->languageFilePath][$languageKey]);
484  }
485 
489  public function ‪clearLabelWithTypoScript()
490  {
491  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
492 
493  $property = $reflectionClass->getProperty('LOCAL_LANG');
494  $property->setAccessible(true);
495  $property->setValue($this->LOCAL_LANG);
496 
497  $typoScriptLocalLang = [
498  '_LOCAL_LANG' => [
499  'dk' => [
500  'key1' => '',
501  ]
502  ]
503  ];
504 
506  $this->configurationManagerInterfaceProphecy
507  ->getConfiguration($configurationType, 'core', null)
508  ->shouldBeCalled()
509  ->willReturn($typoScriptLocalLang);
510 
511  $method = $reflectionClass->getMethod('loadTypoScriptLabels');
512  $method->setAccessible(true);
513  $method->invoke(null, 'core', $this->languageFilePath);
514 
515  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
516  $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
517  $cacheManagerProphecy->getCache('l10n')->willReturn($cacheFrontendProphecy->reveal());
518  $cacheFrontendProphecy->get(Argument::cetera())->willReturn(false);
519  $cacheFrontendProphecy->set(Argument::cetera())->willReturn(null);
520  ‪$GLOBALS['LANG'] = new ‪LanguageService(new ‪Locales(), new ‪LocalizationFactory(new ‪LanguageStore(), $cacheManagerProphecy->reveal()));
521 
522  $result = ‪LocalizationUtility::translate('key1', 'core', null, 'dk');
523  self::assertNotNull($result);
524  self::assertEquals('', $result);
525  }
526 
531  {
532  $this->expectException(\InvalidArgumentException::class);
533  $this->expectExceptionCode(1498144052);
534  ‪LocalizationUtility::translate('foo/bar', '');
535  }
536 
541  {
542  $reflectionClass = new \ReflectionClass(LocalizationUtility::class);
543 
544  $typoScriptLocalLang = [
545  '_LOCAL_LANG' => [
546  'dk' => [
547  'key1' => 'I am a new key and there is no xlf file',
548  ]
549  ]
550  ];
551 
553  $this->configurationManagerInterfaceProphecy
554  ->getConfiguration($configurationType, 'core', null)
555  ->shouldBeCalled()
556  ->willReturn($typoScriptLocalLang);
557 
558  $method = $reflectionClass->getMethod('loadTypoScriptLabels');
559  $method->setAccessible(true);
560  $method->invoke(null, 'core', ''); // setting the language file path to an empty string here
561 
562  $cacheManagerProphecy = $this->prophesize(CacheManager::class);
563  $cacheFrontendProphecy = $this->prophesize(FrontendInterface::class);
564  $cacheManagerProphecy->getCache('l10n')->willReturn($cacheFrontendProphecy->reveal());
565  $cacheFrontendProphecy->get(Argument::cetera())->willReturn(false);
566  $cacheFrontendProphecy->set(Argument::cetera())->willReturn(null);
567  ‪$GLOBALS['LANG'] = new ‪LanguageService(new ‪Locales(), new ‪LocalizationFactory(new ‪LanguageStore(), $cacheManagerProphecy->reveal()));
568 
569  $result = ‪LocalizationUtility::translate('key1', 'core', null, 'dk');
570  self::assertNotNull($result);
571  self::assertEquals('I am a new key and there is no xlf file', $result);
572  }
573 }
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\$configurationManagerInterfaceProphecy
‪ConfigurationManagerInterface $configurationManagerInterfaceProphecy
Definition: LocalizationUtilityTest.php:40
‪TYPO3\CMS\Extbase\Utility\LocalizationUtility
Definition: LocalizationUtility.php:33
‪TYPO3\CMS\Core\Localization\LocalizationFactory
Definition: LocalizationFactory.php:28
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\tearDown
‪tearDown()
Definition: LocalizationUtilityTest.php:188
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:30
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateForEmptyStringKeyReturnsNull
‪translateForEmptyStringKeyReturnsNull()
Definition: LocalizationUtilityTest.php:248
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateWillReturnLabelsFromTsEvenIfNoXlfFileExists
‪translateWillReturnLabelsFromTsEvenIfNoXlfFileExists()
Definition: LocalizationUtilityTest.php:537
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface\CONFIGURATION_TYPE_FRAMEWORK
‪const CONFIGURATION_TYPE_FRAMEWORK
Definition: ConfigurationManagerInterface.php:29
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\implodeTypoScriptLabelArrayWorks
‪implodeTypoScriptLabelArrayWorks()
Definition: LocalizationUtilityTest.php:217
‪TYPO3\CMS\Core\Localization\LanguageStore
Definition: LanguageStore.php:27
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\loadTypoScriptLabelsProvider
‪array loadTypoScriptLabelsProvider()
Definition: LocalizationUtilityTest.php:359
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateTestWithExplicitLanguageParameters
‪translateTestWithExplicitLanguageParameters($key, $languageKey, $expected, array $altLanguageKeys=[], array $arguments=null)
Definition: LocalizationUtilityTest.php:336
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateForEmptyStringKeyWithArgumentsReturnsNull
‪translateForEmptyStringKeyWithArgumentsReturnsNull()
Definition: LocalizationUtilityTest.php:256
‪TYPO3\CMS\Extbase\Tests\Unit\Utility
Definition: DebuggerUtilityTest.php:16
‪TYPO3\CMS\Extbase\Utility\LocalizationUtility\translate
‪static string null translate(string $key, ?string $extensionName=null, array $arguments=null, string $languageKey=null, array $alternativeLanguageKeys=null)
Definition: LocalizationUtility.php:67
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateTestWithBackendUserLanguage
‪translateTestWithBackendUserLanguage($key, $languageKey, $expected, array $altLanguageKeys=[], array $arguments=null)
Definition: LocalizationUtilityTest.php:305
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest
Definition: LocalizationUtilityTest.php:35
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateThrowsExceptionWithEmptyExtensionNameIfKeyIsNotPrefixedWithLLL
‪translateThrowsExceptionWithEmptyExtensionNameIfKeyIsNotPrefixedWithLLL()
Definition: LocalizationUtilityTest.php:527
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\setUp
‪setUp()
Definition: LocalizationUtilityTest.php:56
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\$languageFilePath
‪string $languageFilePath
Definition: LocalizationUtilityTest.php:51
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\getLanguageFilePath
‪string getLanguageFilePath(string $extensionName)
Definition: LocalizationUtilityTest.php:209
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\clearLabelWithTypoScript
‪clearLabelWithTypoScript()
Definition: LocalizationUtilityTest.php:486
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\translateDataProvider
‪array translateDataProvider()
Definition: LocalizationUtilityTest.php:264
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\loadTypoScriptLabels
‪loadTypoScriptLabels(array $LOCAL_LANG, array $typoScriptLocalLang, $languageKey, array $expected)
Definition: LocalizationUtilityTest.php:458
‪TYPO3\CMS\Extbase\Tests\Unit\Utility\LocalizationUtilityTest\$LOCAL_LANG
‪array $LOCAL_LANG
Definition: LocalizationUtilityTest.php:46