added a way to translate strings coming from a variable ({% trans var %}) (closes...
authorFabien Potencier <fabien.potencier@gmail.com>
Mon, 28 Jun 2010 13:10:52 +0000 (15:10 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Mon, 28 Jun 2010 13:20:10 +0000 (15:20 +0200)
CHANGELOG
doc/02-Twig-for-Template-Designers.markdown
lib/Twig/Node/Trans.php
lib/Twig/TokenParser/Trans.php
test/Twig/Tests/Node/TransTest.php

index b999de2..0ea5679 100644 (file)
--- 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
index 0e7106e..abc8b16 100644 (file)
@@ -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
 -----------
index 19b239e..637b127 100644 (file)
@@ -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);
     }
 }
index d819128..f2fbc51 100644 (file)
@@ -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);
             }
         }
 
index 30e0ddc..e7e598e 100644 (file)
@@ -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;
     }
 }