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.
This commit is contained in:
Marcos Sánchez 2015-08-04 16:28:45 -03:00
parent 64d050769b
commit b913695682
5 changed files with 124 additions and 20 deletions

View File

@ -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]));
}
}

View File

@ -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;
}
}

View File

@ -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 = <<<EOT
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file source-language="fr-FR" target-language="en-US" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
<source>foo</source>
<target state="needs-translation">bar</target>
</trans-unit>
</body>
</file>
</xliff>
EOT;
$this->assertEquals(
$content,
file_get_contents($tempDir.'/messages.en_US.xlf')
);
unlink($tempDir.'/messages.en_US.xlf');
}
}

View File

@ -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
*/

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="1">
<source>foo</source>
<target state="translated">bar</target>
</trans-unit>
<trans-unit id="2">
<source>extra</source>
<target state="needs-translation">bar</target>
</trans-unit>
<trans-unit id="3">
<source>key</source>
<target></target>
<note>baz</note>
<note priority="2" from="bar">qux</note>
</trans-unit>
</body>
</file>
</xliff>