Skip to content

Commit

Permalink
[Translation] [Xliff] Support for <note>
Browse files Browse the repository at this point in the history
  • Loading branch information
Jérémy Derussé authored and fabpot committed Jun 17, 2014
1 parent d55fe84 commit d18e758
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 11 deletions.
6 changes: 6 additions & 0 deletions src/Symfony/Component/Translation/Catalogue/DiffOperation.php
Expand Up @@ -33,6 +33,9 @@ protected function processDomain($domain)
if ($this->target->has($id, $domain)) {
$this->messages[$domain]['all'][$id] = $message;
$this->result->add(array($id => $message), $domain);
if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
$this->result->setMetadata($id, $keyMetadata, $domain);
}
} else {
$this->messages[$domain]['obsolete'][$id] = $message;
}
Expand All @@ -43,6 +46,9 @@ protected function processDomain($domain)
$this->messages[$domain]['all'][$id] = $message;
$this->messages[$domain]['new'][$id] = $message;
$this->result->add(array($id => $message), $domain);
if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
$this->result->setMetadata($id, $keyMetadata, $domain);
}
}
}
}
Expand Down
Expand Up @@ -32,13 +32,19 @@ protected function processDomain($domain)
foreach ($this->source->all($domain) as $id => $message) {
$this->messages[$domain]['all'][$id] = $message;
$this->result->add(array($id => $message), $domain);
if (null !== $keyMetadata = $this->source->getMetadata($id, $domain)) {
$this->result->setMetadata($id, $keyMetadata, $domain);
}
}

foreach ($this->target->all($domain) as $id => $message) {
if (!$this->source->has($id, $domain)) {
$this->messages[$domain]['all'][$id] = $message;
$this->messages[$domain]['new'][$id] = $message;
$this->result->add(array($id => $message), $domain);
if (null !== $keyMetadata = $this->target->getMetadata($id, $domain)) {
$this->result->setMetadata($id, $keyMetadata, $domain);
}
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/Symfony/Component/Translation/Dumper/XliffFileDumper.php
Expand Up @@ -50,6 +50,26 @@ protected function format(MessageCatalogue $messages, $domain)
$t = $translation->appendChild($dom->createElement('target'));
$t->appendChild($dom->createTextNode($target));

$metadata = $messages->getMetadata($source, $domain);
if (null !== $metadata && array_key_exists('notes', $metadata) && is_array($metadata['notes'])) {
foreach ($metadata['notes'] as $note) {
if (!isset($note['content'])) {
continue;
}

$n = $translation->appendChild($dom->createElement('note'));
$n->appendChild($dom->createTextNode($note['content']));

if (isset($note['priority'])) {
$n->setAttribute('priority', $note['priority']);
}

if (isset($note['from'])) {
$n->setAttribute('from', $note['from']);
}
}
}

$xliffBody->appendChild($translation);
}

Expand Down
56 changes: 45 additions & 11 deletions src/Symfony/Component/Translation/Loader/XliffFileLoader.php
Expand Up @@ -53,27 +53,61 @@ public function load($resource, $locale, $domain = 'messages')
}

$source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
$target = (string) $translation->target;

// If the xlf file has another encoding specified, try to convert it because
// simple_xml will always return utf-8 encoded values
if ('UTF-8' !== $encoding && !empty($encoding)) {
if (function_exists('mb_convert_encoding')) {
$target = mb_convert_encoding($target, $encoding, 'UTF-8');
} elseif (function_exists('iconv')) {
$target = iconv('UTF-8', $encoding, $target);
} else {
throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
}
}
$target = $this->utf8ToCharset((string) $translation->target, $encoding);

$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);
}
}
$catalogue->addResource(new FileResource($resource));

return $catalogue;
}

/**
* Convert a UTF8 string to the specified encoding
*
* @param string $content String to decode
* @param string $encoding Target encoding
*
* @return string
*/
private function utf8ToCharset($content, $encoding=null)
{
if ('UTF-8' !== $encoding && !empty($encoding)) {
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($content, $encoding, 'UTF-8');
}

if (function_exists('iconv')) {
return iconv('UTF-8', $encoding, $content);
}

throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
}

return $content;
}

