8000 Add support for translator paths and twig paths in translation commands · symfony/symfony@598b3d4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 598b3d4

Browse files
committed
Add support for translator paths and twig paths in translation commands
1 parent 5ed68ee commit 598b3d4

File tree

16 files changed

+172
-21
lines changed

16 files changed

+172
-21
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
* Added information about deprecated aliases in `debug:autowiring`
1616
* Added php ini session options `sid_length` and `sid_bits_per_character`
1717
to the `session` section of the configuration
18+
* Added support for Translator paths, Twig paths in translation commands.
1819

1920
4.2.0
2021
-----

src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ class TranslationDebugCommand extends Command
5050
private $extractor;
5151
private $defaultTransPath;
5252
private $defaultViewsPath;
53+
private $transPaths;
54+
private $viewsPaths;
5355

5456
/**
5557
* @param TranslatorInterface $translator
5658
*/
57-
public function __construct($translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null)
59+
public function __construct($translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = [])
5860
{
5961
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
6062
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
@@ -66,6 +68,8 @@ public function __construct($translator, TranslationReaderInterface $reader, Ext
6668
$this->extractor = $extractor;
6769
$this->defaultTransPath = $defaultTransPath;
6870
$this->defaultViewsPath = $defaultViewsPath;
71+
$this->transPaths = $transPaths;
72+
$this->viewsPaths = $viewsPaths;
6973
}
7074

7175
/**
@@ -131,7 +135,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
131135
$rootDir = $kernel->getContainer()->getParameter('kernel.root_dir');
132136

133137
// Define Root Paths
134-
$transPaths = [];
138+
$transPaths = $this->transPaths;
135139
if (is_dir($dir = $rootDir.'/Resources/translations')) {
136140
if ($dir !== $this->defaultTransPath) {
137141
$notice = sprintf('Storing translations in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
@@ -142,7 +146,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
142146
if ($this->defaultTransPath) {
143147
$transPaths[] = $this->defaultTransPath;
144148
}
145-
$viewsPaths = [];
149+
$viewsPaths = $this->viewsPaths;
146150
if (is_dir($dir = $rootDir.'/Resources/views')) {
147151
if ($dir !== $this->defaultViewsPath) {
148152
$notice = sprintf('Storing templates in the "%s" directory is deprecated since Symfony 4.2, ', $dir);

src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ class TranslationUpdateCommand extends Command
4444
private $defaultLocale;
4545
private $defaultTransPath;
4646
private $defaultViewsPath;
47+
private $transPaths;
48+
private $viewsPaths;
4749

48-
public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null)
50+
public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = [])
4951
{
5052
parent::__construct();
5153

@@ -55,6 +57,8 @@ public function __construct(TranslationWriterInterface $writer, TranslationReade
5557
$this->defaultLocale = $defaultLocale;
5658
$this->defaultTransPath = $defaultTransPath;
5759
$this->defaultViewsPath = $defaultViewsPath;
60+
$this->transPaths = $transPaths;
61+
$this->viewsPaths = $viewsPaths;
5862
}
5963

6064
/**
@@ -122,7 +126,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
122126
$rootDir = $kernel->getContainer()->getParameter('kernel.root_dir');
123127

124128
// Define Root Paths
125-
$transPaths = [];
129+
$transPaths = $this->transPaths;
126130
if (is_dir($dir = $rootDir.'/Resources/translations')) {
127131
if ($dir !== $this->defaultTransPath) {
128132
$notice = sprintf('Storing translations in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
@@ -133,7 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
133137
if ($this->defaultTransPath) {
134138
$transPaths[] = $this->defaultTransPath;
135139
}
136-
$viewsPaths = [];
140+
$viewsPaths = $this->viewsPaths;
137141
if (is_dir($dir = $rootDir.'/Resources/views')) {
138142
if ($dir !== $this->defaultViewsPath) {
139143
$notice = sprintf('Storing templates in the "%s" directory is deprecated since Symfony 4.2, ', $dir);

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,20 +1023,21 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
10231023

10241024
// Discover translation directories
10251025
$dirs = [];
1026+
$transPaths = [];
10261027
if (class_exists('Symfony\Component\Validator\Validation')) {
10271028
$r = new \ReflectionClass('Symfony\Component\Validator\Validation');
10281029

1029-
$dirs[] = \dirname($r->getFileName()).'/Resources/translations';
1030+
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
10301031
}
10311032
if (class_exists('Symfony\Component\Form\Form')) {
10321033
$r = new \ReflectionClass('Symfony\Component\Form\Form');
10331034

1034-
$dirs[] = \dirname($r->getFileName()).'/Resources/translations';
1035+
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
10351036
}
10361037
if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) {
10371038
$r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException');
10381039

1039-
$dirs[] = \dirname(\dirname($r->getFileName())).'/Resources/translations';
1040+
$dirs[] = $transPaths[] = \dirname(\dirname($r->getFileName())).'/Resources/translations';
10401041
}
10411042
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
10421043
$rootDir = $container->getParameter('kernel.root_dir');
@@ -1053,11 +1054,13 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
10531054

10541055
foreach ($config['paths'] as $dir) {
10551056
if ($container->fileExists($dir)) {
1056-
$dirs[] = $dir;
1057+
$dirs[] = $transPaths[] = $dir;
10571058
} else {
10581059
throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir));
10591060
}
10601061
}
1062+
$container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths);
1063+
$container->getDefinition('console.command.translation_update')->replaceArgument(6, $transPaths);
10611064

10621065
if ($container->fileExists($defaultDir)) {
10631066
$dirs[] = $defaultDir;

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
5252
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
5353
use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
54+
use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass;
5455
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
5556
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
5657
use Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass;
@@ -105,7 +106,9 @@ public function build(ContainerBuilder $container)
105106
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255);
106107
$this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
107108
$this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING);
108-
$this->addCompilerPassIfExists($container, TranslatorPass::class);
109+
// must be registered as late as possible to get access to all Twig paths registered in
110+
// twig.template_iterator definition
111+
$this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
109112
$container->addCompilerPass(new LoggingTranslatorPass());
110113
$container->addCompilerPass(new AddExpressionLanguageProvidersPass(false));
111114
$this->addCompilerPassIfExists($container, TranslationExtractorPass::class);

src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
<argument type="service" id="translation.extractor" />
102102
<argument>%translator.default_path%</argument>
103103
<argument /> <!-- %twig.default_path% -->
104+
<argument type="collection" /> <!-- Translator paths -->
105+
<argument type="collection" /> <!-- Twig paths -->
104106
<tag name="console.command" command="debug:translation" />
105107
</service>
106108

@@ -111,6 +113,8 @@
111113
<argument>%kernel.default_locale%</argument>
112114
<argument>%translator.default_path%</argument>
113115
<argument /> <!-- %twig.default_path% -->
116+
<argument type="collection" /> <!-- Translator paths -->
117+
<argument type="collection" /> <!-- Twig paths -->
114118
<tag name="console.command" command="translation:update" />
115119
</service>
116120

src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function testDebugDefaultRootDirectory()
9090
$this->fs->mkdir($this->translationDir.'/translations');
9191
$this->fs->mkdir($this->translationDir.'/templates');
9292

93-
$tester = $this->createCommandTester(['foo' => 'foo'], ['bar' => 'bar']);
93+
$tester = $this->createCommandTester(['foo' => 'foo'], ['bar' => 'bar'], null, [$this->translationDir.'/trans'], [$this->translationDir.'/views']);
9494
$tester->execute(['locale' => 'en']);
9595

9696
$this->assertRegExp('/missing/', $tester->getDisplay());
@@ -145,7 +145,7 @@ protected function tearDown()
145145
/**
146146
* @return CommandTester
147147
*/
148-
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null)
148+
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null, array $transPaths = [], array $viewsPaths = [])
149149
{
150150
$translator = $this->getMockBuilder('Symfony\Component\Translation\Translator')
151151
->disableOriginalConstructor()
@@ -207,7 +207,7 @@ private function createCommandTester($extractedMessages = [], $loadedMessages =
207207
->method('getContainer')
208208
->will($this->returnValue($container));
209209

210-
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates');
210+
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $viewsPaths);
211211

212212
$application = new Application($kernel);
213213
$application->add($command);

src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function testDumpMessagesAndCleanInRootDirectory()
3939
$this->fs->mkdir($this->translationDir.'/translations');
4040
$this->fs->mkdir($this->translationDir.'/templates');
4141

42-
$tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]);
42+
$tester = $this->createCommandTester(['messages' => ['foo' => 'foo']], [], null, [$this->translationDir.'/trans'], [$this->translationDir.'/views']);
4343
$tester->execute(['command' => 'translation:update', 'locale' => 'en', '--dump-messages' => true, '--clean' => true]);
4444
$this->assertRegExp('/foo/', $tester->getDisplay());
4545
$this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay());
@@ -121,7 +121,7 @@ protected function tearDown()
121121
/**
122122
* @return CommandTester
123123
*/
124-
private function createCommandTester($extractedMessages = [], $loadedMessages = [], HttpKernel\KernelInterface $kernel = null)
124+
private function createCommandTester($extractedMessages = [], $loadedMessages = [], HttpKernel\KernelInterface $kernel = null, array $transPaths = [], array $viewsPaths = [])
125125
{
126126
$translator = $this->getMockBuilder('Symfony\Component\Translation\Translator')
127127
->disableOriginalConstructor()
@@ -197,7 +197,7 @@ private function createCommandTester($extractedMessages = [], $loadedMessages =
197197
->method('getContainer')
198198
->will($this->returnValue($container));
199199

200-
$command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates');
200+
$command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $viewsPaths);
201201

202202
$application = new Application($kernel);
203203
$application->add($command);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
8+
/**
9+
* Remove in Symfony 5.0 when the templates directory deprecation is gone.
10+
*/
11+
class TranslationDebugPass implements CompilerPassInterface
12+
{
13+
public function process(ContainerBuilder $container)
14+
{
15+
if ($container->hasDefinition('console.command.translation_debug')) {
16+
// skipping the /Resources/views path deprecation
17+
$container->getDefinition('console.command.translation_debug')
18+
->setArgument(4, '%kernel.project_dir%/Resources/views');
19+
}
20+
}
21+
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/TestBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\AnnotationReaderPass;
1515
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\Config\CustomConfig;
16+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\TranslationDebugPass;
1617
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
1718
use Symfony\Component\DependencyInjection\ContainerBuilder;
1819
use Symfony\Component\HttpKernel\Bundle\Bundle;
@@ -29,5 +30,6 @@ public function build(ContainerBuilder $container)
2930
$extension->setCustomConfig(new CustomConfig());
3031

3132
$container->addCompilerPass(new AnnotationReaderPass(), PassConfig::TYPE_AFTER_REMOVING);
33+
$container->addCompilerPass(new TranslationDebugPass());
3234
}
3335
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Bundle\FrameworkBundle\Console\Application;
15+
use Symfony\Component\Console\Tester\CommandTester;
16+
17+
/**
18+
* @group functional
19+
*/
20+
class TranslationDebugCommandTest extends WebTestCase
21+
{
22+
private $application;
23+
24+
protected function setUp()
25+
{
26+
$kernel = static::createKernel(['test_case' => 'TransDebug', 'root_config' => 'config.yml']);
27+
$this->application = new Application($kernel);
28+
}
29+
30+
public function testDumpAllTrans()
31+
{
32+
$tester = $this->createCommandTester();
33+
$ret = $tester->execute(['locale' => 'en']);
34+
35+
$this->assertSame(0, $ret, 'Returns 0 in case of success');
36+
$this->assertContains('unused validators This value should be blank.', $tester->getDisplay());
37+
$this->assertContains('unused security Invalid CSRF token.', $tester->getDisplay());
38+
}
39+
40+
private function createCommandTester(): CommandTester
41+
{
42+
$command = $this->application->find('debug:translation');
43+
44+
return new CommandTester($command);
45+
}
46+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
];
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
framework:
5+
secret: '%secret%'
6+
default_locale: '%env(LOCALE)%'
7+
translator:
8+
fallbacks:
9+
- '%env(LOCALE)%'
10+
11+
parameters:
12+
env(LOCALE): en
13+
secret: test

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"symfony/property-info": "<3.4",
7575
"symfony/serializer": "<4.2",
7676
"symfony/stopwatch": "<3.4",
77-
"symfony/translation": "<4.2",
77+
"symfony/translation": "<4.3",
7878
"symfony/twig-bridge": "<4.1.1",
7979
"symfony/validator": "<4.1",
8080
"symfony/workflow": "<4.1"

src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,16 @@ public function process(ContainerBuilder $container)
6868
return;
6969
}
7070

