Add support for translator paths and twig paths in translation commands
This commit is contained in:
parent
5ed68eec7e
commit
31d7a09bf5
@ -15,6 +15,7 @@ CHANGELOG
|
||||
* Added information about deprecated aliases in `debug:autowiring`
|
||||
* Added php ini session options `sid_length` and `sid_bits_per_character`
|
||||
to the `session` section of the configuration
|
||||
* Added support for Translator paths, Twig paths in translation commands.
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
@ -50,11 +50,13 @@ class TranslationDebugCommand extends Command
|
||||
private $extractor;
|
||||
private $defaultTransPath;
|
||||
private $defaultViewsPath;
|
||||
private $transPaths;
|
||||
private $viewsPaths;
|
||||
|
||||
/**
|
||||
* @param TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct($translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null)
|
||||
public function __construct($translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = [])
|
||||
{
|
||||
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||
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 @@ class TranslationDebugCommand extends Command
|
||||
$this->extractor = $extractor;
|
||||
$this->defaultTransPath = $defaultTransPath;
|
||||
$this->defaultViewsPath = $defaultViewsPath;
|
||||
$this->transPaths = $transPaths;
|
||||
$this->viewsPaths = $viewsPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +135,7 @@ EOF
|
||||
$rootDir = $kernel->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
// Define Root Paths
|
||||
$transPaths = [];
|
||||
$transPaths = $this->transPaths;
|
||||
if (is_dir($dir = $rootDir.'/Resources/translations')) {
|
||||
if ($dir !== $this->defaultTransPath) {
|
||||
$notice = sprintf('Storing translations in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
|
||||
@ -142,7 +146,7 @@ EOF
|
||||
if ($this->defaultTransPath) {
|
||||
$transPaths[] = $this->defaultTransPath;
|
||||
}
|
||||
$viewsPaths = [];
|
||||
$viewsPaths = $this->viewsPaths;
|
||||
if (is_dir($dir = $rootDir.'/Resources/views')) {
|
||||
if ($dir !== $this->defaultViewsPath) {
|
||||
$notice = sprintf('Storing templates in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
|
||||
|
@ -44,8 +44,10 @@ class TranslationUpdateCommand extends Command
|
||||
private $defaultLocale;
|
||||
private $defaultTransPath;
|
||||
private $defaultViewsPath;
|
||||
private $transPaths;
|
||||
private $viewsPaths;
|
||||
|
||||
public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null)
|
||||
public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = [])
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
@ -55,6 +57,8 @@ class TranslationUpdateCommand extends Command
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
$this->defaultTransPath = $defaultTransPath;
|
||||
$this->defaultViewsPath = $defaultViewsPath;
|
||||
$this->transPaths = $transPaths;
|
||||
$this->viewsPaths = $viewsPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,7 +126,7 @@ EOF
|
||||
$rootDir = $kernel->getContainer()->getParameter('kernel.root_dir');
|
||||
|
||||
// Define Root Paths
|
||||
$transPaths = [];
|
||||
$transPaths = $this->transPaths;
|
||||
if (is_dir($dir = $rootDir.'/Resources/translations')) {
|
||||
if ($dir !== $this->defaultTransPath) {
|
||||
$notice = sprintf('Storing translations in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
|
||||
@ -133,7 +137,7 @@ EOF
|
||||
if ($this->defaultTransPath) {
|
||||
$transPaths[] = $this->defaultTransPath;
|
||||
}
|
||||
$viewsPaths = [];
|
||||
$viewsPaths = $this->viewsPaths;
|
||||
if (is_dir($dir = $rootDir.'/Resources/views')) {
|
||||
if ($dir !== $this->defaultViewsPath) {
|
||||
$notice = sprintf('Storing templates in the "%s" directory is deprecated since Symfony 4.2, ', $dir);
|
||||
|
@ -1023,20 +1023,21 @@ class FrameworkExtension extends Extension
|
||||
|
||||
// Discover translation directories
|
||||
$dirs = [];
|
||||
$transPaths = [];
|
||||
if (class_exists('Symfony\Component\Validator\Validation')) {
|
||||
$r = new \ReflectionClass('Symfony\Component\Validator\Validation');
|
||||
|
||||
$dirs[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
}
|
||||
if (class_exists('Symfony\Component\Form\Form')) {
|
||||
$r = new \ReflectionClass('Symfony\Component\Form\Form');
|
||||
|
||||
$dirs[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
$dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations';
|
||||
}
|
||||
if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) {
|
||||
$r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException');
|
||||
|
||||
$dirs[] = \dirname(\dirname($r->getFileName())).'/Resources/translations';
|
||||
$dirs[] = $transPaths[] = \dirname(\dirname($r->getFileName())).'/Resources/translations';
|
||||
}
|
||||
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
|
||||
$rootDir = $container->getParameter('kernel.root_dir');
|
||||
@ -1053,11 +1054,13 @@ class FrameworkExtension extends Extension
|
||||
|
||||
foreach ($config['paths'] as $dir) {
|
||||
if ($container->fileExists($dir)) {
|
||||
$dirs[] = $dir;
|
||||
$dirs[] = $transPaths[] = $dir;
|
||||
} else {
|
||||
throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir));
|
||||
}
|
||||
}
|
||||
$container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths);
|
||||
$container->getDefinition('console.command.translation_update')->replaceArgument(6, $transPaths);
|
||||
|
||||
if ($container->fileExists($defaultDir)) {
|
||||
$dirs[] = $defaultDir;
|
||||
|
@ -105,7 +105,9 @@ class FrameworkBundle extends Bundle
|
||||
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255);
|
||||
$this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
|
||||
$this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$this->addCompilerPassIfExists($container, TranslatorPass::class);
|
||||
// must be registered as late as possible to get access to all Twig paths registered in
|
||||
// twig.template_iterator definition
|
||||
$this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
|
||||
$container->addCompilerPass(new LoggingTranslatorPass());
|
||||
$container->addCompilerPass(new AddExpressionLanguageProvidersPass(false));
|
||||
$this->addCompilerPassIfExists($container, TranslationExtractorPass::class);
|
||||
|
@ -101,6 +101,8 @@
|
||||
<argument type="service" id="translation.extractor" />
|
||||
<argument>%translator.default_path%</argument>
|
||||
<argument /> <!-- %twig.default_path% -->
|
||||
<argument type="collection" /> <!-- Translator paths -->
|
||||
<argument type="collection" /> <!-- Twig paths -->
|
||||
<tag name="console.command" command="debug:translation" />
|
||||
</service>
|
||||
|
||||
@ -111,6 +113,8 @@
|
||||
<argument>%kernel.default_locale%</argument>
|
||||
<argument>%translator.default_path%</argument>
|
||||
<argument /> <!-- %twig.default_path% -->
|
||||
<argument type="collection" /> <!-- Translator paths -->
|
||||
<argument type="collection" /> <!-- Twig paths -->
|
||||
<tag name="console.command" command="translation:update" />
|
||||
</service>
|
||||
|
||||
|
@ -90,7 +90,7 @@ class TranslationDebugCommandTest extends TestCase
|
||||
$this->fs->mkdir($this->translationDir.'/translations');
|
||||
$this->fs->mkdir($this->translationDir.'/templates');
|
||||
|
||||
$tester = $this->createCommandTester(['foo' => 'foo'], ['bar' => 'bar']);
|
||||
$tester = $this->createCommandTester(['foo' => 'foo'], ['bar' => 'bar'], null, [$this->translationDir.'/trans'], [$this->translationDir.'/views']);
|
||||
$tester->execute(['locale' => 'en']);
|
||||
|
||||
$this->assertRegExp('/missing/', $tester->getDisplay());
|
||||
@ -145,7 +145,7 @@ class TranslationDebugCommandTest extends TestCase
|
||||
/**
|
||||
* @return CommandTester
|
||||
*/
|
||||
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null)
|
||||
private function createCommandTester($extractedMessages = [], $loadedMessages = [], $kernel = null, array $transPaths = [], array $viewsPaths = [])
|
||||
{
|
||||
$translator = $this->getMockBuilder('Symfony\Component\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
@ -207,7 +207,7 @@ class TranslationDebugCommandTest extends TestCase
|
||||
->method('getContainer')
|
||||
->will($this->returnValue($container));
|
||||
|
||||
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates');
|
||||
$command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $viewsPaths);
|
||||
|
||||
$application = new Application($kernel);
|
||||
$application->add($command);
|
||||
|
@ -39,7 +39,7 @@ class TranslationUpdateCommandTest extends TestCase
|
||||
$this->fs->mkdir($this->translationDir.'/translations');
|
||||
$this->fs->mkdir($this->translationDir.'/templates');
|
||||
|
||||
$tester = $this->createCommandTester(['messages' => ['foo' => 'foo']]);
|
||||
$tester = $this->createCommandTester(['messages' => ['foo' => 'foo']], [], null, [$this->translationDir.'/trans'], [$this->translationDir.'/views']);
|
||||
$tester->execute(['command' => 'translation:update', 'locale' => 'en', '--dump-messages' => true, '--clean' => true]);
|
||||
$this->assertRegExp('/foo/', $tester->getDisplay());
|
||||
$this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay());
|
||||
@ -121,7 +121,7 @@ class TranslationUpdateCommandTest extends TestCase
|
||||
/**
|
||||
* @return CommandTester
|
||||
*/
|
||||
private function createCommandTester($extractedMessages = [], $loadedMessages = [], HttpKernel\KernelInterface $kernel = null)
|
||||
private function createCommandTester($extractedMessages = [], $loadedMessages = [], HttpKernel\KernelInterface $kernel = null, array $transPaths = [], array $viewsPaths = [])
|
||||
{
|
||||
$translator = $this->getMockBuilder('Symfony\Component\Translation\Translator')
|
||||
->disableOriginalConstructor()
|
||||
@ -197,7 +197,7 @@ class TranslationUpdateCommandTest extends TestCase
|
||||
->method('getContainer')
|
||||
->will($this->returnValue($container));
|
||||
|
||||
$command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates');
|
||||
$command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates', $transPaths, $viewsPaths);
|
||||
|
||||
$application = new Application($kernel);
|
||||
$application->add($command);
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Remove in Symfony 5.0 when the templates directory deprecation is gone.
|
||||
*/
|
||||
class TranslationDebugPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if ($container->hasDefinition('console.command.translation_debug')) {
|
||||
// skipping the /Resources/views path deprecation
|
||||
$container->getDefinition('console.command.translation_debug')
|
||||
->setArgument(4, '%kernel.project_dir%/Resources/views');
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\AnnotationReaderPass;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\Config\CustomConfig;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\DependencyInjection\TranslationDebugPass;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
@ -29,5 +30,6 @@ class TestBundle extends Bundle
|
||||
$extension->setCustomConfig(new CustomConfig());
|
||||
|
||||
$container->addCompilerPass(new AnnotationReaderPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||
$container->addCompilerPass(new TranslationDebugPass());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @group functional
|
||||
*/
|
||||
class TranslationDebugCommandTest extends WebTestCase
|
||||
{
|
||||
private $application;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$kernel = static::createKernel(['test_case' => 'TransDebug', 'root_config' => 'config.yml']);
|
||||
$this->application = new Application($kernel);
|
||||
}
|
||||
|
||||
public function testDumpAllTrans()
|
||||
{
|
||||
$tester = $this->createCommandTester();
|
||||
$ret = $tester->execute(['locale' => 'en']);
|
||||
|
||||
$this->assertSame(0, $ret, 'Returns 0 in case of success');
|
||||
$this->assertContains('unused validators This value should be blank.', $tester->getDisplay());
|
||||
$this->assertContains('unused security Invalid CSRF token.', $tester->getDisplay());
|
||||
}
|
||||
|
||||
private function createCommandTester(): CommandTester
|
||||
{
|
||||
$command = $this->application->find('debug:translation');
|
||||
|
||||
return new CommandTester($command);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
|
||||
|
||||
return [
|
||||
new FrameworkBundle(),
|
||||
new TestBundle(),
|
||||
];
|
@ -0,0 +1,13 @@
|
||||
imports:
|
||||
- { resource: ../config/default.yml }
|
||||
|
||||
framework:
|
||||
secret: '%secret%'
|
||||
default_locale: '%env(LOCALE)%'
|
||||
translator:
|
||||
fallbacks:
|
||||
- '%env(LOCALE)%'
|
||||
|
||||
parameters:
|
||||
env(LOCALE): en
|
||||
secret: test
|
@ -74,7 +74,7 @@
|
||||
"symfony/property-info": "<3.4",
|
||||
"symfony/serializer": "<4.2",
|
||||
"symfony/stopwatch": "<3.4",
|
||||
"symfony/translation": "<4.2",
|
||||
"symfony/translation": "<4.3",
|
||||
"symfony/twig-bridge": "<4.1.1",
|
||||
"symfony/validator": "<4.1",
|
||||
"symfony/workflow": "<4.1"
|
||||
|
@ -68,12 +68,16 @@ class TranslatorPass implements CompilerPassInterface
|
||||
return;
|
||||
}
|
||||
|
||||
$paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(2));
|
||||
if ($container->hasDefinition($this->debugCommandServiceId)) {
|
||||
$container->getDefinition($this->debugCommandServiceId)->replaceArgument(4, $container->getParameter('twig.default_path'));
|
||||
$definition = $container->getDefinition($this->debugCommandServiceId);
|
||||
$definition->replaceArgument(4, $container->getParameter('twig.default_path'));
|
||||
$definition->replaceArgument(6, $paths);
|
||||
}
|
||||
|
||||
if ($container->hasDefinition($this->updateCommandServiceId)) {
|
||||
$container->getDefinition($this->updateCommandServiceId)->replaceArgument(5, $container->getParameter('twig.default_path'));
|
||||
$definition = $container->getDefinition($this->updateCommandServiceId);
|
||||
$definition->replaceArgument(5, $container->getParameter('twig.default_path'));
|
||||
$definition->replaceArgument(7, $paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,4 +54,32 @@ class TranslationPassTest extends TestCase
|
||||
$expected = ['translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader'))];
|
||||
$this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
|
||||
}
|
||||
|
||||
public function testValidCommandsViewPathsArgument()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('translator.default')
|
||||
->setArguments([null, null, null, null])
|
||||
;
|
||||
$debugCommand = $container->register('console.command.translation_debug')
|
||||
->setArguments([null, null, null, null, null, [], []])
|
||||
;
|
||||
$updateCommand = $container->register('console.command.translation_update')
|
||||
->setArguments([null, null, null, null, null, null, [], []])
|
||||
;
|
||||
$container->register('twig.template_iterator')
|
||||
->setArguments([null, null, ['other/templates' => null, 'tpl' => 'App']])
|
||||
;
|
||||
$container->setParameter('twig.default_path', 'templates');
|
||||
|
||||
$pass = new TranslatorPass('translator.default');
|
||||
$pass->process($container);
|
||||
|
||||
$expectedViewPaths = ['other/templates', 'tpl'];
|
||||
|
||||
$this->assertSame('templates', $debugCommand->getArgument(4));
|
||||
$this->assertSame('templates', $updateCommand->getArgument(5));
|
||||
$this->assertSame($expectedViewPaths, $debugCommand->getArgument(6));
|
||||
$this->assertSame($expectedViewPaths, $updateCommand->getArgument(7));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user