diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index 579e326..d738b23 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -32,9 +32,11 @@ public function getFunctions() { public function getFilters() { return array( 't' => new \Twig_Filter_Function('t'), - // Fake filters equivalent to "raw" and only used in the trans tag. - // These filters are necessary to identify the type of prefix to use - // when passing tokens to t() from a trans tag. + // The "raw" filter is not detectable when parsing "trans" tags. To detect + // which prefix must be used for translation (@, !, %), we must clone the + // "raw" filter and give it identifiable names. These filters should only + // be used in "trans" tags. + // @see TwigNodeTrans::compileString() 'passthrough' => new \Twig_SimpleFilter('passthrough', 'twig_raw_filter'), 'placeholder' => new \Twig_SimpleFilter('placeholder', 'twig_raw_filter'), ); diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php index 2f928a4..64e0b2e 100644 --- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php +++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php @@ -4,6 +4,7 @@ * @file * Contains \Drupal\Core\Template\TwigNodeTrans. * + * @see http://twig.sensiolabs.org/doc/extensions/i18n.html * @see https://github.com/fabpot/Twig-extensions */ @@ -124,7 +125,17 @@ public function compile(\Twig_Compiler $compiler) { } /** - * {@inheritdoc} + * Extracts the text and tokens for the "trans" tag. + * + * @param \Twig_NodeInterface $body + * The node to compile. + * + * @return array + * Returns an array containing the two following parameters: + * - string $msg + * The extracted text. + * - array $vars + * The extracted tokens as new \Twig_Node_Expression_Name instances. */ protected function compileString(\Twig_NodeInterface $body) { if ($body instanceof \Twig_Node_Expression_Name || $body instanceof \Twig_Node_Expression_Constant || $body instanceof \Twig_Node_Expression_TempName) { @@ -147,10 +158,12 @@ protected function compileString(\Twig_NodeInterface $body) { } $args = $n->getNode('arguments')->getNode(0); - // Default prefix passed to t(), escapes printed token. + // Detect if a token implements one of the filters reserved for + // modifying the prefix of a token. The default prefix used for + // translations is "@". This escapes the printed token and makes them + // safe for templates. + // @see TwigExtension::getFilters() $argPrefix = '@'; - - // Detect if one of the "fake" filters for the trans tag is applied. while ($args instanceof \Twig_Node_Expression_Filter) { switch ($args->getNode('filter')->getAttribute('value')) { case 'passthrough': diff --git a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php index 4071aff..e1f4807 100644 --- a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php +++ b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php @@ -4,6 +4,7 @@ * @file * Contains \Drupal\Core\Template\TwigTransTokenParser. * + * @see http://twig.sensiolabs.org/doc/extensions/i18n.html * @see https://github.com/fabpot/Twig-extensions */ @@ -16,7 +17,7 @@ * code into an Abstract Syntax Tree (AST). The AST will later be compiled * into PHP code usable for runtime execution of the template. * - * @see core/vendor/twig/twig/lib/Twig/TokenParser.php + * @see \Twig_TokenParser */ class TwigTransTokenParser extends \Twig_TokenParser { /** @@ -51,14 +52,14 @@ public function parse(\Twig_Token $token) { } /** - * {@inheritdoc} + * Detect a 'plural' switch or the end of a 'trans' tag. */ public function decideForFork($token) { return $token->test(array('plural', 'endtrans')); } /** - * {@inheritdoc} + * Detect the end of a 'trans' tag. */ public function decideForEnd($token) { return $token->test('endtrans'); @@ -72,10 +73,15 @@ public function getTag() { } /** - * {@inheritdoc} + * Ensure that any nodes that are parsed are only of allowed types. + * + * @param \Twig_NodeInterface $body + * The expression to check. + * @param integer $lineno + * The source line. */ protected function checkTransString(\Twig_NodeInterface $body, $lineno) { - foreach ($body as $i => $node) { + foreach ($body as $node) { if ( $node instanceof \Twig_Node_Text || @@ -90,5 +96,5 @@ protected function checkTransString(\Twig_NodeInterface $body, $lineno) { throw new \Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno); } } - + } diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php index a9e17e9..8717147 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php @@ -10,7 +10,7 @@ use Drupal\simpletest\WebTestBase; /** - * Tests twig trans and format_plural blocks. + * Tests Twig "trans" tags. */ class TwigTransTest extends WebTestBase { @@ -26,26 +26,44 @@ class TwigTransTest extends WebTestBase { 'language' ); + /** + * An administrative user for testing. + * + * @var \Drupal\user\Plugin\Core\Entity\User + */ protected $admin_user; - + /** * Custom language code. + * + * @var string */ protected $langcode = 'xx'; - + /** - * LOL Speak machine name. + * Custom language name. + * + * @var string */ protected $name = 'Lolspeak'; + /** + * Defines information about this test. + * + * @return array + * An associative array of information. + */ public static function getInfo() { return array( 'name' => 'Twig Translation', - 'description' => 'Test Twig translation tags.', + 'description' => 'Test Twig "trans" tags.', 'group' => 'Theme', ); } + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); @@ -100,9 +118,9 @@ protected function setUp() { } /** - * Test valid Twig "trans" blocks. + * Test Twig "trans" tags. */ - public function testTwigTransBlocks() { + public function testTwigTransTags() { $this->drupalGet('twig-theme-test/trans', array('language' => language_load('xx'))); $this->assertText( @@ -189,6 +207,12 @@ protected function importPoFile($contents, array $options = array()) { drupal_unlink($name); } + /** + * An example .po file. + * + * @return string + * The .po contents used for this test. + */ protected function examplePoFile() { return <<< EOF msgid ""