8000 feature #14630 [Translator] Dump translation constants as tree instea… · symfony/symfony@a57ce90 · GitHub
[go: up one dir, main page]

Skip to content

Commit a57ce90

Browse files
committed
feature #14630 [Translator] Dump translation constants as tree instead of simple list (gepo)
This PR was merged into the 2.8 branch. Discussion ---------- [Translator] Dump translation constants as tree instead of simple list | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | no | Fixed tickets | | License | MIT | Doc PR | PR #14434 for 2.8 branch Commits ------- 29ec5ca [Translation] add options 'as_tree', 'inline' to YamlFileDumper to dump messages as tree instead of simple list.
2 parents 791e583 + 29ec5ca commit a57ce90

File tree

8 files changed

+241
-6
lines changed

8 files changed

+241
-6
lines changed

src/Symfony/Component/Translation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* deprecated Translator::getMessages(), use TranslatorBagInterface::getCatalogue() instead.
8+
* added options 'as_tree', 'inline' to YamlFileDumper
89

910
2.7.0
1011
-----

src/Symfony/Component/Translation/Dumper/FileDumper.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,26 @@ public function dump(MessageCatalogue $messages, $options = array())
8282
}
8383
}
8484
// save file
85-
file_put_contents($fullpath, $this->format($messages, $domain));
85+
file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
8686
}
8787
}
8888

89+
/**
90+
* Transforms a domain of a message catalogue to its string representation.
91+
*
92+
* Override this function in child class if $options is used for message formatting.
93+
*
94+
* @param MessageCatalogue $messages
95+
* @param string $domain
96+
* @param array $options
97+
*
98+
* @return string representation
99+
*/
100+
protected function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
101+
{
102+
return $this->format($messages, $domain);
103+
}
104+
89105
/**
90106
* Transforms a domain of a message catalogue to its string representation.
91107
*

src/Symfony/Component/Translation/Dumper/YamlFileDumper.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Translation\Dumper;
1313

1414
use Symfony\Component\Translation\MessageCatalogue;
15+
use Symfony\Component\Translation\Util\ArrayConverter;
1516
use Symfony\Component\Yaml\Yaml;
1617

1718
/**
@@ -24,13 +25,31 @@ class YamlFileDumper extends FileDumper
2425
/**
2526
* {@inheritdoc}
2627
*/
27-
protected function format(MessageCatalogue $messages, $domain)
28+
protected function formatCatalogue(MessageCatalogue $messages, $domain, array $options = array())
2829
{
2930
if (!class_exists('Symfony\Component\Yaml\Yaml')) {
3031
throw new \LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
3132
}
3233

33-
return Yaml::dump($messages->all($domain));
34+
$data = $messages->all($domain);
35+
36+
if (isset($options['as_tree']) && $options['as_tree']) {
37+
$data = ArrayConverter::expandToTree F438 ($data);
38+
}
39+
40+
if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
41+
return Yaml::dump($data, $inline);
42+
}
43+
44+
return Yaml::dump($data);
45+
}
46+
47+
/**
48+
* {@inheritdoc}
49+
*/
50+
protected function format(MessageCatalogue $messages, $domain)
51+
{
52+
return $this->formatCatalogue($messages, $domain);
3453
}
3554

