From dc31739288fbdd3ac10f50347a433b35e0658978 Mon Sep 17 00:00:00 2001 From: Stadly Date: Fri, 26 Apr 2019 12:33:43 +0200 Subject: [PATCH] [Translator] Dump native plural formats to po files --- .../Translation/Dumper/PoFileDumper.php | 57 ++++++++++++++++++- .../Tests/Dumper/PoFileDumperTest.php | 13 +++++ .../Tests/Loader/PoFileLoaderTest.php | 6 +- .../Translation/Tests/fixtures/plurals.po | 8 +++ 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php index 5f60086285f9..658ae729654c 100644 --- a/src/Symfony/Component/Translation/Dumper/PoFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/PoFileDumper.php @@ -51,13 +51,66 @@ public function formatCatalogue(MessageCatalogue $messages, $domain, array $opti $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':'); } - $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); - $output .= sprintf('msgstr "%s"'."\n", $this->escape($target)); + $sourceRules = $this->getStandardRules($source); + $targetRules = $this->getStandardRules($target); + if (2 == \count($sourceRules) && $targetRules !== []) { + $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0])); + $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1])); + foreach ($targetRules as $i => $targetRule) { + $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule)); + } + } else { + $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); + $output .= sprintf('msgstr "%s"'."\n", $this->escape($target)); + } } return $output; } + private function getStandardRules(string $id) + { + // Partly copied from TranslatorTrait::trans. + $parts = []; + if (preg_match('/^\|++$/', $id)) { + $parts = explode('|', $id); + } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { + $parts = $matches[0]; + } + + $intervalRegexp = <<<'EOF' +/^(?P + ({\s* + (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) + \s*}) + + | + + (?P[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) +)\s*(?P.*?)$/xs +EOF; + + $standardRules = []; + foreach ($parts as $part) { + $part = trim(str_replace('||', '|', $part)); + + if (preg_match($intervalRegexp, $part)) { + // Explicit rule is not a standard rule. + return []; + } else { + $standardRules[] = $part; + } + } + + return $standardRules; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php index 46df869f89e6..81f35f2d2701 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php @@ -45,4 +45,17 @@ public function testFormatCatalogue() $this->assertStringEqualsFile(__DIR__.'/../fixtures/resources.po', $dumper->formatCatalogue($catalogue, 'messages')); } + + public function testDumpPlurals() + { + $catalogue = new MessageCatalogue('en'); + $catalogue->add([ + 'foo|foos' => 'bar|bars', + '{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars', + ]); + + $dumper = new PoFileDumper(); + + $this->assertStringEqualsFile(__DIR__.'/../fixtures/plurals.po', $dumper->formatCatalogue($catalogue, 'messages')); + } } diff --git a/src/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php b/src/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php index d8e2c1993ba1..0f479dc5eca8 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php @@ -34,7 +34,11 @@ public function testLoadPlurals() $resource = __DIR__.'/../fixtures/plurals.po'; $catalogue = $loader->load($resource, 'en', 'domain1'); - $this->assertEquals(['foo' => 'bar', 'foos' => 'bar|bars'], $catalogue->all('domain1')); + $this->assertEquals([ + 'foo' => 'bar', + 'foos' => 'bar|bars', + '{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars', + ], $catalogue->all('domain1')); $this->assertEquals('en', $catalogue->getLocale()); $this->assertEquals([new FileResource($resource)], $catalogue->getResources()); } diff --git a/src/Symfony/Component/Translation/Tests/fixtures/plurals.po b/src/Symfony/Component/Translation/Tests/fixtures/plurals.po index 439c41ad7fef..5d7b39d80bd3 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/plurals.po +++ b/src/Symfony/Component/Translation/Tests/fixtures/plurals.po @@ -1,5 +1,13 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" + msgid "foo" msgid_plural "foos" msgstr[0] "bar" msgstr[1] "bars" +msgid "{0} no foos|one foo|%count% foos" +msgstr "{0} no bars|one bar|%count% bars"