Attachment 'mki18n.py'
Download 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 # -----------------------------------------------------------------------------
84 # Global variables
85 # ----------------
86 #
87
88 __author__ = "Pierre Rouleau"
89 __version__= "$Revision: 1.5 $"
90
91 # -----------------------------------------------------------------------------
92 # Public variables
93 # ----------------
94 #
95 # iso639 : natural
96 # 2-letter : language
97 # code : name
98 iso639_languageDict = { 'aa' : 'Afar. ',
99 'ab' : 'Abkhazian. ',
100 'ae' : 'Avestan. ',
101 'af' : 'Afrikaans. ',
102 'am' : 'Amharic. ',
103 'ar' : 'Arabic. ',
104 'as' : 'Assamese. ',
105 'ay' : 'Aymara. ',
106 'az' : 'Azerbaijani. ',
107 'ba' : 'Bashkir. ',
108 'be' : 'Byelorussian; Belarusian. ',
109 'bg' : 'Bulgarian. ',
110 'bh' : 'Bihari. ',
111 'bi' : 'Bislama. ',
112 'bn' : 'Bengali; Bangla. ',
113 'bo' : 'Tibetan. ',
114 'br' : 'Breton. ',
115 'bs' : 'Bosnian. ',
116 'ca' : 'Catalan. ',
117 'ce' : 'Chechen. ',
118 'ch' : 'Chamorro. ',
119 'co' : 'Corsican. ',
120 'cs' : 'Czech. ',
121 'cu' : 'Church Slavic. ',
122 'cv' : 'Chuvash. ',
123 'cy' : 'Welsh. ',
124 'da' : 'Danish. ',
125 'de' : 'German. ',
126 'dz' : 'Dzongkha; Bhutani. ',
127 'el' : 'Greek. ',
128 'en' : 'English. ',
129 'eo' : 'Esperanto. ',
130 'es' : 'Spanish. ',
131 'et' : 'Estonian. ',
132 'eu' : 'Basque. ',
133 'fa' : 'Persian. ',
134 'fi' : 'Finnish. ',
135 'fj' : 'Fijian; Fiji. ',
136 'fo' : 'Faroese. ',
137 'fr' : 'French. ',
138 'fy' : 'Frisian. ',
139 'ga' : 'Irish. ',
140 'gd' : 'Scots; Gaelic. ',
141 'gl' : 'Gallegan; Galician. ',
142 'gn' : 'Guarani. ',
143 'gu' : 'Gujarati. ',
144 'gv' : 'Manx. ',
145 'ha' : 'Hausa (?). ',
146 'he' : 'Hebrew (formerly iw). ',
147 'hi' : 'Hindi. ',
148 'ho' : 'Hiri Motu. ',
149 'hr' : 'Croatian. ',
150 'hu' : 'Hungarian. ',
151 'hy' : 'Armenian. ',
152 'hz' : 'Herero. ',
153 'ia' : 'Interlingua. ',
154 'id' : 'Indonesian (formerly in). ',
155 'ie' : 'Interlingue. ',
156 'ik' : 'Inupiak. ',
157 'io' : 'Ido. ',
158 'is' : 'Icelandic. ',
159 'it' : 'Italian. ',
160 'iu' : 'Inuktitut. ',
161 'ja' : 'Japanese. ',
162 'jv' : 'Javanese. ',
163 'ka' : 'Georgian. ',
164 'ki' : 'Kikuyu. ',
165 'kj' : 'Kuanyama. ',
166 'kk' : 'Kazakh. ',
167 'kl' : 'Kalaallisut; Greenlandic. ',
168 'km' : 'Khmer; Cambodian. ',
169 'kn' : 'Kannada. ',
170 'ko' : 'Korean. ',
171 'ks' : 'Kashmiri. ',
172 'ku' : 'Kurdish. ',
173 'kv' : 'Komi. ',
174 'kw' : 'Cornish. ',
175 'ky' : 'Kirghiz. ',
176 'la' : 'Latin. ',
177 'lb' : 'Letzeburgesch. ',
178 'ln' : 'Lingala. ',
179 'lo' : 'Lao; Laotian. ',
180 'lt' : 'Lithuanian. ',
181 'lv' : 'Latvian; Lettish. ',
182 'mg' : 'Malagasy. ',
183 'mh' : 'Marshall. ',
184 'mi' : 'Maori. ',
185 'mk' : 'Macedonian. ',
186 'ml' : 'Malayalam. ',
187 'mn' : 'Mongolian. ',
188 'mo' : 'Moldavian. ',
189 'mr' : 'Marathi. ',
190 'ms' : 'Malay. ',
191 'mt' : 'Maltese. ',
192 'my' : 'Burmese. ',
193 'na' : 'Nauru. ',
194 'nb' : 'Norwegian Bokmål. ',
195 'nd' : 'Ndebele, North. ',
196 'ne' : 'Nepali. ',
197 'ng' : 'Ndonga. ',
198 'nl' : 'Dutch. ',
199 'nn' : 'Norwegian Nynorsk. ',
200 'no' : 'Norwegian. ',
201 'nr' : 'Ndebele, South. ',
202 'nv' : 'Navajo. ',
203 'ny' : 'Chichewa; Nyanja. ',
204 'oc' : 'Occitan; Provençal. ',
205 'om' : '(Afan) Oromo. ',
206 'or' : 'Oriya. ',
207 'os' : 'Ossetian; Ossetic. ',
208 'pa' : 'Panjabi; Punjabi. ',
209 'pi' : 'Pali. ',
210 'pl' : 'Polish. ',
211 'ps' : 'Pashto, Pushto. ',
212 'pt' : 'Portuguese. ',
213 'qu' : 'Quechua. ',
214 'rm' : 'Rhaeto-Romance. ',
215 'rn' : 'Rundi; Kirundi. ',
216 'ro' : 'Romanian. ',
217 'ru' : 'Russian. ',
218 'rw' : 'Kinyarwanda. ',
219 'sa' : 'Sanskrit. ',
220 'sc' : 'Sardinian. ',
221 'sd' : 'Sindhi. ',
222 'se' : 'Northern Sami. ',
223 'sg' : 'Sango; Sangro. ',
224 'si' : 'Sinhalese. ',
225 'sk' : 'Slovak. ',
226 'sl' : 'Slovenian. ',
227 'sm' : 'Samoan. ',
228 'sn' : 'Shona. ',
229 'so' : 'Somali. ',
230 'sq' : 'Albanian. ',
231 'sr' : 'Serbian. ',
232 'ss' : 'Swati; Siswati. ',
233 'st' : 'Sesotho; Sotho, Southern. ',
234 'su' : 'Sundanese. ',
235 'sv' : 'Swedish. ',
236 'sw' : 'Swahili. ',
237 'ta' : 'Tamil. ',
238 'te' : 'Telugu. ',
239 'tg' : 'Tajik. ',
240 'th' : 'Thai. ',
241 'ti' : 'Tigrinya. ',
242 'tk' : 'Turkmen. ',
243 'tl' : 'Tagalog. ',
244 'tn' : 'Tswana; Setswana. ',
245 'to' : 'Tonga (?). ',
246 'tr' : 'Turkish. ',
247 'ts' : 'Tsonga. ',
248 'tt' : 'Tatar. ',
249 'tw' : 'Twi. ',
250 'ty' : 'Tahitian. ',
251 'ug' : 'Uighur. ',
252 'uk' : 'Ukrainian. ',
253 'ur' : 'Urdu. ',
254 'uz' : 'Uzbek. ',
255 'vi' : 'Vietnamese. ',
256 'vo' : 'Volapük; Volapuk. ',
257 'wa' : 'Walloon. ',
258 'wo' : 'Wolof. ',
259 'xh' : 'Xhosa. ',
260 'yi' : 'Yiddish (formerly ji). ',
261 'yo' : 'Yoruba. ',
262 'za' : 'Zhuang. ',
263 'zh' : 'Chinese. ',
264 'zu' : 'Zulu.'
265 }
266
267
268 # -----------------------------------------------------------------------------
269 # m a k e P O ( ) -- Build the Portable Object file for the application --
270 # ^^^^^^^^^^^^^^^
271 #
272 def makePO(applicationDirectoryPath, applicationDomain=None, verbose=0) :
273 """Build the Portable Object Template file for the application.
274
275 makePO builds the .pot file for the application stored inside
276 a specified directory by running xgettext for all application source
277 files. It finds the name of all files by looking for a file called 'app.fil'.
278 If this file does not exists, makePo raises an IOError exception.
279 By default the application domain (the application
280 name) is the same as the directory name but it can be overridden by the
281 'applicationDomain' argument.
282
283 makePO always creates a new file called messages.pot. If it finds files
284 of the form app_xx.po where 'app' is the application name and 'xx' is one
285 of the ISO 639 two-letter language codes, makePO resynchronizes those
286 files with the latest extracted strings (now contained in messages.pot).
287 This process updates all line location number in the language-specific
288 .po files and may also create new entries for translation (or comment out
289 some). The .po file is not changed, instead a new file is created with
290 the .new extension appended to the name of the .po file.
291
292 By default the function does not display what it is doing. Set the
293 verbose argument to 1 to force it to print its commands.
294 """
295
296 if applicationDomain is None:
297 applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
298 else:
299 applicationName = applicationDomain
300 currentDir = os.getcwd()
301 os.chdir(applicationDirectoryPath)
302 if not os.path.exists('app.fil'):
303 raise IOError(2,'No module file: app.fil')
304
305 # Steps:
306 # Use xgettext to parse all application modules
307 # The following switches are used:
308 #
309 # -s : sort output by string content (easier to use when we need to merge several .po files)
310 # --files-from=app.fil : The list of files is taken from the file: app.fil
311 # --output= : specifies the name of the output file (using a .pot extension)
312 cmd = 'xgettext -s --no-wrap --files-from=app.fil --output=messages.pot'
313 if verbose: print cmd
314 os.system(cmd)
315
316 for langCode in iso639_languageDict.keys():
317 if langCode == 'en':
318 pass
319 else:
320 langPOfileName = "%s_%s.po" % (applicationName , langCode)
321 if os.path.exists(langPOfileName):
322 cmd = "msgmerge -s --no-wrap %s messages.pot > %s.new" % (langPOfileName, langPOfileName)
323 if verbose: print cmd
324 os.system(cmd)
325 os.chdir(currentDir)
326
327 # -----------------------------------------------------------------------------
328 # c a t P O ( ) -- Concatenate one or several PO files with the application domain files. --
329 # ^^^^^^^^^^^^^
330 #
331 def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0) :
332 """Concatenate one or several PO files with the application domain files.
333 """
334
335 if applicationDomain is None:
336 applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
337 else:
338 applicationName = applicationDomain
339 currentDir = os.getcwd()
340 os.chdir(applicationDirectoryPath)
341
342 for langCode in iso639_languageDict.keys():
343 if langCode == 'en':
344 pass
345 else:
346 langPOfileName = "%s_%s.po" % (applicationName , langCode)
347 if os.path.exists(langPOfileName):
348 fileList = ''
349 for fileName in listOf_extraPo:
350 fileList += ("%s_%s.po " % (fileName,langCode))
351 cmd = "msgcat -s --no-wrap %s %s > %s.cat" % (langPOfileName, fileList, langPOfileName)
352 if verbose: print cmd
353 os.system(cmd)
354 if targetDir is None:
355 pass
356 else:
357 mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
358 cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po.cat" % (mo_targetDir,applicationName,applicationName,langCode)
359 if verbose: print cmd
360 os.system(cmd)
361 os.chdir(currentDir)
362
363 # -----------------------------------------------------------------------------
364 # m a k e M O ( ) -- Compile the Portable Object files into the Machine Object stored in the right location. --
365 # ^^^^^^^^^^^^^^^
366 #
367 def makeMO(applicationDirectoryPath,targetDir='./locale',applicationDomain=None, verbose=0, forceEnglish=0) :
368 """Compile the Portable Object files into the Machine Object stored in the right location.
369
370 makeMO converts all translated language-specific PO files located inside
371 the application directory into the binary .MO files stored inside the
372 LC_MESSAGES sub-directory for the found locale files.
373
374 makeMO searches for all files that have a name of the form 'app_xx.po'
375 inside the application directory specified by the first argument. The
376 'app' is the application domain name (that can be specified by the
377 applicationDomain argument or is taken from the directory name). The 'xx'
378 corresponds to one of the ISO 639 two-letter language codes.
379
380 makeMo stores the resulting files inside a sub-directory of `targetDir`
381 called xx/LC_MESSAGES where 'xx' corresponds to the 2-letter language
382 code.
383 """
384 if targetDir is None:
385 targetDir = './locale'
386 if verbose:
387 print "Target directory for .mo files is: %s" % targetDir
388
389 if applicationDomain is None:
390 applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
391 else:
392 applicationName = applicationDomain
393 currentDir = os.getcwd()
394 os.chdir(applicationDirectoryPath)
395
396 for langCode in iso639_languageDict.keys():
397 if (langCode == 'en') and (forceEnglish==0):
398 pass
399 else:
400 langPOfileName = "%s_%s.po" % (applicationName , langCode)
401 if os.path.exists(langPOfileName):
402 mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
403 if not os.path.exists(mo_targetDir):
404 mkdir(mo_targetDir)
405 cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po" % (mo_targetDir,applicationName,applicationName,langCode)
406 if verbose: print cmd
407 os.system(cmd)
408 os.chdir(currentDir)
409
410 # -----------------------------------------------------------------------------
411 # p r i n t U s a g e -- Displays how to use this script from the command line --
412 # ^^^^^^^^^^^^^^^^^^^
413 #
414 def printUsage(errorMsg=None) :
415 """Displays how to use this script from the command line."""
416 print """
417 ##################################################################################
418 # mki18n : Make internationalization files. #
419 # Uses the GNU gettext system to create PO (Portable Object) files #
420 # from source code, coimpile PO into MO (Machine Object) files. #
421 # Supports C,C++,Python source files. #
422 # #
423 # Usage: mki18n {OPTION} [appDirPath] #
424 # #
425 # Options: #
426 # -e : When -m is used, forces English .mo file creation #
427 # -h : prints this help #
428 # -m : make MO from existing PO files #
429 # -p : make PO, update PO files: Creates a new messages.pot #
430 # file. Creates a dom_xx.po.new for every existing #
431 # language specific .po file. ('xx' stands for the ISO639 #
432 # two-letter language code and 'dom' stands for the #
433 # application domain name). mki18n requires that you #
434 # write a 'app.fil' file which contains the list of all #
435 # source code to parse. #
436 # -v : verbose (prints comments while running) #
437 # --domain=appName : specifies the application domain name. By default #
438 # the directory name is used. #
439 # --moTarget=dir : specifies the directory where .mo files are stored. #
440 # If not specified, the target is './locale' #
441 # #
442 # You must specify one of the -p or -m option to perform the work. You can #
443 # specify the path of the target application. If you leave it out mki18n #
444 # will use the current directory as the application main directory. #
445 # #
446 ##################################################################################"""
447 if errorMsg:
448 print "\n ERROR: %s" % errorMsg
449
450 # -----------------------------------------------------------------------------
451 # f i l e B a s e O f ( ) -- Return base name of filename --
452 # ^^^^^^^^^^^^^^^^^^^^^^^
453 #
454 def fileBaseOf(filename,withPath=0) :
455 """fileBaseOf(filename,withPath) ---> string
456
457 Return base name of filename. The returned string never includes the extension.
458 Use os.path.basename() to return the basename with the extension. The
459 second argument is optional. If specified and if set to 'true' (non zero)
460 the string returned contains the full path of the file name. Otherwise the
461 path is excluded.
462
463 [Example]
464 >>> fn = 'd:/dev/telepath/tvapp/code/test.html'
465 >>> fileBaseOf(fn)
466 'test'
467 >>> fileBaseOf(fn)
468 'test'
469 >>> fileBaseOf(fn,1)
470 'd:/dev/telepath/tvapp/code/test'
471 >>> fileBaseOf(fn,0)
472 'test'
473 >>> fn = 'abcdef'
474 >>> fileBaseOf(fn)
475 'abcdef'
476 >>> fileBaseOf(fn,1)
477 'abcdef'
478 >>> fn = "abcdef."
479 >>> fileBaseOf(fn)
480 'abcdef'
481 >>> fileBaseOf(fn,1)
482 'abcdef'
483 """
484 pos = filename.rfind('.')
485 if pos > 0:
486 filename = filename[:pos]
487 if withPath:
488 return filename
489 else:
490 return os.path.basename(filename)
491 # -----------------------------------------------------------------------------
492 # m k d i r ( ) -- Create a directory (and possibly the entire tree) --
493 # ^^^^^^^^^^^^^
494 #
495 def mkdir(directory) :
496 """Create a directory (and possibly the entire tree).
497
498 The os.mkdir() will fail to create a directory if one of the
499 directory in the specified path does not exist. mkdir()
500 solves this problem. It creates every intermediate directory
501 required to create the final path. Under Unix, the function
502 only supports forward slash separator, but under Windows and MacOS
503 the function supports the forward slash and the OS separator (backslash
504 under windows).
505 """
506
507 # translate the path separators
508 directory = unixpath(directory)
509 # build a list of all directory elements
510 aList = filter(lambda x: len(x)>0, directory.split('/'))
511 theLen = len(aList)
512 # if the first element is a Windows-style disk drive
513 # concatenate it with the first directory
514 if aList[0].endswith(':'):
515 if theLen > 1:
516 aList[1] = aList[0] + '/' + aList[1]
517 del aList[0]
518 theLen -= 1
519 # if the original directory starts at root,
520 # make sure the first element of the list
521 # starts at root too
522 if directory[0] == '/':
523 aList[0] = '/' + aList[0]
524 # Now iterate through the list, check if the
525 # directory exists and if not create it
526 theDir = ''
527 for i in range(theLen):
528 theDir += aList[i]
529 if not os.path.exists(theDir):
530 os.mkdir(theDir)
531 theDir += '/'
532
533 # -----------------------------------------------------------------------------
534 # u n i x p a t h ( ) -- Return a path name that contains Unix separator. --
535 # ^^^^^^^^^^^^^^^^^^^
536 #
537 def unixpath(thePath) :
538 r"""Return a path name that contains Unix separator.
539
540 [Example]
541 >>> unixpath(r"d:\test")
542 'd:/test'
543 >>> unixpath("d:/test/file.txt")
544 'd:/test/file.txt'
545 >>>
546 """
547 thePath = os.path.normpath(thePath)
548 if os.sep == '/':
549 return thePath
550 else:
551 return thePath.replace(os.sep,'/')
552
553 # -----------------------------------------------------------------------------
554
555 # S c r i p t e x e c u t i o n -- Runs when invoked from the command line --
556 # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
557 #
558 if __name__ == "__main__":
559 import getopt # command line parsing
560 argc = len(sys.argv)
561 if argc == 1:
562 printUsage('Missing argument: specify at least one of -m or -p (or both).')
563 sys.exit(1)
564 # If there is some arguments, parse the command line
565 validOptions = "ehmpv"
566 validLongOptions = ['domain=', 'moTarget=']
567 option = {}
568 option['forceEnglish'] = 0
569 option['mo'] = 0
570 option['po'] = 0
571 option['verbose'] = 0
572 option['domain'] = None
573 option['moTarget'] = None
574 try:
575 optionList,pargs = getopt.getopt(sys.argv[1:],validOptions,validLongOptions)
576 except getopt.GetoptError, e:
577 printUsage(e[0])
578 sys.exit(1)
579 for (opt,val) in optionList:
580 if (opt == '-h'):
581 printUsage()
582 sys.exit(0)
583 elif (opt == '-e'): option['forceEnglish'] = 1
584 elif (opt == '-m'): option['mo'] = 1
585 elif (opt == '-p'): option['po'] = 1
586 elif (opt == '-v'): option['verbose'] = 1
587 elif (opt == '--domain'): option['domain'] = val
588 elif (opt == '--moTarget'): option['moTarget'] = val
589 if len(pargs) == 0:
590 appDirPath = os.getcwd()
591 if option['verbose']:
592 print "No project directory given. Using current one: %s" % appDirPath
593 elif len(pargs) == 1:
594 appDirPath = pargs[0]
595 else:
596 printUsage('Too many arguments (%u). Use double quotes if you have space in directory name' % len(pargs))
597 sys.exit(1)
598 if option['domain'] is None:
599 # If no domain specified, use the name of the target directory
600 option['domain'] = fileBaseOf(appDirPath)
601 if option['verbose']:
602 print "Application domain used is: '%s'" % option['domain']
603 if option['po']:
604 try:
605 makePO(appDirPath,option['domain'],option['verbose'])
606 except IOError, e:
607 printUsage(e[1] + '\n You must write a file app.fil that contains the list of all files to parse.')
608 if option['mo']:
609 makeMO(appDirPath,option['moTarget'],option['domain'],option['verbose'],option['forceEnglish'])
610 sys.exit(1)
611
612
613 # -----------------------------------------------------------------------------
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.