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 58d19733dbb36..47e082c22e992 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -70,11 +70,17 @@ protected function format(MessageCatalogue $messages, $domain) // 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 @@ protected function getExtension() { 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 d2b5407f82e1f..f2cbacb4f02e6 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -59,24 +59,15 @@ public function load($resource, $locale, $domain = 'messages') $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 @@ private function getXmlErrors($internalErrors) 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 dff2cc4c94a5b..b1f9826c295b9 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -38,4 +38,39 @@ public function testDump() 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 c3d65b493202e..18c3aaeb250c9 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php @@ -73,6 +73,15 @@ public function testEncoding() $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 0000000000000..78730629cdc47 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf @@ -0,0 +1,21 @@ + + + + + + foo + bar + + + extra + bar + + + key + + baz + qux + + + +