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
12namespace Symfony\Component\Translation\Tests\Loader;
13
14use PHPUnit\Framework\TestCase;
15use Symfony\Component\Config\Resource\FileResource;
16use Symfony\Component\Translation\Loader\XliffFileLoader;
17
18class XliffFileLoaderTest extends TestCase
19{
20    public function testLoad()
21    {
22        $loader = new XliffFileLoader();
23        $resource = __DIR__.'/../fixtures/resources.xlf';
24        $catalogue = $loader->load($resource, 'en', 'domain1');
25
26        $this->assertEquals('en', $catalogue->getLocale());
27        $this->assertEquals([new FileResource($resource)], $catalogue->getResources());
28        $this->assertSame([], libxml_get_errors());
29        $this->assertContainsOnly('string', $catalogue->all('domain1'));
30    }
31
32    public function testLoadWithInternalErrorsEnabled()
33    {
34        $internalErrors = libxml_use_internal_errors(true);
35
36        $this->assertSame([], libxml_get_errors());
37
38        $loader = new XliffFileLoader();
39        $resource = __DIR__.'/../fixtures/resources.xlf';
40        $catalogue = $loader->load($resource, 'en', 'domain1');
41
42        $this->assertEquals('en', $catalogue->getLocale());
43        $this->assertEquals([new FileResource($resource)], $catalogue->getResources());
44        $this->assertSame([], libxml_get_errors());
45
46        libxml_clear_errors();
47        libxml_use_internal_errors($internalErrors);
48    }
49
50    public function testLoadWithExternalEntitiesDisabled()
51    {
52        if (\LIBXML_VERSION < 20900) {
53            $disableEntities = libxml_disable_entity_loader(true);
54        }
55
56        $loader = new XliffFileLoader();
57        $resource = __DIR__.'/../fixtures/resources.xlf';
58        $catalogue = $loader->load($resource, 'en', 'domain1');
59
60        if (\LIBXML_VERSION < 20900) {
61            libxml_disable_entity_loader($disableEntities);
62        }
63
64        $this->assertEquals('en', $catalogue->getLocale());
65        $this->assertEquals([new FileResource($resource)], $catalogue->getResources());
66    }
67
68    public function testLoadWithResname()
69    {
70        $loader = new XliffFileLoader();
71        $catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');
72
73        $this->assertEquals(['foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo', 'qux' => 'qux source'], $catalogue->all('domain1'));
74    }
75
76    public function testIncompleteResource()
77    {
78        $loader = new XliffFileLoader();
79        $catalogue = $loader->load(__DIR__.'/../fixtures/resources.xlf', 'en', 'domain1');
80
81        $this->assertEquals(['foo' => 'bar', 'extra' => 'extra', 'key' => '', 'test' => 'with'], $catalogue->all('domain1'));
82    }
83
84    public function testEncoding()
85    {
86        $loader = new XliffFileLoader();
87        $catalogue = $loader->load(__DIR__.'/../fixtures/encoding.xlf', 'en', 'domain1');
88
89        $this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1'));
90        $this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1'));
91        $this->assertEquals(['notes' => [['content' => utf8_decode('bäz')]], 'id' => '1'], $catalogue->getMetadata('foo', 'domain1'));
92    }
93
94    public function testTargetAttributesAreStoredCorrectly()
95    {
96        $loader = new XliffFileLoader();
97        $catalogue = $loader->load(__DIR__.'/../fixtures/with-attributes.xlf', 'en', 'domain1');
98
99        $metadata = $catalogue->getMetadata('foo', 'domain1');
100        $this->assertEquals('translated', $metadata['target-attributes']['state']);
101    }
102
103    public function testLoadInvalidResource()
104    {
105        $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException');
106        $loader = new XliffFileLoader();
107        $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1');
108    }
109
110    public function testLoadResourceDoesNotValidate()
111    {
112        $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException');
113        $loader = new XliffFileLoader();
114        $loader->load(__DIR__.'/../fixtures/non-valid.xlf', 'en', 'domain1');
115    }
116
117    public function testLoadNonExistingResource()
118    {
119        $this->expectException('Symfony\Component\Translation\Exception\NotFoundResourceException');
120        $loader = new XliffFileLoader();
121        $resource = __DIR__.'/../fixtures/non-existing.xlf';
122        $loader->load($resource, 'en', 'domain1');
123    }
124
125    public function testLoadThrowsAnExceptionIfFileNotLocal()
126    {
127        $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException');
128        $loader = new XliffFileLoader();
129        $resource = 'http://example.com/resources.xlf';
130        $loader->load($resource, 'en', 'domain1');
131    }
132
133    public function testDocTypeIsNotAllowed()
134    {
135        $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException');
136        $this->expectExceptionMessage('Document types are not allowed.');
137        $loader = new XliffFileLoader();
138        $loader->load(__DIR__.'/../fixtures/withdoctype.xlf', 'en', 'domain1');
139    }
140
141    public function testParseEmptyFile()
142    {
143        $loader = new XliffFileLoader();
144        $resource = __DIR__.'/../fixtures/empty.xlf';
145
146        $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException');
147        $this->expectExceptionMessage(sprintf('Unable to load "%s":', $resource));
148
149        $loader->load($resource, 'en', 'domain1');
150    }
151
152    public function testLoadNotes()
153    {
154        $loader = new XliffFileLoader();
155        $catalogue = $loader->load(__DIR__.'/../fixtures/withnote.xlf', 'en', 'domain1');
156
157        $this->assertEquals(['notes' => [['priority' => 1, 'content' => 'foo']], 'id' => '1'], $catalogue->getMetadata('foo', 'domain1'));
158        // message without target
159        $this->assertEquals(['notes' => [['content' => 'bar', 'from' => 'foo']], 'id' => '2'], $catalogue->getMetadata('extra', 'domain1'));
160        // message with empty target
161        $this->assertEquals(['notes' => [['content' => 'baz'], ['priority' => 2, 'from' => 'bar', 'content' => 'qux']], 'id' => '123'], $catalogue->getMetadata('key', 'domain1'));
162    }
163
164    public function testLoadVersion2()
165    {
166        $loader = new XliffFileLoader();
167        $resource = __DIR__.'/../fixtures/resources-2.0.xlf';
168        $catalogue = $loader->load($resource, 'en', 'domain1');
169
170        $this->assertEquals('en', $catalogue->getLocale());
171        $this->assertEquals([new FileResource($resource)], $catalogue->getResources());
172        $this->assertSame([], libxml_get_errors());
173
174        $domains = $catalogue->all();
175        $this->assertCount(3, $domains['domain1']);
176        $this->assertContainsOnly('string', $catalogue->all('domain1'));
177
178        // target attributes
179        $this->assertEquals(['target-attributes' => ['order' => 1]], $catalogue->getMetadata('bar', 'domain1'));
180    }
181
182    public function testLoadVersion2WithNoteMeta()
183    {
184        $loader = new XliffFileLoader();
185        $resource = __DIR__.'/../fixtures/resources-notes-meta.xlf';
186        $catalogue = $loader->load($resource, 'en', 'domain1');
187
188        $this->assertEquals('en', $catalogue->getLocale());
189        $this->assertEquals([new FileResource($resource)], $catalogue->getResources());
190        $this->assertSame([], libxml_get_errors());
191
192        // test for "foo" metadata
193        $this->assertTrue($catalogue->defines('foo', 'domain1'));
194        $metadata = $catalogue->getMetadata('foo', 'domain1');
195        $this->assertNotEmpty($metadata);
196        $this->assertCount(3, $metadata['notes']);
197
198        $this->assertEquals('state', $metadata['notes'][0]['category']);
199        $this->assertEquals('new', $metadata['notes'][0]['content']);
200
201        $this->assertEquals('approved', $metadata['notes'][1]['category']);
202        $this->assertEquals('true', $metadata['notes'][1]['content']);
203
204        $this->assertEquals('section', $metadata['notes'][2]['category']);
205        $this->assertEquals('1', $metadata['notes'][2]['priority']);
206        $this->assertEquals('user login', $metadata['notes'][2]['content']);
207
208        // test for "baz" metadata
209        $this->assertTrue($catalogue->defines('baz', 'domain1'));
210        $metadata = $catalogue->getMetadata('baz', 'domain1');
211        $this->assertNotEmpty($metadata);
212        $this->assertCount(2, $metadata['notes']);
213
214        $this->assertEquals('x', $metadata['notes'][0]['id']);
215        $this->assertEquals('x_content', $metadata['notes'][0]['content']);
216
217        $this->assertEquals('target', $metadata['notes'][1]['appliesTo']);
218        $this->assertEquals('quality', $metadata['notes'][1]['category']);
219        $this->assertEquals('Fuzzy', $metadata['notes'][1]['content']);
220    }
221
222    public function testLoadVersion2WithMultiSegmentUnit()
223    {
224        $loader = new XliffFileLoader();
225        $resource = __DIR__.'/../fixtures/resources-2.0-multi-segment-unit.xlf';
226        $catalog = $loader->load($resource, 'en', 'domain1');
227
228        $this->assertSame('en', $catalog->getLocale());
229        $this->assertEquals([new FileResource($resource)], $catalog->getResources());
230        $this->assertFalse(libxml_get_last_error());
231
232        // test for "foo" metadata
233        $this->assertTrue($catalog->defines('foo', 'domain1'));
234        $metadata = $catalog->getMetadata('foo', 'domain1');
235        $this->assertNotEmpty($metadata);
236        $this->assertCount(1, $metadata['notes']);
237
238        $this->assertSame('processed', $metadata['notes'][0]['category']);
239        $this->assertSame('true', $metadata['notes'][0]['content']);
240
241        // test for "bar" metadata
242        $this->assertTrue($catalog->defines('bar', 'domain1'));
243        $metadata = $catalog->getMetadata('bar', 'domain1');
244        $this->assertNotEmpty($metadata);
245        $this->assertCount(1, $metadata['notes']);
246
247        $this->assertSame('processed', $metadata['notes'][0]['category']);
248        $this->assertSame('true', $metadata['notes'][0]['content']);
249    }
250}
251