extract.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2007 Edgewall Software
  4. # All rights reserved.
  5. #
  6. # This software is licensed as described in the file COPYING, which
  7. # you should have received as part of this distribution. The terms
  8. # are also available at http://babel.edgewall.org/wiki/License.
  9. #
  10. # This software consists of voluntary contributions made by many
  11. # individuals. For the exact contribution history, see the revision
  12. # history and logs, available at http://babel.edgewall.org/log/.
  13. from babel.core import *
  14. from django.conf import settings
  15. settings.configure(USE_I18N=True)
  16. from django.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK
  17. from django.utils.translation.trans_real import inline_re, block_re, \
  18. endblock_re, plural_re, \
  19. constant_re
  20. def extract_django(fileobj, keywords, comment_tags, options):
  21. """Extract messages from Django template files.
  22. :param fileobj: the file-like object the messages should be extracted from
  23. :param keywords: a list of keywords (i.e. function names) that should
  24. be recognized as translation functions
  25. :param comment_tags: a list of translator tags to search for and
  26. include in the results
  27. :param options: a dictionary of additional options (optional)
  28. :return: an iterator over ``(lineno, funcname, message, comments)``
  29. tuples
  30. :rtype: ``iterator``
  31. """
  32. intrans = False
  33. inplural = False
  34. singular = []
  35. plural = []
  36. lineno = 1
  37. for t in Lexer(fileobj.read(), None).tokenize():
  38. lineno += t.contents.count('\n')
  39. if intrans:
  40. if t.token_type == TOKEN_BLOCK:
  41. endbmatch = endblock_re.match(t.contents)
  42. pluralmatch = plural_re.match(t.contents)
  43. if endbmatch:
  44. if inplural:
  45. yield lineno, 'ngettext', (unicode(''.join(singular)),
  46. unicode(''.join(plural))), []
  47. else:
  48. yield lineno, None, unicode(''.join(singular)), []
  49. intrans = False
  50. inplural = False
  51. singular = []
  52. plural = []
  53. elif pluralmatch:
  54. inplural = True
  55. else:
  56. raise SyntaxError('Translation blocks must not include '
  57. 'other block tags: %s' % t.contents)
  58. elif t.token_type == TOKEN_VAR:
  59. if inplural:
  60. plural.append('%%(%s)s' % t.contents)
  61. else:
  62. singular.append('%%(%s)s' % t.contents)
  63. elif t.token_type == TOKEN_TEXT:
  64. if inplural:
  65. plural.append(t.contents)
  66. else:
  67. singular.append(t.contents)
  68. else:
  69. if t.token_type == TOKEN_BLOCK:
  70. imatch = inline_re.match(t.contents)
  71. bmatch = block_re.match(t.contents)
  72. cmatches = constant_re.findall(t.contents)
  73. if imatch:
  74. g = imatch.group(1)
  75. if g[0] == '"':
  76. g = g.strip('"')
  77. elif g[0] == "'":
  78. g = g.strip("'")
  79. yield lineno, None, unicode(g), []
  80. elif bmatch:
  81. for fmatch in constant_re.findall(t.contents):
  82. yield lineno, None, unicode(fmatch), []
  83. intrans = True
  84. inplural = False
  85. singular = []
  86. plural = []
  87. elif cmatches:
  88. for cmatch in cmatches:
  89. yield lineno, None, unicode(cmatch), []
  90. elif t.token_type == TOKEN_VAR:
  91. parts = t.contents.split('|')
  92. cmatch = constant_re.match(parts[0])
  93. if cmatch:
  94. yield lineno, None, unicode(cmatch.group(1)), []
  95. for p in parts[1:]:
  96. if p.find(':_(') >= 0:
  97. p1 = p.split(':',1)[1]
  98. if p1[0] == '_':
  99. p1 = p1[1:]
  100. if p1[0] == '(':
  101. p1 = p1.strip('()')
  102. if p1[0] == "'":
  103. p1 = p1.strip("'")
  104. elif p1[0] == '"':
  105. p1 = p1.strip('"')
  106. yield lineno, None, unicode(p1), []