docs: def parse(self, parser):
          """Parse a translatable tag."""
          lineno = next(parser.stream).lineno
  
          # 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
          variables = {}
          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()
              else:
                  variables[name.value] = var = nodes.Name(name.value, 'load')
              if plural_expr is None:
                  plural_expr = var
  
          parser.stream.expect('block_end')
  
          plural = plural_names = 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')
  
          # 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]
              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')
  
          # no variables referenced?  no need to escape
          if not referenced:
              singular = singular.replace('%%', '%')
              if plural:
                  plural = plural.replace('%%', '%')
  
          if not have_plural:
              plural_expr = None
          elif plural_expr is None:
              parser.fail('pluralize without variables', lineno)
  
          if variables:
              variables = nodes.Dict([nodes.Pair(nodes.Const(x, lineno=lineno), y)
                                      for x, y in variables.items()])
          else:
              variables = None
  
          node = self._make_node(singular, plural, variables, plural_expr)
          node.set_lineno(lineno)
          return node