parameters: (self, parser)
docstring: Parse a translatable tag.
docstring_summary: Parse a translatable tag.
docstring_tokens: Parse a translatable tag .
function: def parse(self, parser):
          """Parse a translatable tag."""
          lineno = next(parser.stream).lineno
          num_called_num = False
  
          # 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 = None
          plural_expr_assignment = None
          variables = {}
          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
  
              name = parser.stream.expect("name")
              if name.value in variables:
                  parser.fail(
                      "translatable variable %r defined twice." % name.value,
                      name.lineno,
                      exc=TemplateAssertionError,
                  )
  
              # expressions
              if parser.stream.current.type == "assign":
                  next(parser.stream)
                  variables[name.value] = var = parser.parse_expression()
              elif trimmed is None and name.value in ("trimmed", "notrimmed"):
                  trimmed = name.value == "trimmed"
                  continue
              else:
                  variables[name.value] = var = nodes.Name(name.value, "load")
  
              if plural_expr is None:
                  if isinstance(var, nodes.Call):
                      plural_expr = nodes.Name("_trans", "load")
                      variables[name.value] = plural_expr
                      plural_expr_assignment = nodes.Assign(
                          nodes.Name("_trans", "store"), var
                      )
                  else:
                      plural_expr = var
                  num_called_num = name.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":
                  name = parser.stream.expect("name")
                  if name.value not in variables:
                      parser.fail(
                          "unknown variable %r for pluralization" % name.value,
                          name.lineno,
                          exc=TemplateAssertionError,
                      )
                  plural_expr = variables[name.value]
                  num_called_num = name.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 var in referenced:
              if var not in variables:
                  variables[var] = nodes.Name(var, "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,
              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
function_tokens: def parse ( self , parser ) : lineno = next ( parser . stream ) . lineno num_called_num = False # 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 = None plural_expr_assignment = None variables = { } 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 name = parser . stream . expect ( "name" ) if name . value in variables : parser . fail ( "translatable variable %r defined twice." % name . value , name . lineno , exc = TemplateAssertionError , ) # expressions if parser . stream . current . type == "assign" : next ( parser . stream ) variables [ name . value ] = var = parser . parse_expression ( ) elif trimmed is None and name . value in ( "trimmed" , "notrimmed" ) : trimmed = name . value == "trimmed" continue else : variables [ name . value ] = var = nodes . Name ( name . value , "load" ) if plural_expr is None : if isinstance ( var , nodes . Call ) : plural_expr = nodes . Name ( "_trans" , "load" ) variables [ name . value ] = plural_expr plural_expr_assignment = nodes . Assign ( nodes . Name ( "_trans" , "store" ) , var ) else : plural_expr = var num_called_num = name . 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" : name = parser . stream . expect ( "name" ) if name . value not in variables : parser . fail ( "unknown variable %r for pluralization" % name . value , name . lineno , exc = TemplateAssertionError , ) plural_expr = variables [ name . value ] num_called_num = name . 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 var in referenced : if var not in variables : variables [ var ] = nodes . Name ( var , "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 , 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