class_docstr: This extension adds gettext support to Jinja.
class_docstr_tok: ["This","extension","adds","gettext","support","to","Jinja","."]
docstr: Parse a translatable tag.
docstr_tok: ["Parse","a","translatable","tag","."]
code: def parse(
      self, parser: "Parser"
  ) -> t.Union[nodes.Node, t.List[nodes.Node]]:
      """Parse a translatable tag."""
      lineno = next(parser.stream).lineno
  
      context = None
      context_token = parser.stream.next_if("string")
  
      if context_token is not None:
          context = context_token.value
  
      # find all the variables referenced.  Additionally a variable can be
      # defined in the body of the trans block too, but this is checked at
      # a later state.
      plural_expr: t.Optional[nodes.Expr] = None
      plural_expr_assignment: t.Optional[nodes.Assign] = None
      num_called_num = False
      variables: t.Dict[str, nodes.Expr] = {}
      trimmed = None
      while parser.stream.current.type != "block_end":
          if variables:
              parser.stream.expect("comma")
  
          # skip colon for python compatibility
          if parser.stream.skip_if("colon"):
              break
  
          token = parser.stream.expect("name")
          if token.value in variables:
              parser.fail(
                  f"translatable variable {token.value!r} defined twice.",
                  token.lineno,
                  exc=TemplateAssertionError,
              )
  
          # expressions
          if parser.stream.current.type == "assign":
              next(parser.stream)
              variables[token.value] = var = parser.parse_expression()
          elif trimmed is None and token.value in (
              "trimmed",
              "notrimmed",
          ):
              trimmed = token.value == "trimmed"
              continue
          else:
              variables[token.value] = var = nodes.Name(
                  token.value, "load"
              )
  
          if plural_expr is None:
              if isinstance(var, nodes.Call):
                  plural_expr = nodes.Name("_trans", "load")
                  variables[token.value] = plural_expr
                  plural_expr_assignment = nodes.Assign(
                      nodes.Name("_trans", "store"), var
                  )
              else:
                  plural_expr = var
              num_called_num = token.value == "num"
  
      parser.stream.expect("block_end")
  
      plural = None
      have_plural = False
      referenced = set()
  
      # now parse until endtrans or pluralize
      singular_names, singular = self._parse_block(parser, True)
      if singular_names:
          referenced.update(singular_names)
          if plural_expr is None:
              plural_expr = nodes.Name(singular_names[0], "load")
              num_called_num = singular_names[0] == "num"
  
      # if we have a pluralize block, we parse that too
      if parser.stream.current.test("name:pluralize"):
          have_plural = True
          next(parser.stream)
          if parser.stream.current.type != "block_end":
              token = parser.stream.expect("name")
              if token.value not in variables:
                  parser.fail(
                      f"unknown variable {token.value!r} for pluralization",
                      token.lineno,
                      exc=TemplateAssertionError,
                  )
              plural_expr = variables[token.value]
              num_called_num = token.value == "num"
          parser.stream.expect("block_end")
          plural_names, plural = self._parse_block(parser, False)
          next(parser.stream)
          referenced.update(plural_names)
      else:
          next(parser.stream)
  
      # register free names as simple name expressions
      for name in referenced:
          if name not in variables:
              variables[name] = nodes.Name(name, "load")
  
      if not have_plural:
          plural_expr = None
      elif plural_expr is None:
          parser.fail("pluralize without variables", lineno)
  
      if trimmed is None:
          trimmed = self.environment.policies["ext.i18n.trimmed"]
      if trimmed:
          singular = self._trim_whitespace(singular)
          if plural:
              plural = self._trim_whitespace(plural)
  
      node = self._make_node(
          singular,
          plural,
          context,
          variables,
          plural_expr,
          bool(referenced),
          num_called_num and have_plural,
      )
      node.set_lineno(lineno)
      if plural_expr_assignment is not None:
          return [plural_expr_assignment, node]
      else:
          return node
  
imports: import pprint
  import re
  import typing
  from markupsafe import Markup
  from .None import defaults
  from .None import nodes
  from .environment import Environment
  from .exceptions import TemplateAssertionError
  from .exceptions import TemplateSyntaxError
  from .runtime import concat
  from .runtime import Context
  from .runtime import Undefined
  from .utils import import_string
  from .utils import pass_context
label_desc: Use image node_id 7 for calling the InternationalizationExtension obj's underlying member method code with example usage: obj.parse(parser) and returns: list, node