/**
* Validates and parses the given file into a SimpleXMLElement
*
Expand Down
Expand Up @@ -53,6 +53,28 @@ public function testGetResultFromSingleDomain()
);
}

public function testGetResultWithMetadata()
{
$leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
$leftCatalogue->setMetadata('a', 'foo', 'messages');
$leftCatalogue->setMetadata('b', 'bar', 'messages');
$rightCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'new_b', 'c' => 'new_c')));
$rightCatalogue->setMetadata('b', 'baz', 'messages');
$rightCatalogue->setMetadata('c', 'qux', 'messages');

$diffCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'old_b', 'c' => 'new_c')));
$diffCatalogue->setMetadata('b', 'bar', 'messages');
$diffCatalogue->setMetadata('c', 'qux', 'messages');

$this->assertEquals(
$diffCatalogue,
$this->createOperation(
$leftCatalogue,
$rightCatalogue
)->getResult()
);
}

protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
{
return new DiffOperation($source, $target);
Expand Down
Expand Up @@ -53,6 +53,29 @@ public function testGetResultFromSingleDomain()
);
}

public function testGetResultWithMetadata()
{
$leftCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b')));
$leftCatalogue->setMetadata('a', 'foo', 'messages');
$leftCatalogue->setMetadata('b', 'bar', 'messages');
$rightCatalogue = new MessageCatalogue('en', array('messages' => array('b' => 'new_b', 'c' => 'new_c')));
$rightCatalogue->setMetadata('b', 'baz', 'messages');
$rightCatalogue->setMetadata('c', 'qux', 'messages');

$mergedCatalogue = new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c')));
$mergedCatalogue->setMetadata('a', 'foo', 'messages');
$mergedCatalogue->setMetadata('b', 'bar', 'messages');
$mergedCatalogue->setMetadata('c', 'qux', 'messages');

$this->assertEquals(
$mergedCatalogue,
$this->createOperation(
$leftCatalogue,
$rightCatalogue
)->getResult()
);
}

protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
{
return new MergeOperation($source, $target);
Expand Down
Expand Up @@ -20,6 +20,8 @@ public function testDump()
{
$catalogue = new MessageCatalogue('en');
$catalogue->add(array('foo' => 'bar', 'key' => ''));
$catalogue->setMetadata('foo', array('notes' => array(array('priority' => 1, 'from' => 'bar', 'content' => 'baz'))));
$catalogue->setMetadata('key', array('notes' => array(array('content' => 'baz'), array('content' => 'qux'))));

$tempDir = sys_get_temp_dir();
$dumper = new XliffFileDumper();
Expand Down
Expand Up @@ -54,6 +54,7 @@ public function testEncoding()

$this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1'));
$this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1'));
$this->assertEquals(array('notes' => array(array('content' => utf8_decode('bäz')))), $catalogue->getMetadata('foo', 'domain1'));
}

/**
Expand Down Expand Up @@ -111,4 +112,15 @@ public function testParseEmptyFile()
$this->setExpectedException('Symfony\Component\Translation\Exception\InvalidResourceException', sprintf('Unable to load "%s":', $resource));
$loader->load($resource, 'en', 'domain1');
}

public function testLoadNotes()
{
$loader = new XliffFileLoader();
$catalogue = $loader->load(__DIR__.'/../fixtures/withnote.xlf', 'en', 'domain1');

$this->assertEquals(array('notes' => array(array('priority' => 1, 'content' => 'foo'))), $catalogue->getMetadata('foo', 'domain1'));
// message without target
$this->assertNull($catalogue->getMetadata('extra', 'domain1'));
$this->assertEquals(array('notes' => array(array('content' => 'baz'), array('priority' => 2, 'from' => 'bar', 'content' => 'qux'))), $catalogue->getMetadata('key', 'domain1'));
}
}
Expand Up @@ -5,6 +5,7 @@
<trans-unit id="1" resname="foo">
<source>foo</source>
<target>bär</target>
<note>bäz</note>
</trans-unit>
<trans-unit id="2" resname="bar">
<source>bar</source>
Expand Down
Expand Up @@ -5,10 +5,13 @@
<trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
<source>foo</source>
<target>bar</target>
<note priority="1" from="bar">baz</note>
</trans-unit>
<trans-unit id="3c6e0b8a9c15224a8228b9a98ca1531d" resname="key">
<source>key</source>
<target></target>
<note>baz</note>
<note>qux</note>
</trans-unit>
</body>
</file>
Expand Down
22 changes: 22 additions & 0 deletions src/Symfony/Component/Translation/Tests/fixtures/withnote.xlf
@@ -0,0 +1,22 @@
<?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>bar</target>
<note priority="1">foo</note>
</trans-unit>
<trans-unit id="2">
<source>extra</source>
<note from="foo">bar</note>
</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>

0 comments on commit d18e758

Please sign in to comment.