andrej@1731: #! /usr/bin/env python
andrej@1731: # -*- coding: iso-8859-1 -*-
andrej@1731: #
andrej@1731: #   PYTHON MODULE:     MKI18N.PY
andrej@1731: #                      =========
andrej@1731: #
andrej@1731: #   Abstract:         Make Internationalization (i18n) files for an application.
andrej@1731: #
andrej@1731: #   Copyright Pierre Rouleau. 2003. Released to public domain.
andrej@1731: #
andrej@1731: #   Last update: Saturday, November 8, 2003. @ 15:55:18.
andrej@1731: #
andrej@1731: #   File: ROUP2003N01::C:/dev/python/mki18n.py
andrej@1731: #
andrej@1731: #   RCS $Header: //software/official/MKS/MKS_SI/TV_NT/dev/Python/rcs/mki18n.py 1.5 2003/11/05 19:40:04 PRouleau Exp $
andrej@1731: #
andrej@1731: #   Update history:
andrej@1731: #
andrej@1731: #   - File created: Saturday, June 7, 2003. by Pierre Rouleau
andrej@1731: #   - 10/06/03 rcs : RCS Revision 1.1  2003/06/10 10:06:12  PRouleau
andrej@1731: #   - 10/06/03 rcs : RCS Initial revision
andrej@1731: #   - 23/08/03 rcs : RCS Revision 1.2  2003/06/10 10:54:27  PRouleau
andrej@1731: #   - 23/08/03 P.R.: [code:fix] : The strings encoded in this file are encode in iso-8859-1 format.  Added the encoding
andrej@1731: #                    notification to Python to comply with Python's 2.3 PEP 263.
andrej@1731: #   - 23/08/03 P.R.: [feature:new] : Added the '-e' switch which is used to force the creation of the empty English .mo file.
andrej@1731: #   - 22/10/03 P.R.: [code] : incorporated utility functions in here to make script self sufficient.
andrej@1731: #   - 05/11/03 rcs : RCS Revision 1.4  2003/10/22 06:39:31  PRouleau
andrej@1731: #   - 05/11/03 P.R.: [code:fix] : included the unixpath() in this file.
andrej@1731: #   - 08/11/03 rcs : RCS Revision 1.5  2003/11/05 19:40:04  PRouleau
andrej@1731: #
andrej@1731: #   RCS $Log: $
andrej@1731: #
andrej@1731: #
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: """
andrej@1731: mki18n allows you to internationalize your software.  You can use it to
andrej@1731: create the GNU .po files (Portable Object) and the compiled .mo files
andrej@1731: (Machine Object).
andrej@1731: 
andrej@1731: mki18n module can be used from the command line or from within a script (see
andrej@1731: the Usage at the end of this page).
andrej@1731: 
andrej@1731:     Table of Contents
andrej@1731:     -----------------
andrej@1731: 
andrej@1731:     makePO()             -- Build the Portable Object file for the application --
andrej@1731:     catPO()              -- Concatenate one or several PO files with the application domain files. --
andrej@1731:     makeMO()             -- Compile the Portable Object files into the Machine Object stored in the right location. --
andrej@1731:     printUsage           -- Displays how to use this script from the command line --
andrej@1731: 
andrej@1731:     Scriptexecution      -- Runs when invoked from the command line --
andrej@1731: 
andrej@1731: 
andrej@1731: NOTE:  this module uses GNU gettext utilities.
andrej@1731: 
andrej@1731: You can get the gettext tools from the following sites:
andrej@1731: 
andrej@1731:    - `GNU FTP site for gettetx`_ where several versions (0.10.40, 0.11.2, 0.11.5 and 0.12.1) are available.
andrej@1731:      Note  that you need to use `GNU libiconv`_ to use this. Get it from the `GNU
andrej@1731:      libiconv  ftp site`_ and get version 1.9.1 or later. Get the Windows .ZIP
andrej@1731:      files and install the packages inside c:/gnu. All binaries will be stored
andrej@1731:      inside  c:/gnu/bin.  Just  put c:/gnu/bin inside your PATH. You will need
andrej@1731:      the following files:
andrej@1731: 
andrej@1731:       - `gettext-runtime-0.12.1.bin.woe32.zip`_
andrej@1731:       - `gettext-tools-0.12.1.bin.woe32.zip`_
andrej@1731:       - `libiconv-1.9.1.bin.woe32.zip`_
andrej@1731: 
andrej@1731: 
andrej@1731: .. _GNU libiconv:                            http://www.gnu.org/software/libiconv/
andrej@1731: .. _GNU libiconv ftp site:                   http://www.ibiblio.org/pub/gnu/libiconv/
andrej@1731: .. _gettext-runtime-0.12.1.bin.woe32.zip:    ftp://ftp.gnu.org/gnu/gettext/gettext-runtime-0.12.1.bin.woe32.zip
andrej@1731: .. _gettext-tools-0.12.1.bin.woe32.zip:      ftp://ftp.gnu.org/gnu/gettext/gettext-tools-0.12.1.bin.woe32.zip
andrej@1731: .. _libiconv-1.9.1.bin.woe32.zip:            http://www.ibiblio.org/pub/gnu/libiconv/libiconv-1.9.1.bin.woe32.zip
andrej@1731: 
andrej@1731: """
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: # Module Import
andrej@1731: # -------------
andrej@1731: #
andrej@1881: 
andrej@1881: from __future__ import absolute_import
andrej@1826: from __future__ import print_function
andrej@1731: import os
andrej@1731: import sys
andrej@1832: import re
andrej@2452: from builtins import str as text
andrej@1731: import wx
andrej@1731: 
andrej@2452: 
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: # Global variables
andrej@1731: # ----------------
andrej@1731: #
andrej@1731: 
andrej@1758: __author__ = "Pierre Rouleau"
andrej@1742: __version__ = "$Revision: 1.5 $"
andrej@1731: 
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: 
andrej@1736: 
andrej@2350: def getSupportedLanguageDict(appname):
andrej@2350:     """
andrej@2350:     Returns dictionary with languages already supported
andrej@2350:     by given application
andrej@2350: 
andrej@2350:     param: appname:
andrej@2350:         name of application
andrej@2350:     """
andrej@2350:     languageDict = {}
andrej@2350:     ext = '.po'
andrej@2350:     files = [x for x in os.listdir('.')
andrej@2350:              if x.startswith(appname) and x.endswith(ext)]
andrej@2350: 
andrej@2350:     langs = [x.split(appname + '_')[1].split(ext)[0] for x in files]
andrej@2350:     for lang in langs:
andrej@2350:         languageDict[lang] = lang
andrej@2350: 
andrej@2350:     return languageDict
andrej@2350: 
andrej@2350: 
andrej@1731: def getlanguageDict():
andrej@1731:     languageDict = {}
andrej@2350:     getSupportedLanguageDict('Beremiz')
andrej@1731:     if wx.VERSION >= (3, 0, 0):
andrej@1847:         _app = wx.App()
andrej@1847:     else:
andrej@1847:         _app = wx.PySimpleApp()
andrej@1731: 
andrej@1731:     for lang in [x for x in dir(wx) if x.startswith("LANGUAGE")]:
andrej@1731:         i = wx.Locale(wx.LANGUAGE_DEFAULT).GetLanguageInfo(getattr(wx, lang))
andrej@1731:         if i:
andrej@1731:             languageDict[i.CanonicalName] = i.Description
andrej@1731: 
andrej@1731:     return languageDict
andrej@1731: 
andrej@1731: 
andrej@1756: def verbosePrint(verbose, str):
andrej@1756:     if verbose:
andrej@1826:         print(str)
andrej@1756: 
andrej@1756: 
andrej@1744: def processCustomFiles(filein, fileout, regexp, prefix=''):
andrej@1731:     appfil_file = open(filein, 'r')
andrej@1731:     messages_file = open(fileout, 'r')
andrej@1731:     messages = messages_file.read()
andrej@1731:     messages_file.close()
andrej@1731:     messages_file = open(fileout, 'a')
andrej@1731:     messages_file.write('\n')
andrej@1731:     messages_file.write('#: %s\n' % prefix)
andrej@1731:     messages_file.write('\n')
andrej@1731: 
andrej@1731:     words_found = {}
andrej@2441:     for filepath in appfil_file.readlines():
andrej@1731:         code_file = open(filepath.strip(), 'r')
andrej@1731:         for match in regexp.finditer(code_file.read()):
andrej@1731:             word = match.group(1)
andrej@1731:             if not words_found.get(word, False) and messages.find("msgid \"%s\"\nmsgstr \"\"" % word) == -1:
andrej@1731:                 words_found[word] = True
andrej@1731:                 messages_file.write('\n')
andrej@1734:                 messages_file.write("msgid \"%s\"\n" % word)
andrej@1731:                 messages_file.write("msgstr \"\"\n")
andrej@1731:         code_file.close()
andrej@1731: 
andrej@1731:     messages_file.close()
andrej@1731:     appfil_file.close()
andrej@1731: 
andrej@1731: 
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: # m a k e P O ( )         -- Build the Portable Object file for the application --
andrej@1731: # ^^^^^^^^^^^^^^^
andrej@1731: #
andrej@1739: def makePO(applicationDirectoryPath,  applicationDomain=None, verbose=0):
andrej@1731:     """Build the Portable Object Template file for the application.
andrej@1731: 
andrej@1731:     makePO builds the .pot file for the application stored inside
andrej@1731:     a specified directory by running xgettext for all application source
andrej@1731:     files.  It finds the name of all files by looking for a file called 'app.fil'.
andrej@1731:     If this file does not exists, makePo raises an IOError exception.
andrej@1731:     By default the application domain (the application
andrej@1731:     name) is the same as the directory name but it can be overridden by the
andrej@1731:     'applicationDomain' argument.
andrej@1731: 
andrej@1731:     makePO always creates a new file called messages.pot.  If it finds files
andrej@1731:     of the form app_xx.po where 'app' is the application name and 'xx' is one
andrej@1731:     of the ISO 639 two-letter language codes, makePO resynchronizes those
andrej@1731:     files with the latest extracted strings (now contained in messages.pot).
andrej@1731:     This process updates all line location number in the language-specific
andrej@1731:     .po files and may also create new entries for translation (or comment out
andrej@1731:     some).  The .po file is not changed, instead a new file is created with
andrej@1731:     the .new extension appended to the name of the .po file.
andrej@1731: 
andrej@1731:     By default the function does not display what it is doing.  Set the
andrej@1731:     verbose argument to 1 to force it to print its commands.
andrej@1731:     """
andrej@1731: 
andrej@1731:     if applicationDomain is None:
andrej@1740:         applicationName = fileBaseOf(applicationDirectoryPath, withPath=0)
andrej@1731:     else:
andrej@1731:         applicationName = applicationDomain
andrej@1731:     currentDir = os.getcwd()
andrej@1731:     os.chdir(applicationDirectoryPath)
andrej@1731:     filelist = 'app.fil'
andrej@1731:     if not os.path.exists(filelist):
andrej@2452:         raise IOError(2, 'No module file: %s' % filelist)
andrej@1731: 
andrej@1731:     fileout = 'messages.pot'
andrej@1731:     # Steps:
andrej@1731:     #  Use xgettext to parse all application modules
andrej@1731:     #  The following switches are used:
andrej@1731:     #
andrej@1731:     #   -s                          : sort output by string content (easier to use when we need to merge several .po files)
andrej@1731:     #   --files-from=app.fil        : The list of files is taken from the file: app.fil
andrej@1731:     #   --output=                   : specifies the name of the output file (using a .pot extension)
andrej@1731:     cmd = 'xgettext -s --no-wrap --language=Python --files-from=' + filelist + ' --output=' + fileout + ' --package-name ' + applicationName
andrej@1756:     verbosePrint(verbose, cmd)
andrej@1731:     os.system(cmd)
andrej@1731: 
andrej@2439:     XSD_STRING_MODEL = re.compile(r"<xsd\:(?:element|attribute) name=\"([^\"]*)\"[^\>]*\>")
andrej@1731:     processCustomFiles(filelist, fileout, XSD_STRING_MODEL, 'Extra XSD strings')
andrej@1731: 
andrej@2439:     XML_TC6_STRING_MODEL = re.compile(r"<documentation>\s*<xhtml\:p><!\[CDATA\[([^\]]*)\]\]></xhtml\:p>\s*</documentation>", re.MULTILINE | re.DOTALL)
andrej@1731:     processCustomFiles(filelist, fileout, XML_TC6_STRING_MODEL, 'Extra TC6 documentation strings')
andrej@1731: 
andrej@1731:     # generate messages.po
andrej@1731:     cmd = 'msginit --no-wrap --no-translator -i %s -l en_US.UTF-8 -o messages.po' % (fileout)
andrej@1756:     verbosePrint(verbose, cmd)
andrej@1731:     os.system(cmd)
andrej@1731: 
andrej@2350:     languageDict = getSupportedLanguageDict(applicationName)
andrej@1731: 
andrej@1731:     for langCode in languageDict.keys():
andrej@1731:         if langCode == 'en':
andrej@1731:             pass
andrej@1731:         else:
andrej@1739:             langPOfileName = "%s_%s.po" % (applicationName, langCode)
andrej@1731:             if os.path.exists(langPOfileName):
andrej@1731:                 cmd = 'msgmerge -s --no-wrap "%s" %s > "%s.new"' % (langPOfileName, fileout, langPOfileName)
andrej@1756:                 verbosePrint(verbose, cmd)
andrej@1731:                 os.system(cmd)
andrej@1731:     os.chdir(currentDir)
andrej@1731: 
andrej@1736: 
andrej@1739: def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0):
andrej@1731:     """Concatenate one or several PO files with the application domain files.
andrej@1731:     """
andrej@1731: 
andrej@1731:     if applicationDomain is None:
andrej@1740:         applicationName = fileBaseOf(applicationDirectoryPath, withPath=0)
andrej@1731:     else:
andrej@1731:         applicationName = applicationDomain
andrej@1731:     currentDir = os.getcwd()
andrej@1731:     os.chdir(applicationDirectoryPath)
andrej@1731: 
andrej@2350:     languageDict = getSupportedLanguageDict(applicationName)
andrej@1731: 
andrej@1731:     for langCode in languageDict.keys():
andrej@1731:         if langCode == 'en':
andrej@1731:             pass
andrej@1731:         else:
andrej@1739:             langPOfileName = "%s_%s.po" % (applicationName, langCode)
andrej@1731:             if os.path.exists(langPOfileName):
andrej@1731:                 fileList = ''
andrej@1731:                 for fileName in listOf_extraPo:
andrej@1740:                     fileList += ("%s_%s.po " % (fileName, langCode))
andrej@1731:                 cmd = "msgcat -s --no-wrap %s %s > %s.cat" % (langPOfileName, fileList, langPOfileName)
andrej@1756:                 verbosePrint(verbose, cmd)
andrej@1731:                 os.system(cmd)
andrej@1731:                 if targetDir is None:
andrej@1731:                     pass
andrej@1731:                 else:
andrej@1740:                     mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir, langCode)
andrej@1740:                     cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po.cat" % (mo_targetDir, applicationName, applicationName, langCode)
andrej@1756:                     verbosePrint(verbose, cmd)
andrej@1731:                     os.system(cmd)
andrej@1731:     os.chdir(currentDir)
andrej@1731: 
andrej@1736: 
andrej@1740: def makeMO(applicationDirectoryPath, targetDir='./locale', applicationDomain=None, verbose=0, forceEnglish=0):
andrej@1731:     """Compile the Portable Object files into the Machine Object stored in the right location.
andrej@1731: 
andrej@1731:     makeMO converts all translated language-specific PO files located inside
andrej@1731:     the  application directory into the binary .MO files stored inside the
andrej@1731:     LC_MESSAGES sub-directory for the found locale files.
andrej@1731: 
andrej@1731:     makeMO searches for all files that have a name of the form 'app_xx.po'
andrej@1731:     inside the application directory specified by the first argument.  The
andrej@1731:     'app' is the application domain name (that can be specified by the
andrej@1731:     applicationDomain argument or is taken from the directory name). The 'xx'
andrej@1731:     corresponds to one of the ISO 639 two-letter language codes.
andrej@1731: 
andrej@1731:     makeMo stores the resulting files inside a sub-directory of `targetDir`
andrej@1731:     called xx/LC_MESSAGES where 'xx' corresponds to the 2-letter language
andrej@1731:     code.
andrej@1731:     """
andrej@1756: 
andrej@1731:     if targetDir is None:
andrej@1731:         targetDir = './locale'
andrej@1756: 
andrej@1756:     verbosePrint(verbose, "Target directory for .mo files is: %s" % targetDir)
andrej@1731: 
andrej@1731:     if applicationDomain is None:
andrej@1740:         applicationName = fileBaseOf(applicationDirectoryPath, withPath=0)
andrej@1731:     else:
andrej@1731:         applicationName = applicationDomain
andrej@1731:     currentDir = os.getcwd()
andrej@1731:     os.chdir(applicationDirectoryPath)
andrej@1731: 
andrej@2350:     languageDict = getSupportedLanguageDict(applicationName)
andrej@1731: 
andrej@1731:     for langCode in languageDict.keys():
andrej@1742:         if (langCode == 'en') and (forceEnglish == 0):
andrej@1731:             pass
andrej@1731:         else:
andrej@1739:             langPOfileName = "%s_%s.po" % (applicationName, langCode)
andrej@1731:             if os.path.exists(langPOfileName):
andrej@1740:                 mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir, langCode)
andrej@1731:                 if not os.path.exists(mo_targetDir):
andrej@1731:                     mkdir(mo_targetDir)
andrej@1740:                 cmd = 'msgfmt --output-file="%s/%s.mo" "%s_%s.po"' % (mo_targetDir, applicationName, applicationName, langCode)
andrej@1756:                 verbosePrint(verbose, cmd)
andrej@1731:                 os.system(cmd)
andrej@1731:     os.chdir(currentDir)
andrej@1731: 
andrej@1736: 
andrej@1739: def printUsage(errorMsg=None):
andrej@1731:     """Displays how to use this script from the command line."""
andrej@1826:     print("""
andrej@1731:     ##################################################################################
andrej@1731:     #   mki18n :   Make internationalization files.                                  #
andrej@1731:     #              Uses the GNU gettext system to create PO (Portable Object) files  #
andrej@1731:     #              from source code, coimpile PO into MO (Machine Object) files.     #
andrej@1731:     #              Supports C,C++,Python source files.                               #
andrej@1731:     #                                                                                #
andrej@1731:     #   Usage: mki18n {OPTION} [appDirPath]                                          #
andrej@1731:     #                                                                                #
andrej@1731:     #   Options:                                                                     #
andrej@1731:     #     -e               : When -m is used, forces English .mo file creation       #
andrej@1731:     #     -h               : prints this help                                        #
andrej@1731:     #     -m               : make MO from existing PO files                          #
andrej@1731:     #     -p               : make PO, update PO files: Creates a new messages.pot    #
andrej@1731:     #                        file. Creates a dom_xx.po.new for every existing        #
andrej@1731:     #                        language specific .po file. ('xx' stands for the ISO639 #
andrej@1731:     #                        two-letter language code and 'dom' stands for the       #
andrej@1731:     #                        application domain name).  mki18n requires that you     #
andrej@1731:     #                        write a 'app.fil' file  which contains the list of all  #
andrej@1731:     #                        source code to parse.                                   #
andrej@1731:     #     -v               : verbose (prints comments while running)                 #
andrej@1731:     #     --domain=appName : specifies the application domain name.  By default      #
andrej@1731:     #                        the directory name is used.                             #
andrej@1731:     #     --moTarget=dir : specifies the directory where .mo files are stored.       #
andrej@1731:     #                      If not specified, the target is './locale'                #
andrej@1731:     #                                                                                #
andrej@1731:     #   You must specify one of the -p or -m option to perform the work.  You can    #
andrej@1731:     #   specify the path of the target application.  If you leave it out mki18n      #
andrej@1731:     #   will use the current directory as the application main directory.            #
andrej@1731:     #                                                                                #
andrej@1826:     ##################################################################################""")
andrej@1731:     if errorMsg:
andrej@1826:         print("\n   ERROR: %s" % errorMsg)
andrej@1731: 
andrej@1736: 
andrej@1740: def fileBaseOf(filename, withPath=0):
andrej@1757:     """fileBaseOf(filename,withPath) ---> string
andrej@1757: 
andrej@1757:     Return base name of filename.  The returned string never includes the extension.
andrej@1757:     Use os.path.basename() to return the basename with the extension.  The
andrej@1757:     second argument is optional.  If specified and if set to 'true' (non zero)
andrej@1757:     the string returned contains the full path of the file name.  Otherwise the
andrej@1757:     path is excluded.
andrej@1757: 
andrej@1757:     [Example]
andrej@1757:     >>> fn = 'd:/dev/telepath/tvapp/code/test.html'
andrej@1757:     >>> fileBaseOf(fn)
andrej@1757:     'test'
andrej@1757:     >>> fileBaseOf(fn)
andrej@1757:     'test'
andrej@1757:     >>> fileBaseOf(fn,1)
andrej@1757:     'd:/dev/telepath/tvapp/code/test'
andrej@1757:     >>> fileBaseOf(fn,0)
andrej@1757:     'test'
andrej@1757:     >>> fn = 'abcdef'
andrej@1757:     >>> fileBaseOf(fn)
andrej@1757:     'abcdef'
andrej@1757:     >>> fileBaseOf(fn,1)
andrej@1757:     'abcdef'
andrej@1757:     >>> fn = "abcdef."
andrej@1757:     >>> fileBaseOf(fn)
andrej@1757:     'abcdef'
andrej@1757:     >>> fileBaseOf(fn,1)
andrej@1757:     'abcdef'
andrej@1757:     """
andrej@1757:     pos = filename.rfind('.')
andrej@1757:     if pos > 0:
andrej@1757:         filename = filename[:pos]
andrej@1757:     if withPath:
andrej@1757:         return filename
andrej@1757:     else:
andrej@1757:         return os.path.basename(filename)
andrej@1736: 
andrej@1736: 
andrej@1739: def mkdir(directory):
andrej@1757:     """Create a directory (and possibly the entire tree).
andrej@1757: 
andrej@1757:     The os.mkdir() will fail to create a directory if one of the
andrej@1757:     directory in the specified path does not exist.  mkdir()
andrej@1757:     solves this problem.  It creates every intermediate directory
andrej@1757:     required to create the final path. Under Unix, the function
andrej@1757:     only supports forward slash separator, but under Windows and MacOS
andrej@1757:     the function supports the forward slash and the OS separator (backslash
andrej@1757:     under windows).
andrej@1757:     """
andrej@1757: 
andrej@1757:     # translate the path separators
andrej@1757:     directory = unixpath(directory)
andrej@1757:     # build a list of all directory elements
andrej@1757:     aList = filter(lambda x: len(x) > 0, directory.split('/'))
andrej@1757:     theLen = len(aList)
andrej@1757:     # if the first element is a Windows-style disk drive
andrej@1757:     # concatenate it with the first directory
andrej@1757:     if aList[0].endswith(':'):
andrej@1757:         if theLen > 1:
andrej@1757:             aList[1] = aList[0] + '/' + aList[1]
andrej@1757:             del aList[0]
andrej@1757:             theLen -= 1
andrej@1757:     # if the original directory starts at root,
andrej@1757:     # make sure the first element of the list
andrej@1757:     # starts at root too
andrej@1757:     if directory[0] == '/':
andrej@1757:         aList[0] = '/' + aList[0]
andrej@1757:     # Now iterate through the list, check if the
andrej@1757:     # directory exists and if not create it
andrej@1757:     theDir = ''
andrej@1757:     for i in range(theLen):
andrej@1757:         theDir += aList[i]
andrej@1757:         if not os.path.exists(theDir):
andrej@1757:             os.mkdir(theDir)
andrej@1757:         theDir += '/'
andrej@1731: 
andrej@1736: 
andrej@1739: def unixpath(thePath):
andrej@1757:     r"""Return a path name that contains Unix separator.
andrej@1757: 
andrej@1757:     [Example]
andrej@1757:     >>> unixpath(r"d:\test")
andrej@1757:     'd:/test'
andrej@1757:     >>> unixpath("d:/test/file.txt")
andrej@1757:     'd:/test/file.txt'
andrej@1757:     >>>
andrej@1757:     """
andrej@1757:     thePath = os.path.normpath(thePath)
andrej@1757:     if os.sep == '/':
andrej@1757:         return thePath
andrej@1757:     else:
andrej@1757:         return thePath.replace(os.sep, '/')
andrej@1731: 
andrej@1749: 
andrej@1731: # -----------------------------------------------------------------------------
andrej@1731: 
andrej@1731: # S c r i p t   e x e c u t i o n               -- Runs when invoked from the command line --
andrej@1731: # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
andrej@1731: #
andrej@1731: if __name__ == "__main__":
Edouard@1919:     # command line parsing
Edouard@1919:     import getopt    # pylint: disable=wrong-import-order,wrong-import-position
andrej@1731:     argc = len(sys.argv)
andrej@1731:     if argc == 1:
andrej@1731:         printUsage('Missing argument: specify at least one of -m or -p (or both).')
andrej@1731:         sys.exit(1)
andrej@1731:     # If there is some arguments, parse the command line
andrej@1754:     validOptions = "ehmpv"
andrej@1731:     validLongOptions = ['domain=', 'moTarget=']
andrej@1731:     option = {}
andrej@1731:     option['forceEnglish'] = 0
andrej@1731:     option['mo'] = 0
andrej@1731:     option['po'] = 0
andrej@1731:     option['verbose'] = 0
andrej@1731:     option['domain'] = None
andrej@1731:     option['moTarget'] = None
andrej@1756:     optionKey = {
andrej@1756:         '-e':         'forceEnglish',
andrej@1756:         '-m':         'mo',
andrej@1756:         '-p':         'po',
andrej@1756:         '-v':         'verbose',
andrej@1756:         '--domain':   'domain',
andrej@1756:         '--moTarget': 'moTarget',
andrej@1756:     }
andrej@1844:     exit_code = 1
andrej@1731:     try:
andrej@1740:         optionList, pargs = getopt.getopt(sys.argv[1:], validOptions, validLongOptions)
andrej@2418:     except getopt.GetoptError as e:
andrej@2452:         printUsage(e)
andrej@1731:         sys.exit(1)
andrej@1740:     for (opt, val) in optionList:
andrej@1828:         if opt == '-h':
andrej@1731:             printUsage()
andrej@1731:             sys.exit(0)
andrej@1756:         option[optionKey[opt]] = 1 if val == '' else val
andrej@1731:     if len(pargs) == 0:
andrej@1731:         appDirPath = os.getcwd()
andrej@1731:         if option['verbose']:
andrej@1826:             print("No project directory given. Using current one:  %s" % appDirPath)
andrej@1731:     elif len(pargs) == 1:
andrej@1731:         appDirPath = pargs[0]
andrej@1731:     else:
andrej@1731:         printUsage('Too many arguments (%u).  Use double quotes if you have space in directory name' % len(pargs))
andrej@1731:         sys.exit(1)
andrej@1731:     if option['domain'] is None:
andrej@1731:         # If no domain specified, use the name of the target directory
andrej@1731:         option['domain'] = fileBaseOf(appDirPath)
andrej@1731:     if option['verbose']:
andrej@1826:         print("Application domain used is: '%s'" % option['domain'])
andrej@1731:     if option['po']:
andrej@1731:         try:
andrej@1740:             makePO(appDirPath, option['domain'], option['verbose'])
andrej@1844:             exit_code = 0
andrej@2418:         except IOError as e:
andrej@2452:             printUsage(text(e) + '\n   You must write a file app.fil that contains the list of all files to parse.')
andrej@1731:     if option['mo']:
andrej@1740:         makeMO(appDirPath, option['moTarget'], option['domain'], option['verbose'], option['forceEnglish'])
andrej@1844:         exit_code = 0
andrej@1844:     sys.exit(exit_code)
andrej@1844: 
andrej@1844: 
andrej@1844: # -----------------------------------------------------------------------------