feature #15452 [Translator] [Xliff] Add support for target attributes. (marcosdsanchez)
This PR was merged into the 2.8 branch.
Discussion
----------
[Translator] [Xliff] Add support for target attributes.
The previous implementation ignored attributes in target nodes in xliff files
so they were lost when you loaded and then dumped the same file. This change
should fix that problem.
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | N/A
| License | MIT
| Doc PR | N/A
Commits
-------
b913695
Add support for target attributes.
This commit is contained in:
commit
c8e05e39ed
@ -70,11 +70,17 @@ class XliffFileDumper extends FileDumper
|
|||||||
// Does the target contain characters requiring a CDATA section?
|
// Does the target contain characters requiring a CDATA section?
|
||||||
$text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
|
$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);
|
$t->appendChild($text);
|
||||||
|
|
||||||
$metadata = $messages->getMetadata($source, $domain);
|
if ($this->hasMetadataArrayInfo('notes', $metadata)) {
|
||||||
if (null !== $metadata && array_key_exists('notes', $metadata) && is_array($metadata['notes'])) {
|
|
||||||
foreach ($metadata['notes'] as $note) {
|
foreach ($metadata['notes'] as $note) {
|
||||||
if (!isset($note['content'])) {
|
if (!isset($note['content'])) {
|
||||||
continue;
|
continue;
|
||||||
@ -106,4 +112,15 @@ class XliffFileDumper extends FileDumper
|
|||||||
{
|
{
|
||||||
return 'xlf';
|
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]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,24 +59,15 @@ class XliffFileLoader implements LoaderInterface
|
|||||||
|
|
||||||
$catalogue->set((string) $source, $target, $domain);
|
$catalogue->set((string) $source, $target, $domain);
|
||||||
|
|
||||||
if (isset($translation->note)) {
|
$metadata = array();
|
||||||
$notes = array();
|
if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
|
||||||
foreach ($translation->note as $xmlNote) {
|
$metadata['notes'] = $notes;
|
||||||
$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);
|
|
||||||
}
|
}
|
||||||
|
if ($translation->target->attributes()) {
|
||||||
|
$metadata['target-attributes'] = $translation->target->attributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
$catalogue->setMetadata((string) $source, $metadata, $domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
|
if (class_exists('Symfony\Component\Config\Resource\FileResource')) {
|
||||||
@ -185,4 +176,35 @@ class XliffFileLoader implements LoaderInterface
|
|||||||
|
|
||||||
return $errors;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,39 @@ class XliffFileDumperTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
unlink($tempDir.'/messages.en_US.xlf');
|
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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'));
|
$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
|
* @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
|
||||||
*/
|
*/
|
||||||
|
21
src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf
vendored
Normal file
21
src/Symfony/Component/Translation/Tests/fixtures/with-attributes.xlf
vendored
Normal 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>
|
Reference in New Issue
Block a user