forked from amandasaurus/django-template-i18n-lint
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdjango-template-i18n-lint.py
executable file
·114 lines (81 loc) · 2.82 KB
/
django-template-i18n-lint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#! /usr/bin/python
"""
Prints out all
"""
import sys, re
def location(str, pos):
"""Given a string str and an integer pos, find the line number and character in that line that correspond to pos"""
lineno, charpos = 1, 1
counter = 0
for char in str:
if counter == pos:
return lineno, charpos
elif char == '\n':
lineno += 1
charpos = 1
counter += 1
else:
charpos += 1
counter += 1
return lineno, charpos
# Things that are OK:
GOOD_STRINGS = re.compile(
r"""
# django comment
( {%\ comment\ %}.*?{%\ endcomment\ %}
# already translated text
|{%\ ?blocktrans.*?{%\ ?endblocktrans\ ?%}
# any django template function (catches {% trans ..) aswell
|{%.*?%}
# JS
|<script.*?</script>
# A html title or value attribute that's been translated
|(?:value|title|summary|alt)="{%\ ?trans.*?%}"
# A html title or value attribute that's just a template var
|(?:value|title|summary|alt)="{{.*?}}"
# An <option> value tag
|<option[^<>]+?value="[^"]*?"
# Any html attribute that's not value or title
|[a-z:-]+?(?<!alt)(?<!value)(?<!title)(?<!summary)="[^"]*?"
# HTML opening tag
|<[\w:]+
# End of a html opening tag
|>
|/>
# closing html tag
|</.*?>
# any django template variable
|{{.*?}}
# HTML doctype
|<!DOCTYPE.*?>
# IE specific HTML
|<!--\[if.*?<!\[endif\]-->
# HTML comment
|<!--.*?-->
# HTML entities
|&[a-z]{1,10};
# CSS style
|<style.*?</style>
# another common template comment
|{\#.*?\#}
)""",
# MULTILINE to match across lines and DOTALL to make . include the newline
re.MULTILINE|re.DOTALL|re.VERBOSE)
# Stops us matching non-letter parts, e.g. just hypens, full stops etc.
LETTERS = re.compile("\w")
def non_translated_text(filename):
template = open(filename).read()
offset = 0
# Find the parts of the template that don't match this regex
# taken from http://www.technomancy.org/python/strings-that-dont-match-regex/
for index, match in enumerate(GOOD_STRINGS.split(template)):
if index % 2 == 0:
# Ignore it if it doesn't have letters
if LETTERS.search(match):
lineno, charpos = location(template, offset)
yield (lineno, charpos, match.strip().replace("\n", "").replace("\r", "")[:120])
offset += len(match)
if __name__ == '__main__':
filename = sys.argv[1]
for lineno, charpos, message in non_translated_text(filename):
print "%s:%s:%s:%s" % (filename, lineno, charpos, message)