Skip to content

Commit d70bb1b

Browse files
committed
#282 Added warning for dangling comments in the end of the file, added method getWarnings() and introduced new function (loadStringExtended) to avoid breaking the Gettext\Loader\Loader contract
1 parent 3347517 commit d70bb1b

1 file changed

Lines changed: 41 additions & 20 deletions

File tree

src/Loader/StrictPoLoader.php

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
*/
1313
final class StrictPoLoader extends Loader
1414
{
15-
/** @var string[] */
16-
public $warnings = [];
17-
1815
/** @var Translations */
1916
private $translations;
2017
/** @var Translation */
@@ -31,15 +28,26 @@ final class StrictPoLoader extends Loader
3128
private $inPreviousComment;
3229
/** @var bool */
3330
private $throwOnWarning;
31+
/** @var string[] */
32+
private $warnings = [];
3433

3534
/**
3635
* Generates a Translations object from a .po based string
3736
*/
38-
public function loadString(
37+
public function loadString(string $string, Translations $translations = null): Translations
38+
{
39+
return $this->loadStringExtended(...func_get_args());
40+
}
41+
42+
/**
43+
* Generates a Translations object from a .po based string with extra options
44+
*/
45+
public function loadStringExtended(
3946
string $string,
4047
Translations $translations = null,
4148
bool $throwOnWarning = false
42-
): Translations {
49+
): Translations
50+
{
4351
$this->data = $string;
4452
$this->position = 0;
4553
$this->translations = parent::loadString($string, $translations);
@@ -49,6 +57,9 @@ public function loadString(
4957
$this->warnings = [];
5058
for ($this->newEntry(); $this->getChar() !== null; $this->newEntry()) {
5159
while ($this->readComment());
60+
if ($this->getChar() === null) {
61+
$this->addWarning("Comment ignored at the end of the string at byte {$this->position}");
62+
}
5263
$this->readContext();
5364
$this->readOriginal();
5465
if ($this->readPlural() && $this->readPluralTranslation(true)) {
@@ -65,6 +76,15 @@ public function loadString(
6576
return $this->translations;
6677
}
6778

79+
/**
80+
* Retrieves the collected warnings
81+
* @return string[]
82+
*/
83+
public function getWarnings(): array
84+
{
85+
return $this->warnings;
86+
}
87+
6888
/**
6989
* Prepares to parse a new translation
7090
*/
@@ -88,9 +108,9 @@ private function saveEntry(): void
88108
throw new Exception("Duplicated entry at byte {$this->position}");
89109
}
90110
if ($this->pluralCount !== null && $this->translation->getPlural() !== null
91-
&& count($this->translation->getPluralTranslations()) < $this->pluralCount) {
92-
$this->addWarning("The translation doesn't have all the {$this->pluralCount} "
93-
. "plural forms at byte {$this->position}");
111+
&& ($translationCount = count($this->translation->getPluralTranslations())) !== ($this->pluralCount - 1)) {
112+
$this->addWarning("The translation has {$translationCount} plural forms, "
113+
."while the header expects {$this->pluralCount} at byte {$this->position}");
94114
}
95115
$this->translations->add($this->translation);
96116
}
@@ -114,7 +134,7 @@ private function readPreviousTranslationComment(): bool
114134
/**
115135
* Attempts to read whitespace characters, also might skip complex comment prologs when needed
116136
*/
117-
private function readWhiteSpace(): bool
137+
private function readWhitespace(): bool
118138
{
119139
$position = $this->position;
120140
while ((ctype_space($this->getChar() ?? '') && $this->nextChar())
@@ -258,11 +278,11 @@ private function readQuotedString(): string
258278
}
259279
}
260280
if (!$this->readChar('"')) {
261-
throw new Exception("Expected an ending quote at byte {$this->position}");
281+
throw new Exception("Expected a closing quote at byte {$this->position}");
262282
}
263283
// Saves a checkpoint and attempts to read a new sequence
264284
$checkpoint = $this->position;
265-
$this->readWhiteSpace();
285+
$this->readWhitespace();
266286
}
267287

268288
return $data;
@@ -273,7 +293,7 @@ private function readQuotedString(): string
273293
*/
274294
private function readComment(): bool
275295
{
276-
$this->readWhiteSpace();
296+
$this->readWhitespace();
277297
if (!$this->readChar('#')) {
278298
return false;
279299
}
@@ -336,7 +356,7 @@ private function readComment(): bool
336356
private function readIdentifier(string $identifier, bool $throwIfNotFound = false): ?string
337357
{
338358
$checkpoint = $this->position;
339-
$this->readWhiteSpace();
359+
$this->readWhitespace();
340360
if (!$this->readString($identifier)) {
341361
if ($throwIfNotFound) {
342362
throw new Exception("Expected $identifier at byte {$this->position}");
@@ -345,7 +365,7 @@ private function readIdentifier(string $identifier, bool $throwIfNotFound = fals
345365

346366
return null;
347367
}
348-
$this->readWhiteSpace();
368+
$this->readWhitespace();
349369

350370
return $this->readQuotedString();
351371
}
@@ -392,11 +412,11 @@ private function readPlural(): bool
392412
*/
393413
private function readTranslation(): void
394414
{
395-
$this->readWhiteSpace();
415+
$this->readWhitespace();
396416
if (!$this->readString('msgstr')) {
397417
throw new Exception("Expected msgstr at byte {$this->position}");
398418
}
399-
$this->readWhiteSpace();
419+
$this->readWhitespace();
400420
$data = $this->readQuotedString();
401421
// The header might be surrounded by newlines
402422
if ($this->translation->getOriginal() !== '') {
@@ -410,22 +430,23 @@ private function readTranslation(): void
410430
*/
411431
private function readPluralTranslation(bool $throwIfNotFound = false): bool
412432
{
413-
$this->readWhiteSpace();
433+
$this->readWhitespace();
414434
if (!$this->readString('msgstr')) {
415435
if ($throwIfNotFound) {
416436
throw new Exception("Expected indexed msgstr at byte {$this->position}");
417437
}
418438

419439
return false;
420440
}
421-
$this->readWhiteSpace();
441+
$this->readWhitespace();
422442
if (!$this->readChar('[')) {
423443
throw new Exception("Expected character \"[\" at byte {$this->position}");
424444
}
445+
$this->readWhitespace();
425446
if (!strlen($index = $this->readNumber())) {
426447
throw new Exception("Expected msgstr index at byte {$this->position}");
427448
}
428-
$this->readWhiteSpace();
449+
$this->readWhitespace();
429450
if (!$this->readChar(']')) {
430451
throw new Exception("Expected character \"]\" at byte {$this->position}");
431452
}
@@ -436,7 +457,7 @@ private function readPluralTranslation(bool $throwIfNotFound = false): bool
436457
if (count($translations) !== (int) $index) {
437458
throw new Exception("The msgstr has an invalid index at byte {$this->position}");
438459
}
439-
$this->readWhiteSpace();
460+
$this->readWhitespace();
440461
$data = $this->readQuotedString();
441462
$translations[] = $data;
442463
$this->checkNewLine($data, 'msgstr');

0 commit comments

Comments
 (0)