[TwigBridge] fixed trans twig extractor

This commit is contained in:
Jean-François Simon 2013-02-27 10:07:28 +01:00 committed by Fabien Potencier
parent 83382bc798
commit bae83c7c81
6 changed files with 223 additions and 9 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
use Symfony\Bridge\Twig\Tests\TestCase;
class TranslationDefaultDomainNodeVisitorTest extends TestCase
{
private static $message = 'message';
private static $domain = 'domain';
/** @dataProvider getDefaultDomainAssignmentTestData */
public function testDefaultDomainAssignment(\Twig_Node $node)
{
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => 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)),
);
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
use Symfony\Bridge\Twig\Tests\TestCase;
class TranslationNodeVisitorTest extends TestCase
{
/** @dataProvider getMessagesExtractionTestData */
public function testMessagesExtraction(\Twig_Node $node, array $expectedMessages)
{
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => 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))),
);
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Symfony\Bridge\Twig\Tests\NodeVisitor;
use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
use Symfony\Bridge\Twig\Node\TransNode;
class TwigNodeProvider
{
public static function getTransFilter($message, $domain = null)
{
$arguments = $domain ? array(
new \Twig_Node_Expression_Array(array(), 0),
new \Twig_Node_Expression_Constant($domain, 0),
) : array();
return new \Twig_Node_Expression_Filter(
new \Twig_Node_Expression_Constant($message, 0),
new \Twig_Node_Expression_Constant('trans', 0),
new \Twig_Node($arguments),
0
);
}
public static function getTransChoiceFilter($message, $domain = null)
{
$arguments = $domain ? array(
new \Twig_Node_Expression_Constant(0, 0),
new \Twig_Node_Expression_Array(array(), 0),
new \Twig_Node_Expression_Constant($domain, 0),
) : array();
return new \Twig_Node_Expression_Filter(
new \Twig_Node_Expression_Constant($message, 0),
new \Twig_Node_Expression_Constant('transchoice', 0),
new \Twig_Node($arguments),
0
);
}
public static function getTransTag($message, $domain = null)
{
return new TransNode(
new \Twig_Node_Body(array(), array('data' => $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)
);
}
}

View File

@ -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')),
);
}
}