3655
/**

src/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,38 @@
1616

1717
class YamlFileDumperTest extends \PHPUnit_Framework_TestCase
1818
{
19-
public function testDump()
19+
public function testTreeDump()
2020
{
2121
$catalogue = new MessageCatalogue('en');
22-
$catalogue->add(array('foo' => 'bar'));
22+
$catalogue->add(
23+
array(
24+
'foo.bar1' => 'value1',
25+
'foo.bar2' => 'value2',
26+
));
27+
28+
$tempDir = sys_get_temp_dir();
29+
$dumper = new YamlFileDumper();
30+
$dumper->dump($catalogue, array('path' => $tempDir, 'as_tree' => true, 'inline' => 999));
31+
32+
$this->assertEquals(file_get_contents(__DIR__.'/../fixtures/messages.yml'), file_get_contents($tempDir.'/messages.en.yml'));
33+
34+
unlink($tempDir.'/messages.en.yml');
35+
}
36+
37+
public function testLinearDump()
38+
{
39+
$catalogue = new MessageCatalogue('en');
40+
$catalogue->add(
41+
array(
42+
'foo.bar1' => 'value1',
43+
'foo.bar2' => 'value2',
44+
));
2345

2446
$tempDir = sys_get_temp_dir();
2547
$dumper = new YamlFileDumper();
2648
$dumper->dump($catalogue, array('path' => $tempDir));
2749

28-
$this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.yml'), file_get_contents($tempDir.'/messages.en.yml'));
50+
$this->assertEquals(file_get_contents(__DIR__.'/../fixtures/messages_linear.yml'), file_get_contents($tempDir.'/messages.en.yml'));
2951

3052
unlink($tempDir.'/messages.en.yml');
3153
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation\Tests\Util;
13+
14+
use Symfony\Component\Translation\Util\ArrayConverter;
15+
16+
class ArrayConverterTest extends \PHPUnit_Framework_TestCase
17+
{
18+
/**
19+
* @dataProvider messsagesData
20+
*/
21+
public function testDump($input, $expectedOutput)
22+
{
23+
$this->assertEquals($expectedOutput, ArrayConverter::expandToTree($input));
24+
}
25+
26+
public function messsagesData()
27+
{
28+
return array(
29+
array(
30+
// input
31+
array(
32+
'foo1' => 'bar',
33+
'foo.bar' => 'value',
34+
),
35+
// expected output
36+
array(
37+
'foo1' => 'bar',
38+
'foo' => array('bar' => 'value'),
39+
),
40+
),
41+
array(
42+
// input
43+
array(
44+
'foo.bar' => 'value1',
45+
'foo.bar.test' => 'value2',
46+
),
47+
// expected output
48+
array(
49+
'foo' => array(
50+
'bar' => 'value1',
51+
'bar.test' => 'value2',
52+
),
53+
),
54+
),
55+
array(
56+
// input
57+
array(
58+
'foo.level2.level3.level4' => 'value1',
59+
'foo.level2' => 'value2',
60+
'foo.bar' => 'value3',
61+
),
62+
// expected output
63+
array(
64+
'foo' => array(
65+
'level2' => 'value2',
66+
'level2.level3.level4' => 'value1',
67+
'bar' => 'value3',
68+
),
69+
),
70+
),
71+
);
72+
}
73+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
foo:
2+
bar1: value1
3+
bar2: value2
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo.bar1: value1
2+
foo.bar2: value2
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation\Util;
13+
14+
/**
15+
* ArrayConverter generates tree like structure from a message catalogue.
16+
* e.g. this
17+
* 'foo.bar1' => 'test1',
18+
* 'foo.bar2' => 'test2'
19+
* converts to follows:
20+
* foo:
21+
* bar1: test1
22+
* bar2: test2.
23+
*
24+
* @author Gennady Telegin <gtelegin@gmail.com>
25+
*/
26+
class ArrayConverter
27+
{
28+
/**
29+
* Converts linear messages array to tree-like array.
30+
* For example this rray('foo.bar' => 'value') will be converted to array('foo' => array('bar' => 'value')).
31+
*
32+
* @param array $messages Linear messages array
33+
*
34+
* @return array Tree-like messages array
35+
*/
36+
public static function expandToTree(array $messages)
37+
{
38+
$tree = array();
39+
40+
foreach ($messages as $id => $value) {
41+
$referenceToElement = &self::getElementByPath($tree, explode('.', $id));
42+
43+
$referenceToElement = $value;
44+
45+
unset($referenceToElement);
46+
}
47+
48+
return $tree;
49+
}
50+
51+
private static function &getElementByPath(array &$tree, array $parts)
52+
{
53+
$elem = &$tree;
54+
$parentOfElem = null;
55+
56+
foreach ($parts as $i => $part) {
57+
if (isset($elem[$part]) && is_string($elem[$part])) {
58+
/* Process next case:
59+
* 'foo': 'test1',
60+
* 'foo.bar': 'test2'
61+
*
62+
* $tree['foo'] was string before we found array {bar: test2}.
63+
* Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
64+
*/
65+
$elem = &$elem[ implode('.', array_slice($parts, $i)) ];
66+
break;
67+
}
68+
$parentOfElem = &$elem;
69+
$elem = &$elem[$part];
70+
}
71+
72+
if (is_array($elem) && count($elem) > 0 && $parentOfElem) {
73+
/* Process next case:
74+
* 'foo.bar': 'test1'
75+
* 'foo': 'test2'
76+
*
77+
* $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
78+
* Cancel treating $tree['foo'] as array and cancel back it expansion,
79+
* e.g. make it $tree['foo.bar'] = 'test1' again.
80+
*/
81+
self::cancelExpand($parentOfElem, $part, $elem);
82+
}
83+
84+
return $elem;
85+
}
86+
87+
private static function cancelExpand(array &$tree, $prefix, array $node)
88+
{
89+
$prefix .= '.';
90+
91+
foreach ($node as $id => $value) {
92+
if (is_string($value)) {
93+
$tree[$prefix.$id] = $value;
94+
} else {
95+
self::cancelExpand($tree, $prefix.$id, $value);
96+
}
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)
0