diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index c7bebdd12a..f6869dee77 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -33,11 +33,17 @@ class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface } if ($node instanceof TransDefaultDomainNode) { - $var = $env->getParser()->getVarName(); - $name = new \Twig_Node_Expression_AssignName($var, $node->getLine()); - $this->domain = new \Twig_Node_Expression_Name($var, $node->getLine()); + if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) { + $this->domain = $node->getNode('expr'); - return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine()); + return $node; + } else { + $var = $env->getParser()->getVarName(); + $name = new \Twig_Node_Expression_AssignName($var, $node->getLine()); + $this->domain = new \Twig_Node_Expression_Name($var, $node->getLine()); + + return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getLine()); + } } if (null === $this->domain) { @@ -68,6 +74,10 @@ class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface */ public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) { + if ($node instanceof TransDefaultDomainNode) { + return false; + } + return $node; } @@ -76,6 +86,6 @@ class TranslationDefaultDomainNodeVisitor implements \Twig_NodeVisitorInterface */ public function getPriority() { - return 0; + return -10; } } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php index 3a943f7106..592c250625 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php @@ -20,6 +20,8 @@ use Symfony\Bridge\Twig\Node\TransNode; */ class TranslationNodeVisitor implements \Twig_NodeVisitorInterface { + const UNDEFINED_DOMAIN = '_undefined'; + private $enabled = false; private $messages = array(); @@ -57,7 +59,7 @@ class TranslationNodeVisitor implements \Twig_NodeVisitorInterface // extract constant nodes with a trans filter $this->messages[] = array( $node->getNode('node')->getAttribute('value'), - $node->getNode('arguments')->hasNode(1) ? $node->getNode('arguments')->getNode(1)->getAttribute('value') : null, + $this->getReadDomainFromArguments($node->getNode('arguments'), 1), ); } elseif ( $node instanceof \Twig_Node_Expression_Filter && @@ -67,13 +69,13 @@ class TranslationNodeVisitor implements \Twig_NodeVisitorInterface // extract constant nodes with a trans filter $this->messages[] = array( $node->getNode('node')->getAttribute('value'), - $node->getNode('arguments')->hasNode(2) ? $node->getNode('arguments')->getNode(2)->getAttribute('value') : null, + $this->getReadDomainFromArguments($node->getNode('arguments'), 2), ); } elseif ($node instanceof TransNode) { // extract trans nodes $this->messages[] = array( $node->getNode('body')->getAttribute('data'), - null === $node->getNode('domain') ? 'messages' : $node->getNode('domain')->getAttribute('value'), + $this->getReadDomainFromNode($node->getNode('domain')), ); } @@ -93,6 +95,43 @@ class TranslationNodeVisitor implements \Twig_NodeVisitorInterface */ public function getPriority() { - return -10; + return 0; + } + + /** + * @param \Twig_Node $arguments + * @param int $index + * + * @return string|null + */ + private function getReadDomainFromArguments(\Twig_Node $arguments, $index) + { + if ($arguments->hasNode('domain')) { + $argument = $arguments->getNode('domain'); + } elseif ($arguments->hasNode($index)) { + $argument = $arguments->getNode($index); + } else { + return null; + } + + return $this->getReadDomainFromNode($argument); + } + + /** + * @param \Twig_Node $node + * + * @return string|null + */ + private function getReadDomainFromNode(\Twig_Node $node = null) + { + if (null === $node) { + return null; + } + + if ($node instanceof \Twig_Node_Expression_Constant) { + return $node->getAttribute('value'); + } + + return self::UNDEFINED_DOMAIN; } } diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php new file mode 100644 index 0000000000..9fd367c6c9 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php @@ -0,0 +1,49 @@ + false, 'autoescape' => false, 'optimizations' => 0)); + + $visitor = new TranslationDefaultDomainNodeVisitor(); + + // visit trans_default_domain tag + $defaultDomain = TwigNodeProvider::getTransDefaultDomainTag('domain'); + $visitor->enterNode($defaultDomain, $env); + $visitor->leaveNode($defaultDomain, $env); + + // visit tested node + $enteredNode = $visitor->enterNode($node, $env); + $leavedNode = $visitor->leaveNode($node, $env); + $this->assertSame($node, $enteredNode); + $this->assertSame($node, $leavedNode); + + // extracting tested node messages + $visitor = new TranslationNodeVisitor(); + $visitor->enable(); + $visitor->enterNode($node, $env); + $visitor->leaveNode($node, $env); + + $this->assertEquals(array(array(self::$message, self::$domain)), $visitor->getMessages()); + } + + public function getDefaultDomainAssignmentTestData() + { + return array( + array(TwigNodeProvider::getTransFilter(self::$message, self::$domain)), + array(TwigNodeProvider::getTransChoiceFilter(self::$message, self::$domain)), + array(TwigNodeProvider::getTransTag(self::$message, self::$domain)), + ); + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php new file mode 100644 index 0000000000..175a7c8ac4 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php @@ -0,0 +1,52 @@ + false, 'autoescape' => false, 'optimizations' => 0)); + $visitor = new TranslationNodeVisitor(); + $visitor->enable(); + $visitor->enterNode($node, $env); + $visitor->leaveNode($node, $env); + $this->assertEquals($expectedMessages, $visitor->getMessages()); + } + + public function testMessageExtractionWithInvalidDomainNode() + { + $message = 'new key'; + + $node = new \Twig_Node_Expression_Filter( + new \Twig_Node_Expression_Constant($message, 0), + new \Twig_Node_Expression_Constant('trans', 0), + new \Twig_Node(array( + new \Twig_Node_Expression_Array(array(), 0), + new \Twig_Node_Expression_Name('variable', 0), + )), + 0 + ); + + $this->testMessagesExtraction($node, array(array($message, TranslationNodeVisitor::UNDEFINED_DOMAIN))); + } + + public function getMessagesExtractionTestData() + { + $message = 'new key'; + $domain = 'domain'; + + return array( + array(TwigNodeProvider::getTransFilter($message), array(array($message, null))), + array(TwigNodeProvider::getTransChoiceFilter($message), array(array($message, null))), + array(TwigNodeProvider::getTransTag($message), array(array($message, null))), + array(TwigNodeProvider::getTransFilter($message, $domain), array(array($message, $domain))), + array(TwigNodeProvider::getTransChoiceFilter($message, $domain), array(array($message, $domain))), + array(TwigNodeProvider::getTransTag($message, $domain), array(array($message, $domain))), + ); + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php new file mode 100644 index 0000000000..2b753ce7af --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php @@ -0,0 +1,55 @@ + $message)), + $domain ? new \Twig_Node_Expression_Constant($domain, 0) : null + ); + } + + public static function getTransDefaultDomainTag($domain) + { + return new TransDefaultDomainNode( + new \Twig_Node_Expression_Constant($domain, 0) + ); + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php index a5859db1e1..a2c5cd3d03 100644 --- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php @@ -67,6 +67,15 @@ class TwigExtractorTest extends TestCase array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')), array('{% set foo = "new key" | trans %}', array('new key' => 'messages')), array('{{ 1 ? "new key" | trans : "another key" | trans }}', array('new key' => 'messages', 'another key' => 'messages')), + + // make sure 'trans_default_domain' tag is supported + array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')), + array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')), + array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')), + + // make sure this works with twig's named arguments + array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')), + array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')), ); } }