580
|
1 |
#! /usr/bin/env python
|
|
2 |
# -*- coding: iso-8859-1 -*-
|
|
3 |
#
|
|
4 |
# PYTHON MODULE: MKI18N.PY
|
|
5 |
# =========
|
|
6 |
#
|
|
7 |
# Abstract: Make Internationalization (i18n) files for an application.
|
|
8 |
#
|
|
9 |
# Copyright Pierre Rouleau. 2003. Released to public domain.
|
|
10 |
#
|
|
11 |
# Last update: Saturday, November 8, 2003. @ 15:55:18.
|
|
12 |
#
|
|
13 |
# File: ROUP2003N01::C:/dev/python/mki18n.py
|
|
14 |
#
|
|
15 |
# RCS $Header: //software/official/MKS/MKS_SI/TV_NT/dev/Python/rcs/mki18n.py 1.5 2003/11/05 19:40:04 PRouleau Exp $
|
|
16 |
#
|
|
17 |
# Update history:
|
|
18 |
#
|
|
19 |
# - File created: Saturday, June 7, 2003. by Pierre Rouleau
|
|
20 |
# - 10/06/03 rcs : RCS Revision 1.1 2003/06/10 10:06:12 PRouleau
|
|
21 |
# - 10/06/03 rcs : RCS Initial revision
|
|
22 |
# - 23/08/03 rcs : RCS Revision 1.2 2003/06/10 10:54:27 PRouleau
|
|
23 |
# - 23/08/03 P.R.: [code:fix] : The strings encoded in this file are encode in iso-8859-1 format. Added the encoding
|
|
24 |
# notification to Python to comply with Python's 2.3 PEP 263.
|
|
25 |
# - 23/08/03 P.R.: [feature:new] : Added the '-e' switch which is used to force the creation of the empty English .mo file.
|
|
26 |
# - 22/10/03 P.R.: [code] : incorporated utility functions in here to make script self sufficient.
|
|
27 |
# - 05/11/03 rcs : RCS Revision 1.4 2003/10/22 06:39:31 PRouleau
|
|
28 |
# - 05/11/03 P.R.: [code:fix] : included the unixpath() in this file.
|
|
29 |
# - 08/11/03 rcs : RCS Revision 1.5 2003/11/05 19:40:04 PRouleau
|
|
30 |
#
|
|
31 |
# RCS $Log: $
|
|
32 |
#
|
|
33 |
#
|
|
34 |
# -----------------------------------------------------------------------------
|
|
35 |
"""
|
|
36 |
mki18n allows you to internationalize your software. You can use it to
|
|
37 |
create the GNU .po files (Portable Object) and the compiled .mo files
|
|
38 |
(Machine Object).
|
|
39 |
|
|
40 |
mki18n module can be used from the command line or from within a script (see
|
|
41 |
the Usage at the end of this page).
|
|
42 |
|
|
43 |
Table of Contents
|
|
44 |
-----------------
|
|
45 |
|
|
46 |
makePO() -- Build the Portable Object file for the application --
|
|
47 |
catPO() -- Concatenate one or several PO files with the application domain files. --
|
|
48 |
makeMO() -- Compile the Portable Object files into the Machine Object stored in the right location. --
|
|
49 |
printUsage -- Displays how to use this script from the command line --
|
|
50 |
|
|
51 |
Scriptexecution -- Runs when invoked from the command line --
|
|
52 |
|
|
53 |
|
|
54 |
NOTE: this module uses GNU gettext utilities.
|
|
55 |
|
|
56 |
You can get the gettext tools from the following sites:
|
|
57 |
|
|
58 |
- `GNU FTP site for gettetx`_ where several versions (0.10.40, 0.11.2, 0.11.5 and 0.12.1) are available.
|
|
59 |
Note that you need to use `GNU libiconv`_ to use this. Get it from the `GNU
|
|
60 |
libiconv ftp site`_ and get version 1.9.1 or later. Get the Windows .ZIP
|
|
61 |
files and install the packages inside c:/gnu. All binaries will be stored
|
|
62 |
inside c:/gnu/bin. Just put c:/gnu/bin inside your PATH. You will need
|
|
63 |
the following files:
|
|
64 |
|
|
65 |
- `gettext-runtime-0.12.1.bin.woe32.zip`_
|
|
66 |
- `gettext-tools-0.12.1.bin.woe32.zip`_
|
|
67 |
- `libiconv-1.9.1.bin.woe32.zip`_
|
|
68 |
|
|
69 |
|
|
70 |
.. _GNU libiconv: http://www.gnu.org/software/libiconv/
|
|
71 |
.. _GNU libiconv ftp site: http://www.ibiblio.org/pub/gnu/libiconv/
|
|
72 |
.. _gettext-runtime-0.12.1.bin.woe32.zip: ftp://ftp.gnu.org/gnu/gettext/gettext-runtime-0.12.1.bin.woe32.zip
|
|
73 |
.. _gettext-tools-0.12.1.bin.woe32.zip: ftp://ftp.gnu.org/gnu/gettext/gettext-tools-0.12.1.bin.woe32.zip
|
|
74 |
.. _libiconv-1.9.1.bin.woe32.zip: http://www.ibiblio.org/pub/gnu/libiconv/libiconv-1.9.1.bin.woe32.zip
|
|
75 |
|
|
76 |
"""
|
|
77 |
# -----------------------------------------------------------------------------
|
|
78 |
# Module Import
|
|
79 |
# -------------
|
|
80 |
#
|
|
81 |
import os
|
|
82 |
import sys
|
|
83 |
import wx
|
|
84 |
# -----------------------------------------------------------------------------
|
|
85 |
# Global variables
|
|
86 |
# ----------------
|
|
87 |
#
|
|
88 |
|
|
89 |
__author__ = "Pierre Rouleau"
|
|
90 |
__version__= "$Revision: 1.5 $"
|
|
91 |
|
|
92 |
# -----------------------------------------------------------------------------
|
|
93 |
|
|
94 |
def getlanguageDict():
|
|
95 |
languageDict = {}
|
|
96 |
|
|
97 |
for lang in [x for x in dir(wx) if x.startswith("LANGUAGE")]:
|
|
98 |
i = wx.Locale(wx.LANGUAGE_DEFAULT).GetLanguageInfo(getattr(wx, lang))
|
|
99 |
if i:
|
|
100 |
languageDict[i.CanonicalName] = i.Description
|
|
101 |
|
|
102 |
return languageDict
|
|
103 |
|
|
104 |
# -----------------------------------------------------------------------------
|
|
105 |
# m a k e P O ( ) -- Build the Portable Object file for the application --
|
|
106 |
# ^^^^^^^^^^^^^^^
|
|
107 |
#
|
|
108 |
def makePO(applicationDirectoryPath, applicationDomain=None, verbose=0) :
|
|
109 |
"""Build the Portable Object Template file for the application.
|
|
110 |
|
|
111 |
makePO builds the .pot file for the application stored inside
|
|
112 |
a specified directory by running xgettext for all application source
|
|
113 |
files. It finds the name of all files by looking for a file called 'app.fil'.
|
|
114 |
If this file does not exists, makePo raises an IOError exception.
|
|
115 |
By default the application domain (the application
|
|
116 |
name) is the same as the directory name but it can be overridden by the
|
|
117 |
'applicationDomain' argument.
|
|
118 |
|
|
119 |
makePO always creates a new file called messages.pot. If it finds files
|
|
120 |
of the form app_xx.po where 'app' is the application name and 'xx' is one
|
|
121 |
of the ISO 639 two-letter language codes, makePO resynchronizes those
|
|
122 |
files with the latest extracted strings (now contained in messages.pot).
|
|
123 |
This process updates all line location number in the language-specific
|
|
124 |
.po files and may also create new entries for translation (or comment out
|
|
125 |
some). The .po file is not changed, instead a new file is created with
|
|
126 |
the .new extension appended to the name of the .po file.
|
|
127 |
|
|
128 |
By default the function does not display what it is doing. Set the
|
|
129 |
verbose argument to 1 to force it to print its commands.
|
|
130 |
"""
|
|
131 |
|
|
132 |
if applicationDomain is None:
|
|
133 |
applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
|
|
134 |
else:
|
|
135 |
applicationName = applicationDomain
|
|
136 |
currentDir = os.getcwd()
|
|
137 |
os.chdir(applicationDirectoryPath)
|
|
138 |
if not os.path.exists('app.fil'):
|
|
139 |
raise IOError(2,'No module file: app.fil')
|
|
140 |
|
|
141 |
# Steps:
|
|
142 |
# Use xgettext to parse all application modules
|
|
143 |
# The following switches are used:
|
|
144 |
#
|
|
145 |
# -s : sort output by string content (easier to use when we need to merge several .po files)
|
|
146 |
# --files-from=app.fil : The list of files is taken from the file: app.fil
|
|
147 |
# --output= : specifies the name of the output file (using a .pot extension)
|
|
148 |
cmd = 'xgettext -s --no-wrap --language=Python --files-from=app.fil --output=messages.pot'
|
|
149 |
if verbose: print cmd
|
|
150 |
os.system(cmd)
|
|
151 |
|
|
152 |
languageDict = getlanguageDict()
|
|
153 |
|
|
154 |
for langCode in languageDict.keys():
|
|
155 |
if langCode == 'en':
|
|
156 |
pass
|
|
157 |
else:
|
|
158 |
langPOfileName = "%s_%s.po" % (applicationName , langCode)
|
|
159 |
if os.path.exists(langPOfileName):
|
|
160 |
cmd = 'msgmerge -s --no-wrap "%s" messages.pot > "%s.new"' % (langPOfileName, langPOfileName)
|
|
161 |
if verbose: print cmd
|
|
162 |
os.system(cmd)
|
|
163 |
os.chdir(currentDir)
|
|
164 |
|
|
165 |
# -----------------------------------------------------------------------------
|
|
166 |
# c a t P O ( ) -- Concatenate one or several PO files with the application domain files. --
|
|
167 |
# ^^^^^^^^^^^^^
|
|
168 |
#
|
|
169 |
def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0) :
|
|
170 |
"""Concatenate one or several PO files with the application domain files.
|
|
171 |
"""
|
|
172 |
|
|
173 |
if applicationDomain is None:
|
|
174 |
applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
|
|
175 |
else:
|
|
176 |
applicationName = applicationDomain
|
|
177 |
currentDir = os.getcwd()
|
|
178 |
os.chdir(applicationDirectoryPath)
|
|
179 |
|
|
180 |
languageDict = getlanguageDict()
|
|
181 |
|
|
182 |
for langCode in languageDict.keys():
|
|
183 |
if langCode == 'en':
|
|
184 |
pass
|
|
185 |
else:
|
|
186 |
langPOfileName = "%s_%s.po" % (applicationName , langCode)
|
|
187 |
if os.path.exists(langPOfileName):
|
|
188 |
fileList = ''
|
|
189 |
for fileName in listOf_extraPo:
|
|
190 |
fileList += ("%s_%s.po " % (fileName,langCode))
|
|
191 |
cmd = "msgcat -s --no-wrap %s %s > %s.cat" % (langPOfileName, fileList, langPOfileName)
|
|
192 |
if verbose: print cmd
|
|
193 |
os.system(cmd)
|
|
194 |
if targetDir is None:
|
|
195 |
pass
|
|
196 |
else:
|
|
197 |
mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
|
|
198 |
cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po.cat" % (mo_targetDir,applicationName,applicationName,langCode)
|
|
199 |
if verbose: print cmd
|
|
200 |
os.system(cmd)
|
|
201 |
os.chdir(currentDir)
|
|
202 |
|
|
203 |
# -----------------------------------------------------------------------------
|
|
204 |
# m a k e M O ( ) -- Compile the Portable Object files into the Machine Object stored in the right location. --
|
|
205 |
# ^^^^^^^^^^^^^^^
|
|
206 |
#
|
|
207 |
def makeMO(applicationDirectoryPath,targetDir='./locale',applicationDomain=None, verbose=0, forceEnglish=0) :
|
|
208 |
"""Compile the Portable Object files into the Machine Object stored in the right location.
|
|
209 |
|
|
210 |
makeMO converts all translated language-specific PO files located inside
|
|
211 |
the application directory into the binary .MO files stored inside the
|
|
212 |
LC_MESSAGES sub-directory for the found locale files.
|
|
213 |
|
|
214 |
makeMO searches for all files that have a name of the form 'app_xx.po'
|
|
215 |
inside the application directory specified by the first argument. The
|
|
216 |
'app' is the application domain name (that can be specified by the
|
|
217 |
applicationDomain argument or is taken from the directory name). The 'xx'
|
|
218 |
corresponds to one of the ISO 639 two-letter language codes.
|
|
219 |
|
|
220 |
makeMo stores the resulting files inside a sub-directory of `targetDir`
|
|
221 |
called xx/LC_MESSAGES where 'xx' corresponds to the 2-letter language
|
|
222 |
code.
|
|
223 |
"""
|
|
224 |
if targetDir is None:
|
|
225 |
targetDir = './locale'
|
|
226 |
if verbose:
|
|
227 |
print "Target directory for .mo files is: %s" % targetDir
|
|
228 |
|
|
229 |
if applicationDomain is None:
|
|
230 |
applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
|
|
231 |
else:
|
|
232 |
applicationName = applicationDomain
|
|
233 |
currentDir = os.getcwd()
|
|
234 |
os.chdir(applicationDirectoryPath)
|
|
235 |
|
|
236 |
languageDict = getlanguageDict()
|
|
237 |
|
|
238 |
for langCode in languageDict.keys():
|
|
239 |
if (langCode == 'en') and (forceEnglish==0):
|
|
240 |
pass
|
|
241 |
else:
|
|
242 |
langPOfileName = "%s_%s.po" % (applicationName , langCode)
|
|
243 |
if os.path.exists(langPOfileName):
|
|
244 |
mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
|
|
245 |
if not os.path.exists(mo_targetDir):
|
|
246 |
mkdir(mo_targetDir)
|
|
247 |
cmd = 'msgfmt --output-file="%s/%s.mo" "%s_%s.po"' % (mo_targetDir,applicationName,applicationName,langCode)
|
|
248 |
if verbose: print cmd
|
|
249 |
os.system(cmd)
|
|
250 |
os.chdir(currentDir)
|
|
251 |
|
|
252 |
# -----------------------------------------------------------------------------
|
|
253 |
# p r i n t U s a g e -- Displays how to use this script from the command line --
|
|
254 |
# ^^^^^^^^^^^^^^^^^^^
|
|
255 |
#
|
|
256 |
def printUsage(errorMsg=None) :
|
|
257 |
"""Displays how to use this script from the command line."""
|
|
258 |
print """
|
|
259 |
##################################################################################
|
|
260 |
# mki18n : Make internationalization files. #
|
|
261 |
# Uses the GNU gettext system to create PO (Portable Object) files #
|
|
262 |
# from source code, coimpile PO into MO (Machine Object) files. #
|
|
263 |
# Supports C,C++,Python source files. #
|
|
264 |
# #
|
|
265 |
# Usage: mki18n {OPTION} [appDirPath] #
|
|
266 |
# #
|
|
267 |
# Options: #
|
|
268 |
# -e : When -m is used, forces English .mo file creation #
|
|
269 |
# -h : prints this help #
|
|
270 |
# -m : make MO from existing PO files #
|
|
271 |
# -p : make PO, update PO files: Creates a new messages.pot #
|
|
272 |
# file. Creates a dom_xx.po.new for every existing #
|
|
273 |
# language specific .po file. ('xx' stands for the ISO639 #
|
|
274 |
# two-letter language code and 'dom' stands for the #
|
|
275 |
# application domain name). mki18n requires that you #
|
|
276 |
# write a 'app.fil' file which contains the list of all #
|
|
277 |
# source code to parse. #
|
|
278 |
# -v : verbose (prints comments while running) #
|
|
279 |
# --domain=appName : specifies the application domain name. By default #
|
|
280 |
# the directory name is used. #
|
|
281 |
# --moTarget=dir : specifies the directory where .mo files are stored. #
|
|
282 |
# If not specified, the target is './locale' #
|
|
283 |
# #
|
|
284 |
# You must specify one of the -p or -m option to perform the work. You can #
|
|
285 |
# specify the path of the target application. If you leave it out mki18n #
|
|
286 |
# will use the current directory as the application main directory. #
|
|
287 |
# #
|
|
288 |
##################################################################################"""
|
|
289 |
if errorMsg:
|
|
290 |
print "\n ERROR: %s" % errorMsg
|
|
291 |
|
|
292 |
# -----------------------------------------------------------------------------
|
|
293 |
# f i l e B a s e O f ( ) -- Return base name of filename --
|
|
294 |
# ^^^^^^^^^^^^^^^^^^^^^^^
|
|
295 |
#
|
|
296 |
def fileBaseOf(filename,withPath=0) :
|
|
297 |
"""fileBaseOf(filename,withPath) ---> string
|
|
298 |
|
|
299 |
Return base name of filename. The returned string never includes the extension.
|
|
300 |
Use os.path.basename() to return the basename with the extension. The
|
|
301 |
second argument is optional. If specified and if set to 'true' (non zero)
|
|
302 |
the string returned contains the full path of the file name. Otherwise the
|
|
303 |
path is excluded.
|
|
304 |
|
|
305 |
[Example]
|
|
306 |
>>> fn = 'd:/dev/telepath/tvapp/code/test.html'
|
|
307 |
>>> fileBaseOf(fn)
|
|
308 |
'test'
|
|
309 |
>>> fileBaseOf(fn)
|
|
310 |
'test'
|
|
311 |
>>> fileBaseOf(fn,1)
|
|
312 |
'd:/dev/telepath/tvapp/code/test'
|
|
313 |
>>> fileBaseOf(fn,0)
|
|
314 |
'test'
|
|
315 |
>>> fn = 'abcdef'
|
|
316 |
>>> fileBaseOf(fn)
|
|
317 |
'abcdef'
|
|
318 |
>>> fileBaseOf(fn,1)
|
|
319 |
'abcdef'
|
|
320 |
>>> fn = "abcdef."
|
|
321 |
>>> fileBaseOf(fn)
|
|
322 |
'abcdef'
|
|
323 |
>>> fileBaseOf(fn,1)
|
|
324 |
'abcdef'
|
|
325 |
"""
|
|
326 |
pos = filename.rfind('.')
|
|
327 |
if pos > 0:
|
|
328 |
filename = filename[:pos]
|
|
329 |
if withPath:
|
|
330 |
return filename
|
|
331 |
else:
|
|
332 |
return os.path.basename(filename)
|
|
333 |
# -----------------------------------------------------------------------------
|
|
334 |
# m k d i r ( ) -- Create a directory (and possibly the entire tree) --
|
|
335 |
# ^^^^^^^^^^^^^
|
|
336 |
#
|
|
337 |
def mkdir(directory) :
|
|
338 |
"""Create a directory (and possibly the entire tree).
|
|
339 |
|
|
340 |
The os.mkdir() will fail to create a directory if one of the
|
|
341 |
directory in the specified path does not exist. mkdir()
|
|
342 |
solves this problem. It creates every intermediate directory
|
|
343 |
required to create the final path. Under Unix, the function
|
|
344 |
only supports forward slash separator, but under Windows and MacOS
|
|
345 |
the function supports the forward slash and the OS separator (backslash
|
|
346 |
under windows).
|
|
347 |
"""
|
|
348 |
|
|
349 |
# translate the path separators
|
|
350 |
directory = unixpath(directory)
|
|
351 |
# build a list of all directory elements
|
|
352 |
aList = filter(lambda x: len(x)>0, directory.split('/'))
|
|
353 |
theLen = len(aList)
|
|
354 |
# if the first element is a Windows-style disk drive
|
|
355 |
# concatenate it with the first directory
|
|
356 |
if aList[0].endswith(':'):
|
|
357 |
if theLen > 1:
|
|
358 |
aList[1] = aList[0] + '/' + aList[1]
|
|
359 |
del aList[0]
|
|
360 |
theLen -= 1
|
|
361 |
# if the original directory starts at root,
|
|
362 |
# make sure the first element of the list
|
|
363 |
# starts at root too
|
|
364 |
if directory[0] == '/':
|
|
365 |
aList[0] = '/' + aList[0]
|
|
366 |
# Now iterate through the list, check if the
|
|
367 |
# directory exists and if not create it
|
|
368 |
theDir = ''
|
|
369 |
for i in range(theLen):
|
|
370 |
theDir += aList[i]
|
|
371 |
if not os.path.exists(theDir):
|
|
372 |
os.mkdir(theDir)
|
|
373 |
theDir += '/'
|
|
374 |
|
|
375 |
# -----------------------------------------------------------------------------
|
|
376 |
# u n i x p a t h ( ) -- Return a path name that contains Unix separator. --
|
|
377 |
# ^^^^^^^^^^^^^^^^^^^
|
|
378 |
#
|
|
379 |
def unixpath(thePath) :
|
|
380 |
r"""Return a path name that contains Unix separator.
|
|
381 |
|
|
382 |
[Example]
|
|
383 |
>>> unixpath(r"d:\test")
|
|
384 |
'd:/test'
|
|
385 |
>>> unixpath("d:/test/file.txt")
|
|
386 |
'd:/test/file.txt'
|
|
387 |
>>>
|
|
388 |
"""
|
|
389 |
thePath = os.path.normpath(thePath)
|
|
390 |
if os.sep == '/':
|
|
391 |
return thePath
|
|
392 |
else:
|
|
393 |
return thePath.replace(os.sep,'/')
|
|
394 |
|
|
395 |
# -----------------------------------------------------------------------------
|
|
396 |
|
|
397 |
# S c r i p t e x e c u t i o n -- Runs when invoked from the command line --
|
|
398 |
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
399 |
#
|
|
400 |
if __name__ == "__main__":
|
|
401 |
import getopt # command line parsing
|
|
402 |
argc = len(sys.argv)
|
|
403 |
if argc == 1:
|
|
404 |
printUsage('Missing argument: specify at least one of -m or -p (or both).')
|
|
405 |
sys.exit(1)
|
|
406 |
# If there is some arguments, parse the command line
|
|
407 |
validOptions = "ehmpv"
|
|
408 |
validLongOptions = ['domain=', 'moTarget=']
|
|
409 |
option = {}
|
|
410 |
option['forceEnglish'] = 0
|
|
411 |
option['mo'] = 0
|
|
412 |
option['po'] = 0
|
|
413 |
option['verbose'] = 0
|
|
414 |
option['domain'] = None
|
|
415 |
option['moTarget'] = None
|
|
416 |
try:
|
|
417 |
optionList,pargs = getopt.getopt(sys.argv[1:],validOptions,validLongOptions)
|
|
418 |
except getopt.GetoptError, e:
|
|
419 |
printUsage(e[0])
|
|
420 |
sys.exit(1)
|
|
421 |
for (opt,val) in optionList:
|
|
422 |
if (opt == '-h'):
|
|
423 |
printUsage()
|
|
424 |
sys.exit(0)
|
|
425 |
elif (opt == '-e'): option['forceEnglish'] = 1
|
|
426 |
elif (opt == '-m'): option['mo'] = 1
|
|
427 |
elif (opt == '-p'): option['po'] = 1
|
|
428 |
elif (opt == '-v'): option['verbose'] = 1
|
|
429 |
elif (opt == '--domain'): option['domain'] = val
|
|
430 |
elif (opt == '--moTarget'): option['moTarget'] = val
|
|
431 |
if len(pargs) == 0:
|
|
432 |
appDirPath = os.getcwd()
|
|
433 |
if option['verbose']:
|
|
434 |
print "No project directory given. Using current one: %s" % appDirPath
|
|
435 |
elif len(pargs) == 1:
|
|
436 |
appDirPath = pargs[0]
|
|
437 |
else:
|
|
438 |
printUsage('Too many arguments (%u). Use double quotes if you have space in directory name' % len(pargs))
|
|
439 |
sys.exit(1)
|
|
440 |
if option['domain'] is None:
|
|
441 |
# If no domain specified, use the name of the target directory
|
|
442 |
option['domain'] = fileBaseOf(appDirPath)
|
|
443 |
if option['verbose']:
|
|
444 |
print "Application domain used is: '%s'" % option['domain']
|
|
445 |
if option['po']:
|
|
446 |
try:
|
|
447 |
makePO(appDirPath,option['domain'],option['verbose'])
|
|
448 |
except IOError, e:
|
|
449 |
printUsage(e[1] + '\n You must write a file app.fil that contains the list of all files to parse.')
|
|
450 |
if option['mo']:
|
|
451 |
makeMO(appDirPath,option['moTarget'],option['domain'],option['verbose'],option['forceEnglish'])
|
|
452 |
sys.exit(1)
|
|
453 |
|
|
454 |
|
|
455 |
# -----------------------------------------------------------------------------
|