Mercurial > hg-stable
comparison i18n/check-translation.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 19fc5a986669 |
children | c102b704edb5 |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
8 import polib | 8 import polib |
9 | 9 |
10 scanners = [] | 10 scanners = [] |
11 checkers = [] | 11 checkers = [] |
12 | 12 |
13 | |
13 def scanner(): | 14 def scanner(): |
14 def decorator(func): | 15 def decorator(func): |
15 scanners.append(func) | 16 scanners.append(func) |
16 return func | 17 return func |
18 | |
17 return decorator | 19 return decorator |
20 | |
18 | 21 |
19 def levelchecker(level, msgidpat): | 22 def levelchecker(level, msgidpat): |
20 def decorator(func): | 23 def decorator(func): |
21 if msgidpat: | 24 if msgidpat: |
22 match = re.compile(msgidpat).search | 25 match = re.compile(msgidpat).search |
23 else: | 26 else: |
24 match = lambda msgid: True | 27 match = lambda msgid: True |
25 checkers.append((func, level)) | 28 checkers.append((func, level)) |
26 func.match = match | 29 func.match = match |
27 return func | 30 return func |
31 | |
28 return decorator | 32 return decorator |
33 | |
29 | 34 |
30 def match(checker, pe): | 35 def match(checker, pe): |
31 """Examine whether POEntry "pe" is target of specified checker or not | 36 """Examine whether POEntry "pe" is target of specified checker or not |
32 """ | 37 """ |
33 if not checker.match(pe.msgid): | 38 if not checker.match(pe.msgid): |
37 for tc in pe.tcomment.split(): | 42 for tc in pe.tcomment.split(): |
38 if nochecker == tc: | 43 if nochecker == tc: |
39 return | 44 return |
40 return True | 45 return True |
41 | 46 |
47 | |
42 #################### | 48 #################### |
49 | |
43 | 50 |
44 def fatalchecker(msgidpat=None): | 51 def fatalchecker(msgidpat=None): |
45 return levelchecker('fatal', msgidpat) | 52 return levelchecker('fatal', msgidpat) |
53 | |
46 | 54 |
47 @fatalchecker(r'\$\$') | 55 @fatalchecker(r'\$\$') |
48 def promptchoice(pe): | 56 def promptchoice(pe): |
49 """Check translation of the string given to "ui.promptchoice()" | 57 """Check translation of the string given to "ui.promptchoice()" |
50 | 58 |
68 if [c for c, i in indices if i == -1]: | 76 if [c for c, i in indices if i == -1]: |
69 yield "msgstr has invalid choice missing '&'" | 77 yield "msgstr has invalid choice missing '&'" |
70 if [c for c, i in indices if len(c) == i + 1]: | 78 if [c for c, i in indices if len(c) == i + 1]: |
71 yield "msgstr has invalid '&' followed by none" | 79 yield "msgstr has invalid '&' followed by none" |
72 | 80 |
81 | |
73 deprecatedpe = None | 82 deprecatedpe = None |
83 | |
84 | |
74 @scanner() | 85 @scanner() |
75 def deprecatedsetup(pofile): | 86 def deprecatedsetup(pofile): |
76 pes = [p for p in pofile if p.msgid == '(DEPRECATED)' and p.msgstr] | 87 pes = [p for p in pofile if p.msgid == '(DEPRECATED)' and p.msgstr] |
77 if len(pes): | 88 if len(pes): |
78 global deprecatedpe | 89 global deprecatedpe |
79 deprecatedpe = pes[0] | 90 deprecatedpe = pes[0] |
91 | |
80 | 92 |
81 @fatalchecker(r'\(DEPRECATED\)') | 93 @fatalchecker(r'\(DEPRECATED\)') |
82 def deprecated(pe): | 94 def deprecated(pe): |
83 """Check for DEPRECATED | 95 """Check for DEPRECATED |
84 >>> ped = polib.POEntry( | 96 >>> ped = polib.POEntry( |
107 >>> pe = polib.POEntry( | 119 >>> pe = polib.POEntry( |
108 ... msgid = 'Something (DEPRECATED, foo bar)', | 120 ... msgid = 'Something (DEPRECATED, foo bar)', |
109 ... msgstr= 'something (DETACERPED, foo bar)') | 121 ... msgstr= 'something (DETACERPED, foo bar)') |
110 >>> match(deprecated, pe) | 122 >>> match(deprecated, pe) |
111 """ | 123 """ |
112 if not ('(DEPRECATED)' in pe.msgstr or | 124 if not ( |
113 (deprecatedpe and | 125 '(DEPRECATED)' in pe.msgstr |
114 deprecatedpe.msgstr in pe.msgstr)): | 126 or (deprecatedpe and deprecatedpe.msgstr in pe.msgstr) |
127 ): | |
115 yield "msgstr inconsistently translated (DEPRECATED)" | 128 yield "msgstr inconsistently translated (DEPRECATED)" |
116 | 129 |
130 | |
117 #################### | 131 #################### |
132 | |
118 | 133 |
119 def warningchecker(msgidpat=None): | 134 def warningchecker(msgidpat=None): |
120 return levelchecker('warning', msgidpat) | 135 return levelchecker('warning', msgidpat) |
136 | |
121 | 137 |
122 @warningchecker() | 138 @warningchecker() |
123 def taildoublecolons(pe): | 139 def taildoublecolons(pe): |
124 """Check equality of tail '::'-ness between msgid and msgstr | 140 """Check equality of tail '::'-ness between msgid and msgstr |
125 | 141 |
139 tail '::'-ness differs between msgid and msgstr | 155 tail '::'-ness differs between msgid and msgstr |
140 """ | 156 """ |
141 if pe.msgid.endswith('::') != pe.msgstr.endswith('::'): | 157 if pe.msgid.endswith('::') != pe.msgstr.endswith('::'): |
142 yield "tail '::'-ness differs between msgid and msgstr" | 158 yield "tail '::'-ness differs between msgid and msgstr" |
143 | 159 |
160 | |
144 @warningchecker() | 161 @warningchecker() |
145 def indentation(pe): | 162 def indentation(pe): |
146 """Check equality of initial indentation between msgid and msgstr | 163 """Check equality of initial indentation between msgid and msgstr |
147 | 164 |
148 This may report unexpected warning, because this doesn't aware | 165 This may report unexpected warning, because this doesn't aware |
157 idindent = len(pe.msgid) - len(pe.msgid.lstrip()) | 174 idindent = len(pe.msgid) - len(pe.msgid.lstrip()) |
158 strindent = len(pe.msgstr) - len(pe.msgstr.lstrip()) | 175 strindent = len(pe.msgstr) - len(pe.msgstr.lstrip()) |
159 if idindent != strindent: | 176 if idindent != strindent: |
160 yield "initial indentation width differs betweeen msgid and msgstr" | 177 yield "initial indentation width differs betweeen msgid and msgstr" |
161 | 178 |
179 | |
162 #################### | 180 #################### |
163 | 181 |
182 | |
164 def check(pofile, fatal=True, warning=False): | 183 def check(pofile, fatal=True, warning=False): |
165 targetlevel = { 'fatal': fatal, 'warning': warning } | 184 targetlevel = {'fatal': fatal, 'warning': warning} |
166 targetcheckers = [(checker, level) | 185 targetcheckers = [ |
167 for checker, level in checkers | 186 (checker, level) for checker, level in checkers if targetlevel[level] |
168 if targetlevel[level]] | 187 ] |
169 if not targetcheckers: | 188 if not targetcheckers: |
170 return [] | 189 return [] |
171 | 190 |
172 detected = [] | 191 detected = [] |
173 for checker in scanners: | 192 for checker in scanners: |
174 checker(pofile) | 193 checker(pofile) |
175 for pe in pofile.translated_entries(): | 194 for pe in pofile.translated_entries(): |
176 errors = [] | 195 errors = [] |
177 for checker, level in targetcheckers: | 196 for checker, level in targetcheckers: |
178 if match(checker, pe): | 197 if match(checker, pe): |
179 errors.extend((level, checker.__name__, error) | 198 errors.extend( |
180 for error in checker(pe)) | 199 (level, checker.__name__, error) for error in checker(pe) |
200 ) | |
181 if errors: | 201 if errors: |
182 detected.append((pe, errors)) | 202 detected.append((pe, errors)) |
183 return detected | 203 return detected |
184 | 204 |
205 | |
185 ######################################## | 206 ######################################## |
186 | 207 |
187 if __name__ == "__main__": | 208 if __name__ == "__main__": |
188 import sys | 209 import sys |
189 import optparse | 210 import optparse |
190 | 211 |
191 optparser = optparse.OptionParser("""%prog [options] pofile ... | 212 optparser = optparse.OptionParser( |
213 """%prog [options] pofile ... | |
192 | 214 |
193 This checks Mercurial specific translation problems in specified | 215 This checks Mercurial specific translation problems in specified |
194 '*.po' files. | 216 '*.po' files. |
195 | 217 |
196 Each detected problems are shown in the format below:: | 218 Each detected problems are shown in the format below:: |
205 be separated by whitespaces:: | 227 be separated by whitespaces:: |
206 | 228 |
207 # no-foo-check | 229 # no-foo-check |
208 msgid = "....." | 230 msgid = "....." |
209 msgstr = "....." | 231 msgstr = "....." |
210 """) | 232 """ |
211 optparser.add_option("", "--warning", | 233 ) |
212 help="show also warning level problems", | 234 optparser.add_option( |
213 action="store_true") | 235 "", |
214 optparser.add_option("", "--doctest", | 236 "--warning", |
215 help="run doctest of this tool, instead of check", | 237 help="show also warning level problems", |
216 action="store_true") | 238 action="store_true", |
239 ) | |
240 optparser.add_option( | |
241 "", | |
242 "--doctest", | |
243 help="run doctest of this tool, instead of check", | |
244 action="store_true", | |
245 ) | |
217 (options, args) = optparser.parse_args() | 246 (options, args) = optparser.parse_args() |
218 | 247 |
219 if options.doctest: | 248 if options.doctest: |
220 import os | 249 import os |
250 | |
221 if 'TERM' in os.environ: | 251 if 'TERM' in os.environ: |
222 del os.environ['TERM'] | 252 del os.environ['TERM'] |
223 import doctest | 253 import doctest |
254 | |
224 failures, tests = doctest.testmod() | 255 failures, tests = doctest.testmod() |
225 sys.exit(failures and 1 or 0) | 256 sys.exit(failures and 1 or 0) |
226 | 257 |
227 detected = [] | 258 detected = [] |
228 warning = options.warning | 259 warning = options.warning |
229 for f in args: | 260 for f in args: |
230 detected.extend((f, pe, errors) | 261 detected.extend( |
231 for pe, errors in check(polib.pofile(f), | 262 (f, pe, errors) |
232 warning=warning)) | 263 for pe, errors in check(polib.pofile(f), warning=warning) |
264 ) | |
233 if detected: | 265 if detected: |
234 for f, pe, errors in detected: | 266 for f, pe, errors in detected: |
235 for level, checker, error in errors: | 267 for level, checker, error in errors: |
236 sys.stderr.write('%s:%d:%s(%s): %s\n' | 268 sys.stderr.write( |
237 % (f, pe.linenum, level, checker, error)) | 269 '%s:%d:%s(%s): %s\n' |
270 % (f, pe.linenum, level, checker, error) | |
271 ) | |
238 sys.exit(1) | 272 sys.exit(1) |