diff --git a/django/core/management/commands/makemessages.py b/django/core/management/commands/makemessages.py
index 8c73d76..f02a3c8 100644
      
        
          
        
        
          
            | a | b | def make_messages(locale=None, domain='django', verbosity='1', all=False, | 
        
        
          
            | 220 | 220 | os.unlink(os.path.join(dirpath, thefile)) | 
          
            | 221 | 221 | elif domain == 'django' and (file_ext == '.py' or file_ext in extensions): | 
          
            | 222 | 222 | thefile = file | 
        
        
          
            |  | 223 | orig_file = os.path.join(dirpath, file) | 
        
        
          
            | 223 | 224 | if file_ext in extensions: | 
        
        
          
            | 224 |  | src = open(o s.path.join(dirpath, file), "rU").read() | 
          
            |  | 225 | src = open(orig_file, "rU").read() | 
        
        
          
            | 225 | 226 | thefile = '%s.py' % file | 
        
        
          
            |  | 227 | f = open(os.path.join(dirpath, thefile), "w") | 
        
        
          
            | 226 | 228 | try: | 
        
        
          
            | 227 |  | f = open(os.path.join(dirpath, thefile), "w") | 
          
            | 228 |  | try: | 
          
            | 229 |  | f.write(templatize(src)) | 
          
            | 230 |  | finally: | 
          
            | 231 |  | f.close() | 
          
            | 232 |  | except SyntaxError, msg: | 
          
            | 233 |  | msg = "%s (file: %s)" % (msg, os.path.join(dirpath, file)) | 
          
            | 234 |  | raise SyntaxError(msg) | 
          
            |  | 229 | f.write(templatize(src, orig_file[2:])) | 
          
            |  | 230 | finally: | 
          
            |  | 231 | f.close() | 
        
        
          
            | 235 | 232 | if verbosity > 1: | 
          
            | 236 | 233 | sys.stdout.write('processing file %s in %s\n' % (file, dirpath)) | 
          
            | 237 | 234 | cmd = ( | 
        
        
          
            | … | … | def make_messages(locale=None, domain='django', verbosity='1', all=False, | 
        
        
          
            | 250 | 247 |  | 
          
            | 251 | 248 | if thefile != file: | 
          
            | 252 | 249 | old = '#: '+os.path.join(dirpath, thefile)[2:] | 
        
        
          
            | 253 |  | new = '#: '+o s.path.join(dirpath, file)[2:] | 
          
            |  | 250 | new = '#: '+orig_file[2:] | 
        
        
          
            | 254 | 251 | msgs = msgs.replace(old, new) | 
          
            | 255 | 252 | if os.path.exists(potfile): | 
          
            | 256 | 253 | # Strip the header | 
        
      
    
    
      
      diff --git a/django/template/base.py b/django/template/base.py
index c6d646e..bd500d7 100644
      
        
          
        
        
          
            | a | b | def compile_string(template_string, origin): | 
        
        
          
            | 132 | 132 | else: | 
          
            | 133 | 133 | lexer_class, parser_class = Lexer, Parser | 
          
            | 134 | 134 | lexer = lexer_class(template_string, origin) | 
        
        
          
            | 135 |  | parser = parser_class(lexer.tokenize()) | 
          
            |  | 135 | tokens = lexer.tokenize() | 
          
            |  | 136 | tokens = zip(*tokens) | 
          
            |  | 137 | if tokens: | 
          
            |  | 138 | tokens = tokens[0] | 
          
            |  | 139 | parser = parser_class(list(tokens)) | 
        
        
          
            | 136 | 140 | return parser.parse() | 
          
            | 137 | 141 |  | 
          
            | 138 | 142 | class Token(object): | 
        
        
          
            | … | … | class Lexer(object): | 
        
        
          
            | 164 | 168 | def __init__(self, template_string, origin): | 
          
            | 165 | 169 | self.template_string = template_string | 
          
            | 166 | 170 | self.origin = origin | 
        
        
          
            |  | 171 | self.lineno = 1 | 
        
        
          
            | 167 | 172 |  | 
          
            | 168 | 173 | def tokenize(self): | 
          
            | 169 | 174 | "Return a list of tokens from a given template_string." | 
        
        
          
            | … | … | class Lexer(object): | 
        
        
          
            | 171 | 176 | result = [] | 
          
            | 172 | 177 | for bit in tag_re.split(self.template_string): | 
          
            | 173 | 178 | if bit: | 
        
        
          
            | 174 |  | result.append( self.create_token(bit, in_tag)) | 
          
            |  | 179 | result.append((self.create_token(bit, in_tag), self.lineno)) | 
        
        
          
            | 175 | 180 | in_tag = not in_tag | 
          
            | 176 | 181 | return result | 
          
            | 177 | 182 |  | 
        
        
          
            | … | … | class Lexer(object): | 
        
        
          
            | 193 | 198 | token = Token(TOKEN_COMMENT, content) | 
          
            | 194 | 199 | else: | 
          
            | 195 | 200 | token = Token(TOKEN_TEXT, token_string) | 
        
        
          
            |  | 201 | self.lineno += token_string.count('\n') | 
        
        
          
            | 196 | 202 | return token | 
          
            | 197 | 203 |  | 
          
            | 198 | 204 | class Parser(object): | 
        
      
    
    
      
      diff --git a/django/template/debug.py b/django/template/debug.py
index a9e3c4f..21ff65e 100644
      
        
          
        
        
          
            | a | b | class DebugLexer(Lexer): | 
        
        
          
            | 15 | 15 | for match in tag_re.finditer(self.template_string): | 
          
            | 16 | 16 | start, end = match.span() | 
          
            | 17 | 17 | if start > upto: | 
        
        
          
            | 18 |  | result.append( self.create_token(self.template_string[upto:start], (upto, start), False)) | 
          
            |  | 18 | result.append((self.create_token(self.template_string[upto:start], (upto, start), False), None)) | 
        
        
          
            | 19 | 19 | upto = start | 
        
        
          
            | 20 |  | result.append( self.create_token(self.template_string[start:end], (start, end), True)) | 
          
            |  | 20 | result.append((self.create_token(self.template_string[start:end], (start, end), True), None)) | 
        
        
          
            | 21 | 21 | upto = end | 
          
            | 22 | 22 | last_bit = self.template_string[upto:] | 
          
            | 23 | 23 | if last_bit: | 
        
        
          
            | 24 |  | result.append( self.create_token(last_bit, (upto, upto + len(last_bit)), False)) | 
          
            |  | 24 | result.append((self.create_token(last_bit, (upto, upto + len(last_bit)), False), None)) | 
        
        
          
            | 25 | 25 | return result | 
          
            | 26 | 26 |  | 
          
            | 27 | 27 | def create_token(self, token_string, source, in_tag): | 
        
      
    
    
      
      diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index 0e1b4f8..e3edb65 100644
      
        
          
        
        
          
            | a | b | def to_locale(language): | 
        
        
          
            | 104 | 104 | def get_language_from_request(request): | 
          
            | 105 | 105 | return _trans.get_language_from_request(request) | 
          
            | 106 | 106 |  | 
        
        
          
            | 107 |  | def templatize(src ): | 
          
            | 108 |  | return _trans.templatize(src ) | 
          
            |  | 107 | def templatize(src, origin=None): | 
          
            |  | 108 | return _trans.templatize(src, origin) | 
        
        
          
            | 109 | 109 |  | 
          
            | 110 | 110 | def deactivate_all(): | 
          
            | 111 | 111 | return _trans.deactivate_all() | 
        
      
    
    
      
      diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 832acc7..6dbe8e3 100644
      
        
          
        
        
          
            | a | b | endblock_re = re.compile(r"""^\s*endblocktrans$""") | 
        
        
          
            | 421 | 421 | plural_re = re.compile(r"""^\s*plural$""") | 
          
            | 422 | 422 | constant_re = re.compile(r"""_\(((?:".*?")|(?:'.*?'))\)""") | 
          
            | 423 | 423 |  | 
        
        
          
            | 424 |  | def templatize(src ): | 
          
            |  | 424 | def templatize(src, origin=None): | 
        
        
          
            | 425 | 425 | """ | 
          
            | 426 | 426 | Turns a Django template into something that is understood by xgettext. It | 
          
            | 427 | 427 | does so by translating the Django translation tags into standard gettext | 
        
        
          
            | … | … | def templatize(src): | 
        
        
          
            | 435 | 435 | plural = [] | 
          
            | 436 | 436 | incomment = False | 
          
            | 437 | 437 | comment = [] | 
        
        
          
            | 438 |  | for t  in Lexer(src, None).tokenize(): | 
          
            |  | 438 | for t, lineno in Lexer(src, origin).tokenize(): | 
        
        
          
            | 439 | 439 | if incomment: | 
          
            | 440 | 440 | if t.token_type == TOKEN_BLOCK and t.contents == 'endcomment': | 
          
            | 441 | 441 | out.write(' # %s' % ''.join(comment)) | 
        
        
          
            | … | … | def templatize(src): | 
        
        
          
            | 465 | 465 | elif pluralmatch: | 
          
            | 466 | 466 | inplural = True | 
          
            | 467 | 467 | else: | 
        
        
          
            | 468 |  | raise SyntaxError("Translation blocks must not include other block tags: %s" % t.contents) | 
          
            |  | 468 | filemsg = '' | 
          
            |  | 469 | if origin: | 
          
            |  | 470 | filemsg = 'file %s, ' % origin | 
          
            |  | 471 | raise SyntaxError("Translation blocks must not include other block tags: %s (%sline %d)" % (t.contents, filemsg, lineno)) | 
        
        
          
            | 469 | 472 | elif t.token_type == TOKEN_VAR: | 
          
            | 470 | 473 | if inplural: | 
          
            | 471 | 474 | plural.append('%%(%s)s' % t.contents) | 
        
      
    
    
      
      diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py
index 3e8d2d6..9061863 100644
      
        
          
        
        
          
            | a | b | class BasicExtractorTests(ExtractorTests): | 
        
        
          
            | 59 | 59 | self.assertMsgId('I think that 100%% is more that 50%% of anything.', po_contents) | 
          
            | 60 | 60 | self.assertMsgId('I think that 100%% is more that 50%% of %\(obj\)s.', po_contents) | 
          
            | 61 | 61 |  | 
        
        
          
            |  | 62 | def test_extraction_error(self): | 
          
            |  | 63 | os.chdir(self.test_dir) | 
          
            |  | 64 | shutil.copyfile('./templates/template_with_error.txt', './templates/template_with_error.html') | 
          
            |  | 65 | self.assertRaises(SyntaxError, management.call_command, 'makemessages', locale=LOCALE, verbosity=0) | 
          
            |  | 66 | try: | 
          
            |  | 67 | management.call_command('makemessages', locale=LOCALE, verbosity=0) | 
          
            |  | 68 | except SyntaxError, e: | 
          
            |  | 69 | self.assertEqual(str(e), 'Translation blocks must not include other block tags: blocktrans (file templates/template_with_error.html, line 3)') | 
          
            |  | 70 | finally: | 
          
            |  | 71 | os.remove('./templates/template_with_error.html') | 
          
            |  | 72 | os.remove('./templates/template_with_error.html.py') # Waiting for #8536 to be fixed | 
          
            |  | 73 |  | 
        
        
          
            | 62 | 74 |  | 
          
            | 63 | 75 | class JavascriptExtractorTests(ExtractorTests): | 
          
            | 64 | 76 |  | 
        
      
    
    
      
      diff --git a/tests/regressiontests/i18n/commands/templates/template_with_error.txt b/tests/regressiontests/i18n/commands/templates/template_with_error.txt
new file mode 100644
index 0000000..c2b93bd
      
        
          
        
        
          
            | - | + |  | 
        
        
          
            |  | 1 | {% load i18n %} | 
          
            |  | 2 | <p>This template contains an error (no endblocktrans)</p> | 
          
            |  | 3 | <p>{% blocktrans %}This should fail{% blocktrans %}</p> |