From 3d12ac457bb8711f157f39c3dc2224834cd11fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 8 Sep 2024 20:55:43 +0200 Subject: [PATCH] [Translation] Added segment-attributes metadata for Xliff2 files to preserve the "state" attribute of translations --- .../Component/Translation/CHANGELOG.md | 2 ++ .../Translation/Dumper/XliffFileDumper.php | 6 +++++ .../Translation/Loader/XliffFileLoader.php | 7 ++++++ .../Tests/Dumper/XliffFileDumperTest.php | 18 +++++++++++++ .../resources-2.0-segment-attributes.xlf | 17 +++++++++++++ .../Tests/Loader/XliffFileLoaderTest.php | 25 +++++++++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 src/Symfony/Component/Translation/Tests/Fixtures/resources-2.0-segment-attributes.xlf diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 332bf8a31fef4..0d9382a216ff5 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * Make `ProviderFactoryTestCase` and `ProviderTestCase` compatible with PHPUnit 10+ * Add `lint:translations` command * Deprecate passing an escape character to `CsvFileLoader::setCsvControl()` + * Make Xliff 2.0 attributes in segment element available as `segment-attributes` + metadata returned by `XliffFileLoader` and make `XliffFileDumper` write them to the file 7.1 --- diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 23564223b8a93..b41394c193789 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -193,6 +193,12 @@ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ? $segment = $translation->appendChild($dom->createElement('segment')); + if ($this->hasMetadataArrayInfo('segment-attributes', $metadata)) { + foreach ($metadata['segment-attributes'] as $name => $value) { + $segment->setAttribute($name, $value); + } + } + $s = $segment->appendChild($dom->createElement('source')); $s->appendChild($dom->createTextNode($source)); diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php index 3a21ac6aedfa1..e76245dac49fa 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -172,6 +172,13 @@ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, s $catalogue->set((string) $source, $target, $domain); $metadata = []; + if ($segment->attributes()) { + $metadata['segment-attributes'] = []; + foreach ($segment->attributes() as $key => $value) { + $metadata['segment-attributes'][$key] = (string) $value; + } + } + if (isset($segment->target) && $segment->target->attributes()) { $metadata['target-attributes'] = []; foreach ($segment->target->attributes() as $key => $value) { diff --git a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php index f9ae8986f52fe..73e6681716def 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -147,4 +147,22 @@ public function testDumpCatalogueWithXliffExtension() $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR']) ); } + + public function testFormatCatalogueXliff2WithSegmentAttributes() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add([ + 'foo' => 'bar', + 'key' => '', + ]); + $catalogue->setMetadata('foo', ['segment-attributes' => ['state' => 'translated']]); + $catalogue->setMetadata('key', ['segment-attributes' => ['state' => 'translated', 'subState' => 'My Value']]); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../Fixtures/resources-2.0-segment-attributes.xlf', + $dumper->formatCatalogue($catalogue, 'messages', ['default_locale' => 'fr_FR', 'xliff_version' => '2.0']) + ); + } } diff --git a/src/Symfony/Component/Translation/Tests/Fixtures/resources-2.0-segment-attributes.xlf b/src/Symfony/Component/Translation/Tests/Fixtures/resources-2.0-segment-attributes.xlf new file mode 100644 index 0000000000000..0db7df5c8b703 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/Fixtures/resources-2.0-segment-attributes.xlf @@ -0,0 +1,17 @@ + + + + + + foo + bar + + + + + key + + + + + diff --git a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php index bc0e76a48b181..af20f9e7a5e1e 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php @@ -362,4 +362,29 @@ public function testLoadVersion2WithName() $this->assertEquals(['foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo', 'qux' => 'qux source'], $catalogue->all('domain1')); } + + public function testLoadVersion2WithSegmentAttributes() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../Fixtures/resources-2.0-segment-attributes.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + // test for "foo" metadata + $this->assertTrue($catalogue->defines('foo', 'domain1')); + $metadata = $catalogue->getMetadata('foo', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(1, $metadata['segment-attributes']); + $this->assertArrayHasKey('state', $metadata['segment-attributes']); + $this->assertSame('translated', $metadata['segment-attributes']['state']); + + // test for "key" metadata + $this->assertTrue($catalogue->defines('key', 'domain1')); + $metadata = $catalogue->getMetadata('key', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(2, $metadata['segment-attributes']); + $this->assertArrayHasKey('state', $metadata['segment-attributes']); + $this->assertSame('translated', $metadata['segment-attributes']['state']); + $this->assertArrayHasKey('subState', $metadata['segment-attributes']); + $this->assertSame('My Value', $metadata['segment-attributes']['subState']); + } }