From 2c1eb31021d6f2e3c3145efdc50cd07a6fa79697 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Jun 2010 15:10:52 +0200 Subject: [PATCH] added a way to translate strings coming from a variable ({% trans var %}) (closes #69) --- CHANGELOG | 6 ++++++ doc/02-Twig-for-Template-Designers.markdown | 27 +++++++++++++++++---------- lib/Twig/Node/Trans.php | 20 ++++++++++++-------- lib/Twig/TokenParser/Trans.php | 20 +++++++++----------- test/Twig/Tests/Node/TransTest.php | 23 +++++++++++++++++++++++ 5 files changed, 67 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b999de2..0ea5679 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ * 0.9.8 +Backward incompatibilities: + * the trans tag plural count is now attached to the plural tag: + old: `{% trans count %}...{% plural %}...{% endtrans %}` + new: `{% trans %}...{% plural count %}...{% endtrans %}` + + * added a way to translate strings coming from a variable ({% trans var %}) * fixed trans tag when used with the Escaper extension * fixed default cache umask * removed Twig_Template instances from the debug tag output diff --git a/doc/02-Twig-for-Template-Designers.markdown b/doc/02-Twig-for-Template-Designers.markdown index 0e7106e..abc8b16 100644 --- a/doc/02-Twig-for-Template-Designers.markdown +++ b/doc/02-Twig-for-Template-Designers.markdown @@ -824,8 +824,12 @@ When the `i18n` extension is enabled, use the `trans` block to mark parts in the template as translatable: [twig] + {% trans "Hello World!" %} + + {% trans string_var %} + {% trans %} - Hello World! + Hello World! {% endtrans %} >**CAUTION** @@ -836,9 +840,12 @@ In a translatable string, you can embed variables: [twig] {% trans %} - Hello {{ name }}! + Hello {{ name }}! {% endtrans %} +>**NOTE** +>`{% trans "Hello {{ name }}!" %}` is not a valid statement. + If you need to apply filters to the variables, you first need to assign the result to a variable: @@ -846,21 +853,21 @@ result to a variable: {% set name as name|capitalize %} {% trans %} - Hello {{ name }}! + Hello {{ name }}! {% endtrans %} To pluralize a translatable string, use the `plural` block: [twig] - {% trans apple_count %} - Hey {{ name }}, I have one apple. - {% plural %} - Hey {{ name }}, I have {{ count }} apples. + {% trans %} + Hey {{ name }}, I have one apple. + {% plural apple_count %} + Hey {{ name }}, I have {{ count }} apples. {% endtrans %} -The `trans` block first argument is the `count` used to select the right -string. Within the translatable string, the special `count` variable always -contain the count value (here the value of `apple_count`). +The `plural` tag should provide the `count` used to select the right string. +Within the translatable string, the special `count` variable always contain +the count value (here the value of `apple_count`). Expressions ----------- diff --git a/lib/Twig/Node/Trans.php b/lib/Twig/Node/Trans.php index 19b239e..637b127 100644 --- a/lib/Twig/Node/Trans.php +++ b/lib/Twig/Node/Trans.php @@ -45,13 +45,13 @@ class Twig_Node_Trans extends Twig_Node if ($vars) { $compiler ->write('echo strtr('.$function.'(') - ->string($msg) + ->subcompile($msg) ; if (null !== $this->plural) { $compiler ->raw(', ') - ->string($msg1) + ->subcompile($msg1) ->raw(', abs(') ->subcompile($this->count) ->raw(')') @@ -82,7 +82,7 @@ class Twig_Node_Trans extends Twig_Node } else { $compiler ->write('echo '.$function.'(') - ->string($msg) + ->subcompile($msg) ->raw(");\n") ; } @@ -90,21 +90,25 @@ class Twig_Node_Trans extends Twig_Node protected function compileString(Twig_NodeInterface $body) { + if ($body instanceof Twig_Node_Expression_Name || $body instanceof Twig_Node_Expression_Constant) { + return array($body, array()); + } + $msg = ''; $vars = array(); - foreach ($body as $i => $node) { - if ($node instanceof Twig_Node_Text) { - $msg .= $node['data']; - } else { + foreach ($body as $node) { + if ($node instanceof Twig_Node_Print) { $n = $node->expr; while ($n instanceof Twig_Node_Expression_Filter) { $n = $n->node; } $msg .= sprintf('%%%s%%', $n['name']); $vars[] = new Twig_Node_Expression_Name($n['name'], $n->getLine()); + } else { + $msg .= $node['data']; } } - return array(trim($msg), $vars); + return array(new Twig_Node(array(new Twig_Node_Expression_Constant(trim($msg), $node->getLine()))), $vars); } } diff --git a/lib/Twig/TokenParser/Trans.php b/lib/Twig/TokenParser/Trans.php index d819128..f2fbc51 100644 --- a/lib/Twig/TokenParser/Trans.php +++ b/lib/Twig/TokenParser/Trans.php @@ -22,19 +22,17 @@ class Twig_TokenParser_Trans extends Twig_TokenParser $lineno = $token->getLine(); $stream = $this->parser->getStream(); $count = null; - if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { - $count = new Twig_Node_Expression_Name($stream->expect(Twig_Token::NAME_TYPE)->getValue(), $lineno); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideForFork')); $plural = null; - if ('plural' === $stream->next()->getValue()) { - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $plural = $this->parser->subparse(array($this, 'decideForEnd'), true); - if (null === $count) { - throw new Twig_SyntaxError('When a plural is used, you must pass the count as an argument to the "trans" tag', $lineno); + if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { + $body = $this->parser->getExpressionParser()->parseExpression(); + } else { + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideForFork')); + if ('plural' === $stream->next()->getValue()) { + $count = new Twig_Node_Expression_Name($stream->expect(Twig_Token::NAME_TYPE)->getValue(), $lineno); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $plural = $this->parser->subparse(array($this, 'decideForEnd'), true); } } diff --git a/test/Twig/Tests/Node/TransTest.php b/test/Twig/Tests/Node/TransTest.php index 30e0ddc..e7e598e 100644 --- a/test/Twig/Tests/Node/TransTest.php +++ b/test/Twig/Tests/Node/TransTest.php @@ -40,6 +40,14 @@ class Twig_Tests_Node_TransTest extends Twig_Tests_Node_TestCase { $tests = array(); + $body = new Twig_Node_Expression_Name('foo', 0); + $node = new Twig_Node_Trans($body, null, null, 0); + $tests[] = array($node, 'echo gettext((isset($context[\'foo\']) ? $context[\'foo\'] : null));'); + + $body = new Twig_Node_Expression_Constant('Hello', 0); + $node = new Twig_Node_Trans($body, null, null, 0); + $tests[] = array($node, 'echo gettext("Hello");'); + $body = new Twig_Node(array( new Twig_Node_Text('Hello', 0), ), array(), 0); @@ -70,6 +78,21 @@ class Twig_Tests_Node_TransTest extends Twig_Tests_Node_TestCase $node = new Twig_Node_Trans($body, $plural, $count, 0); $tests[] = array($node, 'echo strtr(ngettext("Hey %name%, I have one apple", "Hey %name%, I have %count% apples", abs(12)), array("%name%" => (isset($context[\'name\']) ? $context[\'name\'] : null), "%name%" => (isset($context[\'name\']) ? $context[\'name\'] : null), "%count%" => abs(12), ));'); + // with escaper extension set to on + $filters = new Twig_Node(array( + new Twig_Node_Expression_Constant('escape', 0), + new Twig_Node(), + ), array(), 0); + + $body = new Twig_Node(array( + new Twig_Node_Text('J\'ai ', 0), + new Twig_Node_Print(new Twig_Node_Expression_Filter(new Twig_Node_Expression_Name('foo', 0), $filters, 0), 0), + new Twig_Node_Text(' pommes', 0), + ), array(), 0); + + $node = new Twig_Node_Trans($body, null, null, 0); + $tests[] = array($node, 'echo strtr(gettext("J\'ai %foo% pommes"), array("%foo%" => (isset($context[\'foo\']) ? $context[\'foo\'] : null), ));'); + return $tests; } } -- 1.7.2.5