TwigTransTokenParser.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <?php
  2. namespace Drupal\Core\Template;
  3. /**
  4. * A class that defines the Twig 'trans' token parser for Drupal.
  5. *
  6. * The token parser converts a token stream created from template source
  7. * code into an Abstract Syntax Tree (AST). The AST will later be compiled
  8. * into PHP code usable for runtime execution of the template.
  9. *
  10. * @see \Twig_TokenParser
  11. * @see https://twig-extensions.readthedocs.io/en/latest/i18n.html
  12. * @see https://github.com/fabpot/Twig-extensions
  13. */
  14. class TwigTransTokenParser extends \Twig_TokenParser {
  15. /**
  16. * {@inheritdoc}
  17. */
  18. public function parse(\Twig_Token $token) {
  19. $lineno = $token->getLine();
  20. $stream = $this->parser->getStream();
  21. $body = NULL;
  22. $options = NULL;
  23. $count = NULL;
  24. $plural = NULL;
  25. if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::STRING_TYPE)) {
  26. $body = $this->parser->getExpressionParser()->parseExpression();
  27. }
  28. if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::NAME_TYPE, 'with')) {
  29. $stream->next();
  30. $options = $this->parser->getExpressionParser()->parseExpression();
  31. }
  32. if (!$body) {
  33. $stream->expect(\Twig_Token::BLOCK_END_TYPE);
  34. $body = $this->parser->subparse([$this, 'decideForFork']);
  35. if ('plural' === $stream->next()->getValue()) {
  36. $count = $this->parser->getExpressionParser()->parseExpression();
  37. $stream->expect(\Twig_Token::BLOCK_END_TYPE);
  38. $plural = $this->parser->subparse([$this, 'decideForEnd'], TRUE);
  39. }
  40. }
  41. $stream->expect(\Twig_Token::BLOCK_END_TYPE);
  42. $this->checkTransString($body, $lineno);
  43. $node = new TwigNodeTrans($body, $plural, $count, $options, $lineno, $this->getTag());
  44. return $node;
  45. }
  46. /**
  47. * Detect a 'plural' switch or the end of a 'trans' tag.
  48. */
  49. public function decideForFork($token) {
  50. return $token->test(['plural', 'endtrans']);
  51. }
  52. /**
  53. * Detect the end of a 'trans' tag.
  54. */
  55. public function decideForEnd($token) {
  56. return $token->test('endtrans');
  57. }
  58. /**
  59. * {@inheritdoc}
  60. */
  61. public function getTag() {
  62. return 'trans';
  63. }
  64. /**
  65. * Ensure that any nodes that are parsed are only of allowed types.
  66. *
  67. * @param \Twig_Node $body
  68. * The expression to check.
  69. * @param int $lineno
  70. * The source line.
  71. *
  72. * @throws \Twig_Error_Syntax
  73. */
  74. protected function checkTransString(\Twig_Node $body, $lineno) {
  75. foreach ($body as $node) {
  76. if (
  77. $node instanceof \Twig_Node_Text
  78. ||
  79. ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Name)
  80. ||
  81. ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_GetAttr)
  82. ||
  83. ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Filter)
  84. ) {
  85. continue;
  86. }
  87. throw new \Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno);
  88. }
  89. }
  90. }