1 """Graphical user interface for i18n administration"""
2
3 import os
4 import sys
5 import time
6 import shutil
7 import codecs
8
9 import turbogears
10 from turbogears import controllers, expose, i18n
11 from turbogears.i18n.pygettext import pygettext
12 from turbogears.i18n.pygettext import msgfmt
13 from turbogears.i18n.pygettext import catalog
14
15 import cherrypy
16 from cherrypy.lib import static
17
18
19 supported_exts = ['.py', '.kid', '.tmpl', '.html', '.mak']
23 """I18N administration tool.
24
25 Collect your strings, add and manage locales,
26 edit and compile your catalogs.
27
28 """
29
30 __label__ = 'admi18n'
31 __version__ = '0.1'
32 __author__ = 'Ronald Jaramillo'
33 __email__ = 'ronald@checkandshare.com'
34 __copyright__ = 'Copyright 2005 Ronald Jaramillo'
35 __license__ = 'MIT'
36
37 baseTemplate = 'turbogears.toolbox.admi18n'
38 languages = None
39 icon = "/tg_static/images/admi18n.png"
40 need_project = True
41
42 - def __init__(self, currentProject=None):
43 self.currentProject = currentProject
44 if not self.currentProject:
45 self.currentProject = os.getcwd()
46
52
54 locales = self.locales_directory()
55 if type(code) != type([]):
56 code = [code]
57
58 for c in code:
59 path = os.path.join(locales, c)
60 try:
61 shutil.rmtree(path)
62 except OSError,e:
63 print e
64 return
65
76
78 locales = self.locales_directory()
79 src = os.path.join(locales, 'messages.pot')
80 paths = []
81 for code in codes.split(','):
82 path = os.path.join(locales, code, 'LC_MESSAGES', 'messages.po')
83 if not os.path.exists(path):
84 continue
85
86 paths.append(path)
87 catalog.merge(src, paths)
88
90 locales = self.locales_directory()
91 path = os.path.join(locales, code)
92 try:
93 os.mkdir(path)
94 except OSError, e:
95 print e
96 return
97
98 path = os.path.join(path, 'LC_MESSAGES')
99 try:
100 os.mkdir(path)
101 except OSError, e:
102 print e
103 return
104
105 src = os.path.join(locales, 'messages.pot')
106 dest = os.path.join(path, 'messages.po')
107 shutil.copy(src, dest)
108
109 @expose('json')
111 path = os.path.join(self.locales_directory(),
112 code, 'LC_MESSAGES', 'messages.po')
113 f = codecs.open(path, 'wb', 'utf-8')
114 f.write(unicode(myFile.file.read(), 'utf-8', errors='replace'))
115 f.close()
116 raise cherrypy.HTTPRedirect(turbogears.url('language', code=code))
117
119 path = os.path.join(self.locales_directory(),
120 code, 'LC_MESSAGES', 'messages.po')
121 for arg in args:
122 if not 'text_' in arg:
123 continue
124 msg_id = args[arg].strip()
125 if '\r' in msg_id:
126 msg_id = '\n'.join(msg_id.splitlines())
127 translated = i18n.utils.google_translate(
128 from_lang, to_lang, msg_id)
129 catalog.update(path, msg_id, translated)
130
131 @expose('json')
137
138 @expose('%s.po_view' % baseTemplate)
139 - def po_view(self, code, sort_by=None, dir=None,
140 from_lang=None, to_lang=None, **kargs):
141 visible_checkbox = False
142 if from_lang and to_lang:
143 visible_checkbox = True
144 self.google_translate(code, from_lang, to_lang, kargs)
145 path = os.path.join(self.locales_directory(),
146 code, 'LC_MESSAGES', 'messages.po')
147 return dict(code=code, catalog=catalog.items(path, sort_by, dir),
148 visible_checkbox=visible_checkbox)
149
150 @expose('%s.language' % baseTemplate)
160
161 @expose('json')
164
165 @expose('%s.languageManagement' % baseTemplate)
177
182
184 locales_dir = os.path.join(self.currentProject, 'locales')
185 if not os.path.isdir(locales_dir):
186 try:
187 os.mkdir(locales_dir)
188 except OSError, e:
189 print e
190 return
191 return locales_dir
192
194 locales = []
195 locales_dir = self.locales_directory()
196 if not locales_dir:
197 return locales
198
199 for item in os.listdir(locales_dir):
200 path = os.path.join(locales_dir, item)
201 if not os.path.isdir(path):
202 continue
203
204 language = self.language_for_code(item)
205 if not language:
206 continue
207
208 modified = '-'
209 compiled = '-'
210 po = os.path.join(path, 'LC_MESSAGES', 'messages.po')
211 mo = os.path.join(path, 'LC_MESSAGES', 'messages.mo')
212 if os.path.exists(po):
213 modified = time.ctime(os.path.getmtime(po))
214
215 if os.path.exists(mo):
216 compiled = time.ctime(os.path.getmtime(mo))
217
218 locales.append(dict(
219 code=item,
220 language=language,
221 coverage=0,
222 status=0,
223 modified=modified,
224 compiled=compiled
225 ))
226 return locales
227
229 p = turbogears.util.get_package_name()
230 base_level = len([x for x in p.split(os.sep) if x])
231 fl, dct, visibility = [], {}, {}
232
233 def collect_files(file_list, dirpath, namelist):
234 level = len([x for x in dirpath.split(os.sep) if x]) - base_level
235 slot0 = dict(
236 dir=os.path.dirname(dirpath),
237 file_name=os.path.basename(dirpath),
238 path=dirpath, isdir=True, level=level)
239 slot1 = list()
240 slot2 = list()
241 slots = (slot0, slot1, slot2)
242 dct[dirpath] = slots
243 if level:
244 dct[os.path.dirname(dirpath)][1].append(slots)
245 else:
246 file_list.append(slots)
247
248 namelist.sort()
249 for name in namelist[:]:
250 if (name.startswith('.')
251 or name in ['static', 'sqlobject-history']):
252 namelist.remove(name)
253 continue
254
255 p = os.path.join(dirpath, name)
256 if (os.path.isfile(p)
257 and os.path.splitext(name)[-1] in supported_exts):
258 slot2.append(dict(dir=dirpath, file_name=name,
259 path=p, isdir=os.path.isdir(p), level=level+1))
260
261
262 visibility[dirpath] = bool(slot2)
263 if slot2:
264 while not visibility.get(os.path.dirname(dirpath), True):
265 dirpath = os.path.dirname(dirpath)
266 visibility[dirpath] = True
267
268 os.path.walk(p, collect_files, fl)
269 return [x for x in turbogears.util.flatten_sequence(fl)
270 if not x['isdir'] or visibility[x['path']]]
271
273 if not files:
274 return
275
276 params = ['', '-v']
277 for file in files:
278 params.append(file)
279
280 pygettext.sys.argv = params
281 pygettext.main()
282
283 pot = os.path.join(self.currentProject, 'messages.pot')
284 if not os.path.exists(pot):
285 return
286
287 locales = self.locales_directory()
288 filename = os.path.join(locales, 'messages.pot')
289 try:
290 shutil.copyfile(pot, filename)
291 except IOError, e:
292 print e
293
295 locales = self.locales_directory()
296 pot = os.path.join(locales, 'messages.pot')
297 if not os.path.exists(pot):
298 return
299
300 return dict(name='messages.pot', path=pot,
301 modified=time.ctime(os.path.getmtime(pot)),
302 size=os.path.getsize(pot))
303
304 @expose()
306
307 locales = self.locales_directory()
308 if code == 'pot':
309 path = os.path.join(locales, 'messages.pot')
310 else:
311 path = os.path.join(locales, code)
312 path = os.path.join(path, 'LC_MESSAGES')
313 path = os.path.join(path, 'messages.po')
314 if 'If-Modified-Since' in cherrypy.request.headers:
315 del cherrypy.request.headers['If-Modified-Since']
316 return static.serve_file(path, 'application/x-download', 'attachment')
317
318 @expose('%s.stringCollection' % baseTemplate)
326
327 @expose('%s.internationalization' % baseTemplate)
330