diff options
Diffstat (limited to 'rbutil/rbutilqt/langstats.py')
-rwxr-xr-x | rbutil/rbutilqt/langstats.py | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/langstats.py b/rbutil/rbutilqt/langstats.py new file mode 100755 index 0000000000..068862f431 --- /dev/null +++ b/rbutil/rbutilqt/langstats.py | |||
@@ -0,0 +1,213 @@ | |||
1 | #!/usr/bin/python | ||
2 | |||
3 | # | ||
4 | # lrelease all rbutil translations and create a nice table from the output | ||
5 | # suited to paste in the wiki. | ||
6 | # | ||
7 | # (c) 2010 Dominik Riebeling | ||
8 | # | ||
9 | |||
10 | import subprocess | ||
11 | import re | ||
12 | import sys | ||
13 | import string | ||
14 | import pysvn | ||
15 | import tempfile | ||
16 | import os | ||
17 | import shutil | ||
18 | from datetime import date | ||
19 | |||
20 | |||
21 | langs = { | ||
22 | 'cs' : 'Czech', | ||
23 | 'de' : 'German', | ||
24 | 'fi' : 'Finnish', | ||
25 | 'fr' : 'French', | ||
26 | 'gr' : 'Greek', | ||
27 | 'he' : 'Hebrew', | ||
28 | 'ja' : 'Japanese', | ||
29 | 'nl' : 'Dutch', | ||
30 | 'pl' : 'Polish', | ||
31 | 'pt' : 'Portuguese', | ||
32 | 'pt_BR' : 'Portuguese (Brasileiro)', | ||
33 | 'ru' : 'Russian', | ||
34 | 'tr' : 'Turkish', | ||
35 | 'zh_CN' : 'Chinese', | ||
36 | 'zh_TW' : 'Chinese (trad)' | ||
37 | } | ||
38 | |||
39 | # modules that are not part of python itself. | ||
40 | try: | ||
41 | import pysvn | ||
42 | except ImportError: | ||
43 | print "Fatal: This script requires the pysvn package to run." | ||
44 | print " See http://pysvn.tigris.org/." | ||
45 | sys.exit(-5) | ||
46 | |||
47 | |||
48 | svnserver = "svn://svn.rockbox.org/rockbox/trunk/" | ||
49 | langbase = "rbutil/rbutilqt/" | ||
50 | # Paths and files to retrieve from svn. | ||
51 | # This is a mixed list, holding both paths and filenames. | ||
52 | # Get cpp sources as well for lupdate to work. | ||
53 | svnpaths = [ langbase ] | ||
54 | |||
55 | def printhelp(): | ||
56 | print "Usage:", sys.argv[0], "[options]" | ||
57 | print "Print translation statistics suitable for pasting in the wiki." | ||
58 | print "Options:" | ||
59 | print " --pretty: display pretty output instead of wiki-style" | ||
60 | print " --help: show this help" | ||
61 | |||
62 | |||
63 | def gettrunkrev(svnsrv): | ||
64 | '''Get the revision of trunk for svnsrv''' | ||
65 | client = pysvn.Client() | ||
66 | entries = client.info2(svnsrv, recurse=False) | ||
67 | return entries[0][1].rev.number | ||
68 | |||
69 | |||
70 | def getsources(svnsrv, filelist, dest): | ||
71 | '''Get the files listed in filelist from svnsrv and put it at dest.''' | ||
72 | client = pysvn.Client() | ||
73 | print "Checking out sources from %s, please wait." % svnsrv | ||
74 | |||
75 | for elem in filelist: | ||
76 | url = re.subn('/$', '', svnsrv + elem)[0] | ||
77 | destpath = re.subn('/$', '', dest + elem)[0] | ||
78 | # make sure the destination path does exist | ||
79 | d = os.path.dirname(destpath) | ||
80 | if not os.path.exists(d): | ||
81 | os.makedirs(d) | ||
82 | # get from svn | ||
83 | try: | ||
84 | client.export(url, destpath) | ||
85 | except: | ||
86 | print "SVN client error: %s" % sys.exc_value | ||
87 | print "URL: %s, destination: %s" % (url, destpath) | ||
88 | return -1 | ||
89 | print "Checkout finished." | ||
90 | return 0 | ||
91 | |||
92 | |||
93 | def main(): | ||
94 | if len(sys.argv) > 1: | ||
95 | if sys.argv[1] == '--help': | ||
96 | printhelp() | ||
97 | sys.exit(0) | ||
98 | if len(sys.argv) > 1: | ||
99 | if sys.argv[1] == '--pretty': | ||
100 | pretty = 1 | ||
101 | else: | ||
102 | pretty = 0 | ||
103 | |||
104 | # get svnpaths to temporary folder | ||
105 | workfolder = tempfile.mkdtemp() + "/" | ||
106 | getsources(svnserver, svnpaths, workfolder) | ||
107 | |||
108 | projectfolder = workfolder + langbase | ||
109 | # lupdate translations and drop all obsolete translations | ||
110 | subprocess.Popen(["lupdate-qt4", "-no-obsolete", "rbutilqt.pro"], \ | ||
111 | stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=projectfolder).communicate() | ||
112 | # lrelease translations to get status | ||
113 | output = subprocess.Popen(["lrelease-qt4", "rbutilqt.pro"], stdout=subprocess.PIPE, \ | ||
114 | stderr=subprocess.PIPE, cwd=projectfolder).communicate() | ||
115 | lines = re.split(r"\n", output[0]) | ||
116 | |||
117 | re_updating = re.compile(r"^Updating.*") | ||
118 | re_generated = re.compile(r"Generated.*") | ||
119 | re_ignored = re.compile(r"Ignored.*") | ||
120 | re_qmlang = re.compile(r"'.*/rbutil_(.*)\.qm'") | ||
121 | re_qmbase = re.compile(r"'.*/(rbutil_.*)\.qm'") | ||
122 | re_genout = re.compile(r"[^0-9]([0-9]+) .*[^0-9]([0-9]+) .*[^0-9]([0-9]+) ") | ||
123 | re_ignout = re.compile(r"([0-9]+) ") | ||
124 | |||
125 | # print header | ||
126 | titlemax = 0 | ||
127 | for l in langs: | ||
128 | cur = len(langs[l]) | ||
129 | if titlemax < cur: | ||
130 | titlemax = cur | ||
131 | |||
132 | if pretty == 1: | ||
133 | delim = "+-" + titlemax * "-" \ | ||
134 | + "-+-------+-----+-----+-----+-----+--------------------+-----------------+" | ||
135 | head = "| Language" + (titlemax - 8) * " " \ | ||
136 | + " | Code |Trans| Fin |Unfin| Untr| Updated | Done |" | ||
137 | print delim | ||
138 | print "|" + " " * (len(head) / 2 - 3) + str(gettrunkrev(svnserver)) \ | ||
139 | + " " * (len(head) / 2 - 4) + "|" | ||
140 | print delim | ||
141 | print head | ||
142 | print delim | ||
143 | else: | ||
144 | print "| *Translation status as of revision " + str(gettrunkrev(svnserver)) + "* ||||||||" | ||
145 | print "| *Language* | *Language Code* | *Translations* | *Finished* | " \ | ||
146 | "*Unfinished* | *Untranslated* | *Updated* | *Done* |" | ||
147 | |||
148 | client = pysvn.Client() | ||
149 | # scan output | ||
150 | i = 0 | ||
151 | while i < len(lines): | ||
152 | line = lines[i] | ||
153 | if re_updating.search(line): | ||
154 | lang = re_qmlang.findall(line) | ||
155 | tsfile = "lang/" + re_qmbase.findall(line)[0] + ".ts" | ||
156 | fileinfo = client.info2(svnserver + langbase + tsfile)[0][1] | ||
157 | tsrev = fileinfo.last_changed_rev.number | ||
158 | tsdate = date.fromtimestamp(fileinfo.last_changed_date).isoformat() | ||
159 | |||
160 | line = lines[i + 1] | ||
161 | if re_generated.search(line): | ||
162 | values = re_genout.findall(line) | ||
163 | translations = string.atoi(values[0][0]) | ||
164 | finished = string.atoi(values[0][1]) | ||
165 | unfinished = string.atoi(values[0][2]) | ||
166 | line = lines[i + 2] | ||
167 | if not line.strip(): | ||
168 | line = lines[i + 3] | ||
169 | if re_ignored.search(line): | ||
170 | ignored = string.atoi(re_ignout.findall(line)[0]) | ||
171 | else: | ||
172 | ignored = 0 | ||
173 | if langs.has_key(lang[0]): | ||
174 | name = langs[lang[0]].strip() | ||
175 | else: | ||
176 | name = '(unknown)' | ||
177 | |||
178 | percent = (float(finished + unfinished) * 100 / float(translations + ignored)) | ||
179 | bar = "#" * int(percent / 10) | ||
180 | if (percent % 10) > 5: | ||
181 | bar += "+" | ||
182 | bar += " " * (10 - len(bar)) | ||
183 | if pretty == 1: | ||
184 | fancylang = lang[0] + " " * (5 - len(lang[0])) | ||
185 | else: | ||
186 | fancylang = lang[0] | ||
187 | tsversion = str(tsrev) + " (" + tsdate + ")" | ||
188 | status = [fancylang, translations, finished, unfinished, ignored, tsversion, percent, bar] | ||
189 | if pretty == 1: | ||
190 | thisname = name + (titlemax - len(name)) * " " | ||
191 | print "| " + thisname + " | %5s | %3s | %3s | %3s | %3s | %6s | %3i%% %s |" % tuple(status) | ||
192 | else: | ||
193 | if percent > 90: | ||
194 | color = '%%GREEN%%' | ||
195 | else: | ||
196 | if percent > 50: | ||
197 | color = '%%ORANGE%%' | ||
198 | else: | ||
199 | color = '%%RED%%' | ||
200 | |||
201 | text = "| " + name + " | %s | %s | %s | %s | %s | %s | " + color + "%3i%%%%ENDCOLOR%% %s |" | ||
202 | print text % tuple(status) | ||
203 | i += 1 | ||
204 | |||
205 | if pretty == 1: | ||
206 | print delim | ||
207 | |||
208 | shutil.rmtree(workfolder) | ||
209 | |||
210 | |||
211 | if __name__ == "__main__": | ||
212 | main() | ||
213 | |||