From b913695682f88c483748d8d390118c5528c625b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20S=C3=A1nchez?= Date: Tue, 4 Aug 2015 16:28:45 -0300 Subject: [PATCH] Add support for target attributes. The previous implementation ignored attributes in target nodes in xliff files so they were lost when you load and then dump the same file. This change should fix that problem. --- .../Translation/Dumper/XliffFileDumper.php | 23 +++++++- .../Translation/Loader/XliffFileLoader.php | 56 +++++++++++++------ .../Tests/Dumper/XliffFileDumperTest.php | 35 ++++++++++++ .../Tests/Loader/XliffFileLoaderTest.php | 9 +++ .../Tests/fixtures/with-attributes.xlf | 21 +++++++ 5 files changed, 124 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 58d19733db..47e082c22e 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -70,11 +70,17 @@ class XliffFileDumper extends FileDumper // Does the target contain characters requiring a CDATA section? $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); - $t = $translation->appendChild($dom->createElement('target')); + $targetElement = $dom->createElement('target'); + $metadata = $messages->getMetadata($source, $domain); + if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { + foreach ($metadata['target-attributes'] as $name => $value) { + $targetElement->setAttribute($name, $value); + } + } + $t = $translation->appendChild($targetElement); $t->appendChild($text); - $metadata = $messages->getMetadata($source, $domain); - if (null !== $metadata && array_key_exists('notes', $metadata) && is_array($metadata['notes'])) { + if ($this->hasMetadataArrayInfo('notes', $metadata)) { foreach ($metadata['notes'] as $note) { if (!isset($note['content'])) { continue; @@ -106,4 +112,15 @@ class XliffFileDumper extends FileDumper { return 'xlf'; } + + /** + * @param string $key + * @param array|null $metadata + * + * @return bool + */ + private function hasMetadataArrayInfo($key, $metadata = null) + { + return null !== $metadata && array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || is_array($metadata[$key])); + } } diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php index d2b5407f82..f2cbacb4f0 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -59,24 +59,15 @@ class XliffFileLoader implements LoaderInterface $catalogue->set((string) $source, $target, $domain); - if (isset($translation->note)) { - $notes = array(); - foreach ($translation->note as $xmlNote) { - $noteAttributes = $xmlNote->attributes(); - $note = array('content' => $this->utf8ToCharset((string) $xmlNote, $encoding)); - if (isset($noteAttributes['priority'])) { - $note['priority'] = (int) $noteAttributes['priority']; - } - - if (isset($noteAttributes['from'])) { - $note['from'] = (string) $noteAttributes['from']; - } - - $notes[] = $note; - } - - $catalogue->setMetadata((string) $source, array('notes' => $notes), $domain); + $metadata = array(); + if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) { + $metadata['notes'] = $notes; } + if ($translation->target->attributes()) { + $metadata['target-attributes'] = $translation->target->attributes(); + } + + $catalogue->setMetadata((string) $source, $metadata, $domain); } if (class_exists('Symfony\Component\Config\Resource\FileResource')) { @@ -185,4 +176,35 @@ class XliffFileLoader implements LoaderInterface return $errors; } + + /** + * @param \SimpleXMLElement|null $noteElement + * @param string|null $encoding + * + * @return array + */ + private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, $encoding = null) + { + $notes = array(); + + if (null === $noteElement) { + return $notes; + } + + foreach ($noteElement as $xmlNote) { + $noteAttributes = $xmlNote->attributes(); + $note = array('content' => $this->utf8ToCharset((string) $xmlNote, $encoding)); + if (isset($noteAttributes['priority'])) { + $note['priority'] = (int) $noteAttributes['priority']; + } + + if (isset($noteAttributes['from'])) { + $note['from'] = (string) $noteAttributes['from']; + } + + $notes[] = $note; + } + + return $notes; + } } diff --git a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php index dff2cc4c94..b1f9826c29 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -38,4 +38,39 @@ class XliffFileDumperTest extends \PHPUnit_Framework_TestCase unlink($tempDir.'/messages.en_US.xlf'); } + + public function testTargetAttributesMetadataIsSetInFile() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add(array( + 'foo' => 'bar', + )); + $catalogue->setMetadata('foo', array('target-attributes' => array('state' => 'needs-translation'))); + + $tempDir = sys_get_temp_dir(); + $dumper = new XliffFileDumper(); + $dumper->dump($catalogue, array('path' => $tempDir, 'default_locale' => 'fr_FR')); + + $content = << + + + + + foo + bar + + + + + +EOT; + + $this->assertEquals( + $content, + file_get_contents($tempDir.'/messages.en_US.xlf') + ); + + unlink($tempDir.'/messages.en_US.xlf'); + } } diff --git a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php index c3d65b4932..18c3aaeb25 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php @@ -73,6 +73,15 @@ class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array('notes' => array(array('content' => utf8_decode('bäz')))), $catalogue->getMetadata('foo', 'domain1')); } + public function testTargetAttributesAreStoredCorrectly() + { + $loader = new XliffFileLoader(); + $catalogue = $loader->load(__DIR__.'/../fixtures/with-attributes.xlf', 'en', 'domain1'); + + $metadata = $catalogue->getMetadata('foo', 'domain1'); + $this->assertEquals('translated', $metadata['target-attributes']['state']); + } + /** * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException */ diff --git a/src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf b/src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf new file mode 100644 index 0000000000..78730629cd --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf @@ -0,0 +1,21 @@ + + + + + + foo + bar + + + extra + bar + + + key + + baz + qux + + + +