71+
$paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(2));
7172
if ($container->hasDefinition($this->debugCommandServiceId)) {
72-
$container->getDefinition($this->debugCommandServiceId)->replaceArgument(4, $container->getParameter('twig.default_path'));
73+
$definition = $container->getDefinition($this->debugCommandServiceId);
74+
$definition->replaceArgument(4, $container->getParameter('twig.default_path'));
75+
$definition->replaceArgument(6, $paths);
7376
}
74-
7577
if ($container->hasDefinition($this->updateCommandServiceId)) {
76-
$container->getDefinition($this->updateCommandServiceId)->replaceArgument(5, $container->getParameter('twig.default_path'));
78+
$definition = $container->getDefinition($this->updateCommandServiceId);
79+
$definition->replaceArgument(5, $container->getParameter('twig.default_path'));
80+
$definition->replaceArgument(7, $paths);
7781
}
7882
}
7983
}

src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,32 @@ public function testValidCollector()
5454
$expected = ['translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader'))];
5555
$this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
5656
}
57+
58+
public function testValidCommandsViewPathsArgument()
59+
{
60+
$container = new ContainerBuilder();
61+
$container->register('translator.default')
62+
->setArguments([null, null, null, null])
63+
;
64+
$debugCommand = $container->register('console.command.translation_debug')
65+
->setArguments([null, null, null, null, null, [], []])
66+
;
67+
$updateCommand = $container->register('console.command.translation_update')
68+
->setArguments([null, null, null, null, null, null, [], []])
69+
;
70+
$container->register('twig.template_iterator')
71+
->setArguments([null, null, ['other/templates' => null, 'tpl' => 'App']])
72+
;
73+
$container->setParameter('twig.default_path', 'templates');
74+
75+
$pass = new TranslatorPass('translator.default');
76+
$pass->process($container);
77+
78+
$expectedViewPaths = ['other/templates', 'tpl'];
79+
80+
$this->assertSame('templates', $debugCommand->getArgument(4));
81+
$this->assertSame('templates', $updateCommand->getArgument(5));
82+
$this->assertSame($expectedViewPaths, $debugCommand->getArgument(6));
83+
$this->assertSame($expectedViewPaths, $updateCommand->getArgument(7));
84+
}
5785
}

0 commit comments

Comments
 (0)
0