forked from SEL-Columbia/formhub
-
Notifications
You must be signed in to change notification settings - Fork 2
/
i18ntool.py
executable file
·244 lines (198 loc) · 7.35 KB
/
i18ntool.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/usr/bin/env python
# encoding: utf-8
'''
Wrapper script around common use of i18n.
1. Add new language: creates PO files and instruct how to add to transifex.
2. Update languages: Regenerate English PO files. TX gets it automaticaly.
3. Update translations: download translations from TX and compiles them. '''
import os
import sys
import StringIO
import tempfile
import types
import shutil
import contextlib
import twill
from twill import commands as tw, get_browser
from twill.errors import TwillAssertionError
from clint import args
from clint.textui import puts, colored, indent
from shell_command import shell_call
# List of languages we care about
LANGS = ['en', 'fr', 'es', 'it', 'nl', 'zh', 'ne', 'km']
I18N_APPS = ['main', 'odk_viewer']
TX_LOGIN_URL = u'https://www.transifex.com/signin/'
REPO_ROOT = os.path.dirname(os.path.abspath(__file__))
class DownloadFailed(StandardError):
pass
@contextlib.contextmanager
def chdir(dirname):
curdir = os.getcwd()
try:
os.chdir(dirname)
yield
finally:
os.chdir(curdir)
def download_with_login(url, login_url, login=None,
password=None, ext='',
username_field='username',
password_field='password',
form_id=1):
''' Download a URI from a website using Django by loging-in first
1. Logs in using supplied login & password (if provided)
2. Create a temp file on disk using extension if provided
3. Write content of URI into file '''
# log-in to Django site
if login and password:
tw.go(login_url)
tw.formvalue('%s' % form_id, username_field, login)
tw.formvalue('%s' % form_id, password_field, password)
tw.submit()
# retrieve URI
try:
tw.go(url)
tw.code('200')
except TwillAssertionError:
code = get_browser().get_code()
# ensure we don't keep credentials
tw.reset_browser()
raise DownloadFailed(u"Unable to download %(url)s. "
u"Received HTTP #%(code)s."
% {'url': url, 'code': code})
buff = StringIO.StringIO()
twill.set_output(buff)
try:
tw.show()
finally:
twill.set_output(None)
tw.reset_browser()
# write file on disk
suffix = '.%s' % ext if ext else ''
fileh, filename = tempfile.mkstemp(suffix=suffix)
os.write(fileh, buff.getvalue())
os.close(fileh)
buff.close()
return filename
def getlangs(lang):
if not lang:
return LANGS
if isinstance(lang, types.ListType):
return lang
return [lang, ]
def add(lang):
langs = getlangs(lang)
puts(u"Adding %s" % ', '.join(langs))
for loc in langs:
with indent(2):
puts(u"Generating PO for %s" % loc)
shell_call(u"django-admin.py makemessages -l %(lang)s "
u"-e py,html,email,txt" % {'lang': loc})
for app in I18N_APPS:
with indent(4):
puts(u"Generating PO for app %s" % app)
with chdir(os.path.join(REPO_ROOT, app)):
shell_call(u"django-admin.py makemessages "
u"-d djangojs -l %(lang)s" % {'lang': loc})
puts(colored.green("sucesssfuly generated %s" % loc))
def update(user, password, lang=None):
langs = getlangs(lang)
puts(u"Updating %s" % ', '.join(langs))
for loc in langs:
with indent(2):
puts(u"Downloading PO for %s" % loc)
url = (u'https://www.transifex.com/projects/p/formhub/'
u'resource/django/l/%(lang)s/download/for_use/' % {'lang': loc})
try:
tmp_po_file = download_with_login(url, TX_LOGIN_URL,
login=user, password=password,
ext='po',
username_field='identification',
password_field='password',
form_id=1)
po_file = os.path.join(REPO_ROOT, 'locale', loc,
'LC_MESSAGES', 'django.po')
with indent(2):
puts(u"Copying downloaded file to %s" % po_file)
shutil.move(tmp_po_file, po_file)
except Exception as e:
puts(colored.red(u"Unable to update %s "
u"from Transifex: %r" % (loc, e)))
puts(colored.green("sucesssfuly retrieved %s" % loc))
compile_mo(langs)
def compile_mo(lang=None):
langs = getlangs(lang)
puts(u"Compiling %s" % ', '.join(langs))
for loc in langs:
with indent(2):
puts(u"Compiling %s" % loc)
shell_call(u"django-admin.py compilemessages -l %(lang)s "
% {'lang': loc})
for app in I18N_APPS:
with indent(4):
puts(u"Compiling app %s" % app)
with chdir(os.path.join(REPO_ROOT, app)):
shell_call(u"django-admin.py compilemessages -l %(lang)s"
% {'lang': loc})
puts(colored.green("sucesssfuly compiled %s" % loc))
def usage(exit=True, code=1):
print(u"i18n wrapper script for formhub.\n")
with indent(4):
puts(colored.yellow(u",/i18ntool.py add --lang <lang>"))
puts(u"Create required files for enabling translation "
u"of language with code <lang>\n")
puts(colored.yellow(u"./i18ntool.py refresh [--lang <lang>]"))
puts(u"Update the PO file for <lang> based on code.\n"
u"<lang> is optionnal as we only use EN and do "
u"all translations in Transifex.\n")
puts(colored.yellow(u"./i18ntool.py update --user <tx_user> "
u"--password <tx_pass> [--lang <lang>]"))
puts(u"Downloads new PO files for <lang> (or all) from Transifex "
u"then compiles new MO files\n")
puts(colored.yellow(u"./i18ntool.py compile [--lang <lang>]"))
puts(u"Compiles all PO files for <lang> (or all) into MO files.\n"
u"Not required unless you want to.\n")
if exit:
sys.exit(code)
COMMANDS = {
'add': add,
'refresh': add,
'update': update,
'compile': compile_mo,
'usage': usage,
'help': usage
}
def main():
try:
command = COMMANDS.get(args.all.pop(0).lower(), usage)
except:
command = usage
# fallback to usage.
if command is usage:
return command()
# retrieve lang
try:
lang = args.grouped.get('lang', []).pop(0)
if not lang in LANGS:
raise ValueError(u"Unknown lang code")
except ValueError as e:
puts(colored.red(e.message))
usage()
except IndexError:
lang = None
# update cmd requires more args.
if command is update:
# extract user & password
try:
user = args.grouped.get('--user', []).pop(0)
password = args.grouped.get('--password', []).pop(0)
except:
raise
user = password = None
if not user or not password:
print(colored.red(u"You need to provide Transifex.com credentials"))
usage()
return command(user, password, lang)
# execute command with lang argument.
return command(lang)
if __name__ == '__main__':
main()