Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / symfony / translation / Tests / TranslatorTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Translation\Tests;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\Translation\Translator;
16 use Symfony\Component\Translation\Loader\ArrayLoader;
17 use Symfony\Component\Translation\MessageCatalogue;
18
19 class TranslatorTest extends TestCase
20 {
21     /**
22      * @dataProvider      getInvalidLocalesTests
23      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
24      */
25     public function testConstructorInvalidLocale($locale)
26     {
27         new Translator($locale);
28     }
29
30     /**
31      * @dataProvider getValidLocalesTests
32      */
33     public function testConstructorValidLocale($locale)
34     {
35         $translator = new Translator($locale);
36
37         $this->assertEquals($locale, $translator->getLocale());
38     }
39
40     public function testConstructorWithoutLocale()
41     {
42         $translator = new Translator(null);
43
44         $this->assertNull($translator->getLocale());
45     }
46
47     public function testSetGetLocale()
48     {
49         $translator = new Translator('en');
50
51         $this->assertEquals('en', $translator->getLocale());
52
53         $translator->setLocale('fr');
54         $this->assertEquals('fr', $translator->getLocale());
55     }
56
57     /**
58      * @dataProvider      getInvalidLocalesTests
59      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
60      */
61     public function testSetInvalidLocale($locale)
62     {
63         $translator = new Translator('fr');
64         $translator->setLocale($locale);
65     }
66
67     /**
68      * @dataProvider getValidLocalesTests
69      */
70     public function testSetValidLocale($locale)
71     {
72         $translator = new Translator($locale);
73         $translator->setLocale($locale);
74
75         $this->assertEquals($locale, $translator->getLocale());
76     }
77
78     public function testGetCatalogue()
79     {
80         $translator = new Translator('en');
81
82         $this->assertEquals(new MessageCatalogue('en'), $translator->getCatalogue());
83
84         $translator->setLocale('fr');
85         $this->assertEquals(new MessageCatalogue('fr'), $translator->getCatalogue('fr'));
86     }
87
88     public function testGetCatalogueReturnsConsolidatedCatalogue()
89     {
90         /*
91          * This will be useful once we refactor so that different domains will be loaded lazily (on-demand).
92          * In that case, getCatalogue() will probably have to load all missing domains in order to return
93          * one complete catalogue.
94          */
95
96         $locale = 'whatever';
97         $translator = new Translator($locale);
98         $translator->addLoader('loader-a', new ArrayLoader());
99         $translator->addLoader('loader-b', new ArrayLoader());
100         $translator->addResource('loader-a', array('foo' => 'foofoo'), $locale, 'domain-a');
101         $translator->addResource('loader-b', array('bar' => 'foobar'), $locale, 'domain-b');
102
103         /*
104          * Test that we get a single catalogue comprising messages
105          * from different loaders and different domains
106          */
107         $catalogue = $translator->getCatalogue($locale);
108         $this->assertTrue($catalogue->defines('foo', 'domain-a'));
109         $this->assertTrue($catalogue->defines('bar', 'domain-b'));
110     }
111
112     public function testSetFallbackLocales()
113     {
114         $translator = new Translator('en');
115         $translator->addLoader('array', new ArrayLoader());
116         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
117         $translator->addResource('array', array('bar' => 'foobar'), 'fr');
118
119         // force catalogue loading
120         $translator->trans('bar');
121
122         $translator->setFallbackLocales(array('fr'));
123         $this->assertEquals('foobar', $translator->trans('bar'));
124     }
125
126     public function testSetFallbackLocalesMultiple()
127     {
128         $translator = new Translator('en');
129         $translator->addLoader('array', new ArrayLoader());
130         $translator->addResource('array', array('foo' => 'foo (en)'), 'en');
131         $translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');
132
133         // force catalogue loading
134         $translator->trans('bar');
135
136         $translator->setFallbackLocales(array('fr_FR', 'fr'));
137         $this->assertEquals('bar (fr)', $translator->trans('bar'));
138     }
139
140     /**
141      * @dataProvider      getInvalidLocalesTests
142      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
143      */
144     public function testSetFallbackInvalidLocales($locale)
145     {
146         $translator = new Translator('fr');
147         $translator->setFallbackLocales(array('fr', $locale));
148     }
149
150     /**
151      * @dataProvider getValidLocalesTests
152      */
153     public function testSetFallbackValidLocales($locale)
154     {
155         $translator = new Translator($locale);
156         $translator->setFallbackLocales(array('fr', $locale));
157         // no assertion. this method just asserts that no exception is thrown
158         $this->addToAssertionCount(1);
159     }
160
161     public function testTransWithFallbackLocale()
162     {
163         $translator = new Translator('fr_FR');
164         $translator->setFallbackLocales(array('en'));
165
166         $translator->addLoader('array', new ArrayLoader());
167         $translator->addResource('array', array('bar' => 'foobar'), 'en');
168
169         $this->assertEquals('foobar', $translator->trans('bar'));
170     }
171
172     /**
173      * @dataProvider      getInvalidLocalesTests
174      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
175      */
176     public function testAddResourceInvalidLocales($locale)
177     {
178         $translator = new Translator('fr');
179         $translator->addResource('array', array('foo' => 'foofoo'), $locale);
180     }
181
182     /**
183      * @dataProvider getValidLocalesTests
184      */
185     public function testAddResourceValidLocales($locale)
186     {
187         $translator = new Translator('fr');
188         $translator->addResource('array', array('foo' => 'foofoo'), $locale);
189         // no assertion. this method just asserts that no exception is thrown
190         $this->addToAssertionCount(1);
191     }
192
193     public function testAddResourceAfterTrans()
194     {
195         $translator = new Translator('fr');
196         $translator->addLoader('array', new ArrayLoader());
197
198         $translator->setFallbackLocales(array('en'));
199
200         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
201         $this->assertEquals('foofoo', $translator->trans('foo'));
202
203         $translator->addResource('array', array('bar' => 'foobar'), 'en');
204         $this->assertEquals('foobar', $translator->trans('bar'));
205     }
206
207     /**
208      * @dataProvider      getTransFileTests
209      * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
210      */
211     public function testTransWithoutFallbackLocaleFile($format, $loader)
212     {
213         $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
214         $translator = new Translator('en');
215         $translator->addLoader($format, new $loaderClass());
216         $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en');
217         $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en');
218
219         // force catalogue loading
220         $translator->trans('foo');
221     }
222
223     /**
224      * @dataProvider getTransFileTests
225      */
226     public function testTransWithFallbackLocaleFile($format, $loader)
227     {
228         $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
229         $translator = new Translator('en_GB');
230         $translator->addLoader($format, new $loaderClass());
231         $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en_GB');
232         $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en', 'resources');
233
234         $this->assertEquals('bar', $translator->trans('foo', array(), 'resources'));
235     }
236
237     public function testTransWithFallbackLocaleBis()
238     {
239         $translator = new Translator('en_US');
240         $translator->addLoader('array', new ArrayLoader());
241         $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
242         $translator->addResource('array', array('bar' => 'foobar'), 'en');
243         $this->assertEquals('foobar', $translator->trans('bar'));
244     }
245
246     public function testTransWithFallbackLocaleTer()
247     {
248         $translator = new Translator('fr_FR');
249         $translator->addLoader('array', new ArrayLoader());
250         $translator->addResource('array', array('foo' => 'foo (en_US)'), 'en_US');
251         $translator->addResource('array', array('bar' => 'bar (en)'), 'en');
252
253         $translator->setFallbackLocales(array('en_US', 'en'));
254
255         $this->assertEquals('foo (en_US)', $translator->trans('foo'));
256         $this->assertEquals('bar (en)', $translator->trans('bar'));
257     }
258
259     public function testTransNonExistentWithFallback()
260     {
261         $translator = new Translator('fr');
262         $translator->setFallbackLocales(array('en'));
263         $translator->addLoader('array', new ArrayLoader());
264         $this->assertEquals('non-existent', $translator->trans('non-existent'));
265     }
266
267     /**
268      * @expectedException \Symfony\Component\Translation\Exception\RuntimeException
269      */
270     public function testWhenAResourceHasNoRegisteredLoader()
271     {
272         $translator = new Translator('en');
273         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
274
275         $translator->trans('foo');
276     }
277
278     public function testNestedFallbackCatalogueWhenUsingMultipleLocales()
279     {
280         $translator = new Translator('fr');
281         $translator->setFallbackLocales(array('ru', 'en'));
282
283         $translator->getCatalogue('fr');
284
285         $this->assertNotNull($translator->getCatalogue('ru')->getFallbackCatalogue());
286     }
287
288     public function testFallbackCatalogueResources()
289     {
290         $translator = new Translator('en_GB');
291         $translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
292         $translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
293         $translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
294
295         // force catalogue loading
296         $this->assertEquals('bar', $translator->trans('foo', array()));
297
298         $resources = $translator->getCatalogue('en')->getResources();
299         $this->assertCount(1, $resources);
300         $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'resources.yml', $resources);
301
302         $resources = $translator->getCatalogue('en_GB')->getResources();
303         $this->assertCount(2, $resources);
304         $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'empty.yml', $resources);
305         $this->assertContains(__DIR__.DIRECTORY_SEPARATOR.'fixtures'.DIRECTORY_SEPARATOR.'resources.yml', $resources);
306     }
307
308     /**
309      * @dataProvider getTransTests
310      */
311     public function testTrans($expected, $id, $translation, $parameters, $locale, $domain)
312     {
313         $translator = new Translator('en');
314         $translator->addLoader('array', new ArrayLoader());
315         $translator->addResource('array', array((string) $id => $translation), $locale, $domain);
316
317         $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale));
318     }
319
320     /**
321      * @dataProvider      getInvalidLocalesTests
322      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
323      */
324     public function testTransInvalidLocale($locale)
325     {
326         $translator = new Translator('en');
327         $translator->addLoader('array', new ArrayLoader());
328         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
329
330         $translator->trans('foo', array(), '', $locale);
331     }
332
333     /**
334      * @dataProvider      getValidLocalesTests
335      */
336     public function testTransValidLocale($locale)
337     {
338         $translator = new Translator($locale);
339         $translator->addLoader('array', new ArrayLoader());
340         $translator->addResource('array', array('test' => 'OK'), $locale);
341
342         $this->assertEquals('OK', $translator->trans('test'));
343         $this->assertEquals('OK', $translator->trans('test', array(), null, $locale));
344     }
345
346     /**
347      * @dataProvider getFlattenedTransTests
348      */
349     public function testFlattenedTrans($expected, $messages, $id)
350     {
351         $translator = new Translator('en');
352         $translator->addLoader('array', new ArrayLoader());
353         $translator->addResource('array', $messages, 'fr', '');
354
355         $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr'));
356     }
357
358     /**
359      * @dataProvider getTransChoiceTests
360      */
361     public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
362     {
363         $translator = new Translator('en');
364         $translator->addLoader('array', new ArrayLoader());
365         $translator->addResource('array', array((string) $id => $translation), $locale, $domain);
366
367         $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters, $domain, $locale));
368     }
369
370     /**
371      * @dataProvider      getInvalidLocalesTests
372      * @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
373      */
374     public function testTransChoiceInvalidLocale($locale)
375     {
376         $translator = new Translator('en');
377         $translator->addLoader('array', new ArrayLoader());
378         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
379
380         $translator->transChoice('foo', 1, array(), '', $locale);
381     }
382
383     /**
384      * @dataProvider      getValidLocalesTests
385      */
386     public function testTransChoiceValidLocale($locale)
387     {
388         $translator = new Translator('en');
389         $translator->addLoader('array', new ArrayLoader());
390         $translator->addResource('array', array('foo' => 'foofoo'), 'en');
391
392         $translator->transChoice('foo', 1, array(), '', $locale);
393         // no assertion. this method just asserts that no exception is thrown
394         $this->addToAssertionCount(1);
395     }
396
397     public function getTransFileTests()
398     {
399         return array(
400             array('csv', 'CsvFileLoader'),
401             array('ini', 'IniFileLoader'),
402             array('mo', 'MoFileLoader'),
403             array('po', 'PoFileLoader'),
404             array('php', 'PhpFileLoader'),
405             array('ts', 'QtFileLoader'),
406             array('xlf', 'XliffFileLoader'),
407             array('yml', 'YamlFileLoader'),
408             array('json', 'JsonFileLoader'),
409         );
410     }
411
412     public function getTransTests()
413     {
414         return array(
415             array('Symfony est super !', 'Symfony is great!', 'Symfony est super !', array(), 'fr', ''),
416             array('Symfony est awesome !', 'Symfony is %what%!', 'Symfony est %what% !', array('%what%' => 'awesome'), 'fr', ''),
417             array('Symfony est super !', new StringClass('Symfony is great!'), 'Symfony est super !', array(), 'fr', ''),
418         );
419     }
420
421     public function getFlattenedTransTests()
422     {
423         $messages = array(
424             'symfony' => array(
425                 'is' => array(
426                     'great' => 'Symfony est super!',
427                 ),
428             ),
429             'foo' => array(
430                 'bar' => array(
431                     'baz' => 'Foo Bar Baz',
432                 ),
433                 'baz' => 'Foo Baz',
434             ),
435         );
436
437         return array(
438             array('Symfony est super!', $messages, 'symfony.is.great'),
439             array('Foo Bar Baz', $messages, 'foo.bar.baz'),
440             array('Foo Baz', $messages, 'foo.baz'),
441         );
442     }
443
444     public function getTransChoiceTests()
445     {
446         return array(
447             array('Il y a 0 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array(), 'fr', ''),
448             array('Il y a 1 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array(), 'fr', ''),
449             array('Il y a 10 pommes', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array(), 'fr', ''),
450
451             array('Il y a 0 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 0, array(), 'fr', ''),
452             array('Il y a 1 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 1, array(), 'fr', ''),
453             array('Il y a 10 pommes', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 10, array(), 'fr', ''),
454
455             array('Il y a 0 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array(), 'fr', ''),
456             array('Il y a 1 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array(), 'fr', ''),
457             array('Il y a 10 pommes', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array(), 'fr', ''),
458
459             array('Il n\'y a aucune pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array(), 'fr', ''),
460             array('Il y a 1 pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array(), 'fr', ''),
461             array('Il y a 10 pommes', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array(), 'fr', ''),
462
463             array('Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array(), 'fr', ''),
464
465             // Override %count% with a custom value
466             array('Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 2, array('%count%' => 'quelques'), 'fr', ''),
467         );
468     }
469
470     public function getInvalidLocalesTests()
471     {
472         return array(
473             array('fr FR'),
474             array('français'),
475             array('fr+en'),
476             array('utf#8'),
477             array('fr&en'),
478             array('fr~FR'),
479             array(' fr'),
480             array('fr '),
481             array('fr*'),
482             array('fr/FR'),
483             array('fr\\FR'),
484         );
485     }
486
487     public function getValidLocalesTests()
488     {
489         return array(
490             array(''),
491             array(null),
492             array('fr'),
493             array('francais'),
494             array('FR'),
495             array('frFR'),
496             array('fr-FR'),
497             array('fr_FR'),
498             array('fr.FR'),
499             array('fr-FR.UTF8'),
500             array('sr@latin'),
501         );
502     }
503
504     public function testTransChoiceFallback()
505     {
506         $translator = new Translator('ru');
507         $translator->setFallbackLocales(array('en'));
508         $translator->addLoader('array', new ArrayLoader());
509         $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en');
510
511         $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
512     }
513
514     public function testTransChoiceFallbackBis()
515     {
516         $translator = new Translator('ru');
517         $translator->setFallbackLocales(array('en_US', 'en'));
518         $translator->addLoader('array', new ArrayLoader());
519         $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en_US');
520
521         $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
522     }
523
524     public function testTransChoiceFallbackWithNoTranslation()
525     {
526         $translator = new Translator('ru');
527         $translator->setFallbackLocales(array('en'));
528         $translator->addLoader('array', new ArrayLoader());
529
530         // consistent behavior with Translator::trans(), which returns the string
531         // unchanged if it can't be found
532         $this->assertEquals('some_message2', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
533     }
534 }
535
536 class StringClass
537 {
538     protected $str;
539
540     public function __construct($str)
541     {
542         $this->str = $str;
543     }
544
545     public function __toString()
546     {
547         return $this->str;
548     }
549 }