-
-
Notifications
You must be signed in to change notification settings - Fork 139
Expand file tree
/
Copy pathStrictPoLoaderTest.php
More file actions
304 lines (286 loc) · 11.4 KB
/
StrictPoLoaderTest.php
File metadata and controls
304 lines (286 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
<?php
declare(strict_types = 1);
namespace Gettext\Tests;
use Gettext\Loader\Loader;
use Gettext\Loader\StrictPoLoader;
class StrictPoLoaderTest extends BasePoLoaderTestCase
{
/**
* @return StrictPoLoader
*/
protected function createPoLoader(): Loader
{
return new StrictPoLoader();
}
public function stringDecodeProvider(): array
{
return array_merge(parent::stringDecodeProvider(), [
// Octal
['"Up to 3 digits, 1 will be skipped \\0\\00\\0001"', "Up to 3 digits, 1 will be skipped \0\0\0001"],
['"\\101\\102"', 'AB'],
// Hexadecimal
['"Works with a single character \\x41\\xA\\xD\\x5A\\x5a"', "Works with a single character A\n\rZZ"],
['"Last hex pair: tab = \\x12345678AAAAaaaa09"', "Last hex pair: tab = \t"],
// Unicode
['"UTF-8, up to 4 digits \u00c0A\u00C1 \u0C0\u41\uC1"', 'UTF-8, up to 4 digits ÀAÁ ÀAÁ'],
['"UTF-32, up to 8 digits \U000000c0A\U00C1 \U0C0\U41\UC1"', 'UTF-32, up to 8 digits ÀAÁ ÀAÁ'],
]);
}
public function testCollapsedSyntax(): void
{
$po = "# comment\nmsgctxt\"ctx\"msgid\"original\"msgstr\"trans\"\"lation\"";
$translations = $this->createPoLoader()->loadString($po);
$this->assertEquals($translations->find('ctx', 'original')->getTranslation(), 'translation');
$this->assertEquals($translations->find('ctx', 'original')->getComments()->toArray()[0], ' comment');
}
public function testPreviousTranslation(): void
{
$po = '#| msgctxt "previous ctx"
#| msgid "previous original"
#| msgid_plural "previous plural"
msgctxt "ctx"
msgid "original"
msgid_plural "plural"
msgstr[0] "translation"';
$translations = $this->createPoLoader()->loadString($po);
$translation = $translations->find('ctx', 'original');
$this->assertNotNull($translation);
$this->assertEquals($translation->getContext(), 'ctx');
$this->assertEquals($translation->getOriginal(), 'original');
$this->assertEquals($translation->getPlural(), 'plural');
$this->assertEquals($translation->getTranslation(), 'translation');
$this->assertEquals($translation->getPreviousContext(), 'previous ctx');
$this->assertEquals($translation->getPreviousOriginal(), 'previous original');
$this->assertEquals($translation->getPreviousPlural(), 'previous plural');
}
public function testDisabledWithPreviousTranslation(): void
{
$po = '#~ #| msgctxt "previous ctx"
#~ #| msgid "previous original"
#~ #| msgid_plural "previous plural"
#~ msgctxt "ctx"
#~ msgid "original"
#~ msgid_plural "plural"
#~ msgstr[0] "translation"';
$translations = $this->createPoLoader()->loadString($po);
$translation = $translations->find('ctx', 'original');
$this->assertNotNull($translation);
$this->assertTrue($translation->isDisabled());
$this->assertEquals($translation->getContext(), 'ctx');
$this->assertEquals($translation->getOriginal(), 'original');
$this->assertEquals($translation->getPlural(), 'plural');
$this->assertEquals($translation->getTranslation(), 'translation');
$this->assertEquals($translation->getPreviousContext(), 'previous ctx');
$this->assertEquals($translation->getPreviousOriginal(), 'previous original');
$this->assertEquals($translation->getPreviousPlural(), 'previous plural');
}
public function badFormattedPoProvider(): array
{
return [
'Duplicated entry' => [
'/Duplicated entry/',
'msgid"original"
msgstr"translation"
msgid"original"
msgstr"translation 2"',
],
'Out of order: msgstr before msgid' => [
'/Expected msgid/',
'msgstr "translation"
msgid "original"',
],
'Out of order: msgctxt before msgid' => [
'/Expected msgid/',
'msgctxt "ctx"
msgstr "translation"
msgid "original"',
],
'Out of order: Comment between the definitions' => [
'/Expected msgstr/',
'msgid "original"
# Unexpected comment
msgstr "translation"',
],
'Out of order: Disabled translations (#~) cannot appear after previous translations (#|)' => [
'/Inconsistent use of #~/',
'#|msgid "previous"
#~msgid "disabled"
#~msgstr "disabled translation"
msgid "original"
msgstr "translation"',
],
'Out of order: msgctxt of a previous translation (#|) must appear before its msgid' => [
'/Cannot redeclare the previous comment/',
'#|msgid "previous"
#|msgctxt "previous context"
#|msgid_plural "previous context"
msgid "original"
msgstr "translation"',
],
'Indexed msgstr: msgid_plural requires an indexed msgstr' => [
'/Expected character "\\["/',
'msgid "original"
msgid_plural "plural"
msgstr "translation"',
],
'Indexed msgstr: After the index 0, the next should be 2' => [
'/The msgstr has an invalid index/',
'msgid "original"
msgid_plural "plural"
msgstr[0] "translation"
msgstr[2] "translation"',
],
'Indexed msgstr: Index has trash data (whitespace is ok)' => [
'/Expected character "]"/',
'msgid "original"
msgid_plural "plural"
msgstr[ 0 ] "translation"
msgstr[1s] "translation"',
],
'Incomplete translation' => [
'/Expected msgstr/',
'msgid "original"',
],
'Incomplete disabled translation' => [
'/Expected msgstr/',
'#~ msgid "original"',
],
'Encoding: No quotes' => [
'/Expected an opening quote/',
'msgid "original"
msgstr translation',
],
'Encoding: Missing opening quote' => [
'/Expected an opening quote/',
'msgid "original"
msgstr translation"',
],
'Encoding: Missing closing quote' => [
'/Expected a closing quot/',
'msgid "original"
msgstr "translation',
],
'Encoding: Unescaped newline (using \\n)' => [
'/Newline character must be escaped/',
"msgid \"original\"
msgstr \"trans\nlation\"",
],
'Encoding: Unescaped newline (using \\r)' => [
'/Newline character must be escaped/',
"msgid \"original\"
msgstr \"trans\rlation\"",
],
'Encoding: Invalid octal digit' => [
'/Invalid escaped character/',
'msgid "original"
msgstr "translation\8"',
],
'Encoding: Octal out of range' => [
'/Octal value out of range/',
'msgid "original"
msgstr "translation\777"',
],
'Encoding: Invalid hexadecimal digit' => [
'/Expected at least 1 occurrence of hexadecimal/',
'msgid "original"
msgstr "translation\xGG"',
],
'Encoding: Invalid unicode digit' => [
'/Expected at least 1 occurrence of hexadecimal/',
'msgid "original"
msgstr "translation\uZZ"',
],
'Invalid identifier "unknown"' => [
'/Expected msgid/',
'unknown "original"
msgstr "translation"',
],
// The checks below depends on the $throwOnWarning = true
'msgid, msgid_plural and msgstr cannot begin nor end with a newline' => [
'/msgstr cannot start nor end with a newline/',
'msgid "original"
msgstr "translation\n"',
true,
],
'Missing header' => [
'/The loaded string has no header translation/',
'msgid "original"
msgstr "translation"',
true,
],
'Duplicated header' => [
'/Header already defined/',
'msgid ""
msgstr "Header: \\n"
"Header: \\n"',
true,
],
'Malformed header name' => [
'/Malformed header name/',
'msgid ""
msgstr "Header\\n"',
true,
],
'Missing standard headers Language/Plural-Forms/Content-Type' => [
'/header not declared or empty/',
'msgid ""
msgstr "Header: Value\\n"',
true,
],
'Two plural forms with just one plural translation' => [
'/The translation has \\d+ plural forms, while the header expects \\d+/',
'msgid ""
msgstr "Language: en_US\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
msgid "original"
msgid_plural "plural"
msgstr[0] "translation"',
true,
],
'Two plural forms with 3 plural translations' => [
'/The translation has \\d+ plural forms, while the header expects \\d+/',
'msgid ""
msgstr "Language: en_US\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
msgid "original"
msgid_plural "plural"
msgstr[0] "translation"
msgstr[1] "translation"
msgstr[2] "translation"',
true,
],
'Dangling comment in the end of the data' => [
'/Comment ignored at the end/',
'msgid "original"
msgstr "translation"
# Dangling comment',
true,
],
'Dangling comment in the end of the data using error report with line/column' => [
'/Comment ignored at the end.*line 4 column 34/',
'msgid "original"
msgstr "translation"
# Dangling comment',
true,
true,
],
];
}
/**
* @dataProvider badFormattedPoProvider
*/
public function testBadFormattedPo(
string $exceptionPattern,
string $po,
bool $throwOnWarning = false,
bool $displayErrorLine = false
): void {
$this->expectExceptionMessageMatches($exceptionPattern);
$loader = $this->createPoLoader();
$loader->throwOnWarning = $throwOnWarning;
$loader->displayErrorLine = $displayErrorLine;
$loader->loadString($po);
}
}