diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index d80e2f4de9e69..bb0b02a81f07a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -45,13 +45,17 @@ class TranslationDebugCommand extends ContainerAwareCommand private $translator; private $reader; private $extractor; + private $defaultTransPath; + private $defaultViewsPath; /** * @param TranslatorInterface $translator * @param TranslationReaderInterface $reader * @param ExtractorInterface $extractor + * @param string $defaultTransPath + * @param string $defaultViewsPath */ - public function __construct($translator = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null) + public function __construct($translator = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null, $defaultTransPath = null, $defaultViewsPath = null) { if (!$translator instanceof TranslatorInterface) { @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, TranslatorInterface::class), E_USER_DEPRECATED); @@ -66,6 +70,8 @@ public function __construct($translator = null, TranslationReaderInterface $read $this->translator = $translator; $this->reader = $reader; $this->extractor = $extractor; + $this->defaultTransPath = $defaultTransPath; + $this->defaultViewsPath = $defaultViewsPath; } /** @@ -153,20 +159,34 @@ protected function execute(InputInterface $input, OutputInterface $output) /** @var KernelInterface $kernel */ $kernel = $this->getApplication()->getKernel(); - // Define Root Path to App folder - $transPaths = array($kernel->getRootDir().'/Resources/'); + // Define Root Paths + $transPaths = array($kernel->getRootDir().'/Resources/translations'); + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + $viewsPaths = array($kernel->getRootDir().'/Resources/views'); + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } // Override with provided Bundle info if (null !== $input->getArgument('bundle')) { try { $bundle = $kernel->getBundle($input->getArgument('bundle')); - $transPaths = array( - $bundle->getPath().'/Resources/', - sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName()), - ); + $transPaths = array($bundle->getPath().'/Resources/translations'); + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath.'/'.$bundle->getName(); + } + $transPaths[] = sprintf('%s/Resources/%s/translations', $kernel->getRootDir(), $bundle->getName()); + $viewsPaths = array($bundle->getPath().'/Resources/views'); + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath.'/bundles/'.$bundle->getName(); + } + $viewsPaths[] = sprintf('%s/Resources/%s/views', $kernel->getRootDir(), $bundle->getName()); } catch (\InvalidArgumentException $e) { // such a bundle does not exist, so treat the argument as path - $transPaths = array($input->getArgument('bundle').'/Resources/'); + $transPaths = array($input->getArgument('bundle').'/Resources/translations'); + $viewsPaths = array($input->getArgument('bundle').'/Resources/views'); if (!is_dir($transPaths[0])) { throw new \InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); @@ -174,13 +194,21 @@ protected function execute(InputInterface $input, OutputInterface $output) } } elseif ($input->getOption('all')) { foreach ($kernel->getBundles() as $bundle) { - $transPaths[] = $bundle->getPath().'/Resources/'; - $transPaths[] = sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName()); + $transPaths[] = $bundle->getPath().'/Resources/translations'; + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath.'/'.$bundle->getName(); + } + $transPaths[] = sprintf('%s/Resources/%s/translations', $kernel->getRootDir(), $bundle->getName()); + $viewsPaths[] = $bundle->getPath().'/Resources/views'; + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath.'/bundles/'.$bundle->getName(); + } + $viewsPaths[] = sprintf('%s/Resources/%s/views', $kernel->getRootDir(), $bundle->getName()); } } // Extract used messages - $extractedCatalogue = $this->extractMessages($locale, $transPaths); + $extractedCatalogue = $this->extractMessages($locale, $viewsPaths); // Load defined messages $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths); @@ -310,7 +338,6 @@ private function extractMessages($locale, $transPaths) { $extractedCatalogue = new MessageCatalogue($locale); foreach ($transPaths as $path) { - $path = $path.'views'; if (is_dir($path)) { $this->extractor->extract($path, $extractedCatalogue); } @@ -329,7 +356,6 @@ private function loadCurrentMessages($locale, $transPaths) { $currentCatalogue = new MessageCatalogue($locale); foreach ($transPaths as $path) { - $path = $path.'translations'; if (is_dir($path)) { $this->reader->read($path, $currentCatalogue); } @@ -355,7 +381,6 @@ private function loadFallbackCatalogues($locale, $transPaths) $fallbackCatalogue = new MessageCatalogue($fallbackLocale); foreach ($transPaths as $path) { - $path = $path.'translations'; if (is_dir($path)) { $this->reader->read($path, $fallbackCatalogue); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 9813b82fcf8a0..768617c826964 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Translation\Catalogue\TargetOperation; use Symfony\Component\Translation\Catalogue\MergeOperation; use Symfony\Component\Console\Input\InputInterface; @@ -39,14 +40,18 @@ class TranslationUpdateCommand extends ContainerAwareCommand private $reader; private $extractor; private $defaultLocale; + private $defaultTransPath; + private $defaultViewsPath; /** * @param TranslationWriterInterface $writer * @param TranslationReaderInterface $reader * @param ExtractorInterface $extractor * @param string $defaultLocale + * @param string $defaultTransPath + * @param string $defaultViewsPath */ - public function __construct($writer = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null, $defaultLocale = null) + public function __construct($writer = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null, $defaultLocale = null, $defaultTransPath = null, $defaultViewsPath = null) { if (!$writer instanceof TranslationWriterInterface) { @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, TranslationWriterInterface::class), E_USER_DEPRECATED); @@ -62,6 +67,8 @@ public function __construct($writer = null, TranslationReaderInterface $reader = $this->reader = $reader; $this->extractor = $extractor; $this->defaultLocale = $defaultLocale; + $this->defaultTransPath = $defaultTransPath; + $this->defaultViewsPath = $defaultViewsPath; } /** @@ -149,24 +156,39 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } + /** @var KernelInterface $kernel */ $kernel = $this->getApplication()->getKernel(); - // Define Root Path to App folder - $transPaths = array($kernel->getRootDir().'/Resources/'); + // Define Root Paths + $transPaths = array($kernel->getRootDir().'/Resources/translations'); + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + $viewsPaths = array($kernel->getRootDir().'/Resources/views'); + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } $currentName = 'app folder'; // Override with provided Bundle info if (null !== $input->getArgument('bundle')) { try { $foundBundle = $kernel->getBundle($input->getArgument('bundle')); - $transPaths = array( - $foundBundle->getPath().'/Resources/', - sprintf('%s/Resources/%s/', $kernel->getRootDir(), $foundBundle->getName()), - ); + $transPaths = array($foundBundle->getPath().'/Resources/translations'); + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath.'/'.$foundBundle->getName(); + } + $transPaths[] = sprintf('%s/Resources/%s/translations', $kernel->getRootDir(), $foundBundle->getName()); + $viewsPaths = array($foundBundle->getPath().'/Resources/views'); + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath.'/bundles/'.$foundBundle->getName(); + } + $viewsPaths[] = sprintf('%s/Resources/%s/views', $kernel->getRootDir(), $foundBundle->getName()); $currentName = $foundBundle->getName(); } catch (\InvalidArgumentException $e) { // such a bundle does not exist, so treat the argument as path - $transPaths = array($input->getArgument('bundle').'/Resources/'); + $transPaths = array($input->getArgument('bundle').'/Resources/translations'); + $viewsPaths = array($input->getArgument('bundle').'/Resources/views'); $currentName = $transPaths[0]; if (!is_dir($transPaths[0])) { @@ -188,8 +210,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $prefix = ''; } $this->extractor->setPrefix($prefix); - foreach ($transPaths as $path) { - $path .= 'views'; + foreach ($viewsPaths as $path) { if (is_dir($path)) { $this->extractor->extract($path, $extractedCatalogue); } @@ -199,7 +220,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $currentCatalogue = new MessageCatalogue($input->getArgument('locale')); $errorIo->comment('Loading translation files...'); foreach ($transPaths as $path) { - $path .= 'translations'; if (is_dir($path)) { $this->reader->read($path, $currentCatalogue); } @@ -267,14 +287,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $bundleTransPath = false; foreach ($transPaths as $path) { - $path .= 'translations'; if (is_dir($path)) { $bundleTransPath = $path; } } if (!$bundleTransPath) { - $bundleTransPath = end($transPaths).'translations'; + $bundleTransPath = end($transPaths); } $this->writer->write($operation->getResult(), $input->getOption('output-format'), array('path' => $bundleTransPath, 'default_locale' => $this->defaultLocale)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 9484b985bfad4..34f47a0599b31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -78,6 +78,8 @@ + %translator.default_path% + @@ -86,6 +88,8 @@ %kernel.default_locale% + %translator.default_path% + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index 7e516c7cc5589..a13d9a41e3bd2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -64,6 +64,21 @@ public function testDebugDefaultDirectory() $this->assertRegExp('/unused/', $tester->getDisplay()); } + public function testDebugDefaultRootDirectory() + { + $this->fs->remove($this->translationDir); + $this->fs = new Filesystem(); + $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); + $this->fs->mkdir($this->translationDir.'/translations'); + $this->fs->mkdir($this->translationDir.'/templates'); + + $tester = $this->createCommandTester(array('foo' => 'foo'), array('bar' => 'bar')); + $tester->execute(array('locale' => 'en')); + + $this->assertRegExp('/missing/', $tester->getDisplay()); + $this->assertRegExp('/unused/', $tester->getDisplay()); + } + public function testDebugCustomDirectory() { $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); @@ -100,6 +115,8 @@ protected function setUp() $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); $this->fs->mkdir($this->translationDir.'/Resources/translations'); $this->fs->mkdir($this->translationDir.'/Resources/views'); + $this->fs->mkdir($this->translationDir.'/translations'); + $this->fs->mkdir($this->translationDir.'/templates'); } protected function tearDown() @@ -174,7 +191,7 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag ->method('getContainer') ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock())); - $command = new TranslationDebugCommand($translator, $loader, $extractor); + $command = new TranslationDebugCommand($translator, $loader, $extractor, $this->translationDir.'/translations', $this->translationDir.'/templates'); $application = new Application($kernel); $application->add($command); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index 2cb8e0e2593d9..8a1b2b668e78b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -31,6 +31,19 @@ public function testDumpMessagesAndClean() $this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay()); } + public function testDumpMessagesAndCleanInRootDirectory() + { + $this->fs->remove($this->translationDir); + $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); + $this->fs->mkdir($this->translationDir.'/translations'); + $this->fs->mkdir($this->translationDir.'/templates'); + + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'))); + $tester->execute(array('command' => 'translation:update', 'locale' => 'en', '--dump-messages' => true, '--clean' => true)); + $this->assertRegExp('/foo/', $tester->getDisplay()); + $this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay()); + } + public function testDumpTwoMessagesAndClean() { $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo', 'bar' => 'bar'))); @@ -55,6 +68,18 @@ public function testWriteMessages() $this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay()); } + public function testWriteMessagesInRootDirectory() + { + $this->fs->remove($this->translationDir); + $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); + $this->fs->mkdir($this->translationDir.'/translations'); + $this->fs->mkdir($this->translationDir.'/templates'); + + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'))); + $tester->execute(array('command' => 'translation:update', 'locale' => 'en', '--force' => true)); + $this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay()); + } + public function testWriteMessagesForSpecificDomain() { $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar'))); @@ -68,6 +93,8 @@ protected function setUp() $this->translationDir = sys_get_temp_dir().'/'.uniqid('sf2_translation', true); $this->fs->mkdir($this->translationDir.'/Resources/translations'); $this->fs->mkdir($this->translationDir.'/Resources/views'); + $this->fs->mkdir($this->translationDir.'/translations'); + $this->fs->mkdir($this->translationDir.'/templates'); } protected function tearDown() @@ -152,7 +179,7 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag ->method('getContainer') ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock())); - $command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en'); + $command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en', $this->translationDir.'/translations', $this->translationDir.'/templates'); $application = new Application($kernel); $application->add($command); diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php index 07fc9f68f0152..a5e4097843c07 100644 --- a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php @@ -21,8 +21,10 @@ class TranslatorPass implements CompilerPassInterface private $translatorServiceId; private $readerServiceId; private $loaderTag; + private $debugCommandServiceId; + private $updateCommandServiceId; - public function __construct($translatorServiceId = 'translator.default', $readerServiceId = 'translation.loader', $loaderTag = 'translation.loader') + public function __construct($translatorServiceId = 'translator.default', $readerServiceId = 'translation.loader', $loaderTag = 'translation.loader', $debugCommandServiceId = 'console.command.translation_debug', $updateCommandServiceId = 'console.command.translation_update') { if ('translation.loader' === $readerServiceId && 2 > func_num_args()) { @trigger_error('The default value for $readerServiceId will change in 4.0 to "translation.reader".', E_USER_DEPRECATED); @@ -31,6 +33,8 @@ public function __construct($translatorServiceId = 'translator.default', $reader $this->translatorServiceId = $translatorServiceId; $this->readerServiceId = $readerServiceId; $this->loaderTag = $loaderTag; + $this->debugCommandServiceId = $debugCommandServiceId; + $this->updateCommandServiceId = $updateCommandServiceId; } public function process(ContainerBuilder $container) @@ -75,5 +79,10 @@ public function process(ContainerBuilder $container) ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) ->replaceArgument(3, $loaders) ; + + if ($container->hasParameter('twig.default_path')) { + $container->getDefinition($this->debugCommandServiceId)->replaceArgument(4, $container->getParameter('twig.default_path')); + $container->getDefinition($this->updateCommandServiceId)->replaceArgument(5, $container->getParameter('twig.default_path')); + } } }