wesnoth/utils/wmlxgettext
Nobun 3f287b9098 wmlxgettext: fix UTF-8 issue: #1785 (#1793)
Also: -o parameter is now mandatory. STOUT redirection still possible
2017-07-31 22:29:46 -04:00

262 lines
10 KiB
Python
Executable File

#!/usr/bin/env python3
# encoding: utf-8
#
# wmlxgettext -- generate a blank .pot file for official campaigns translations
# (build tool for wesnoth core)
#
#
# By Nobun, october 2015
# Thanks to Elvish Hunter for writing code for coloring text under windows
#
# PURPOSE
#
# wmlxgettext is a python3 tool that replace the old (but very good)
# perl script with the same name.
# Replacing perl with python3 will ensure more portability.
#
# wmlxgettext is a tool that is directly used during wesnoth build process
# to generate the pot files for the core campaigns.
#
# USAGE
#
# If you want to learn how to use wmlxgettext, read the online End-User
# documentation at:
# http://wmlxgettext-unoff.readthedocs.org/en/latest/enduser/index.html
#
# SOURCE CODE DOCUMENTATION
#
# While the source code contains some comments that explain what it does at
# that point, the source code is mainly explained on source documentation at:
# http://wmlxgettext-unoff.readthedocs.org/en/latest/srcdoc/index.html
import os
import re
import sys
import warnings
import argparse
from datetime import datetime
import pywmlx
def commandline(args):
parser = argparse.ArgumentParser(
description='Generate .po from WML/lua file list.',
usage='''wmlxgettext --domain=DOMAIN -o OUTPUT_FILE
[--directory=START_PATH]
[--recursive] [--initialdomain=INITIALDOMAIN]
[--package-version=PACKAGE_VERSION]
[--no-text-colors] [--fuzzy] [--warnall]
FILE1 FILE2 ... FILEN'''
)
parser.add_argument(
'--version',
action='version',
version='wmlxgettext 2017.06.25.py3'
)
parser.add_argument(
'-o',
required=True,
default=None,
dest='outfile',
help= ('Destination file. In some special situations you might want '
'to write the output to STDOUT instead of writing '
'an actual file (using "-o -"). On a standard usage, however, '
'you should avoid to write the output to STDOUT (or you can'
'face some issues related to text encoding '
'[**REQUIRED ARGUMENT**]')
)
parser.add_argument(
'--domain',
default='wmlxgettext',
required=True,
dest='domain',
help= ('The textdomain (on WML/lua file) wich contains the '
'strings that will be actually translated '
'[**REQUIRED ARGUMENT**]')
)
parser.add_argument(
'--directory',
default='.',
dest='start_path',
help=('Complete path of your "start directory". '
'The path to every source file should start from this '
'directory.')
)
parser.add_argument(
'--initialdomain',
default='wesnoth',
dest='initdom',
help=('Initial domain value on WML/lua file when no textdomain '
'setted in that WML/lua file.\nBy default it is equal to '
'"wesnoth" and usually you don\'t need to change this value')
)
parser.add_argument(
'--package-version',
default='PACKAGE VERSION',
dest='package_version',
help=('Version number of your wesnoth add-on. You don\'t actually '
'require to set this option since you can directly edit the '
'po file produced by wmlxgettext. However this option could '
'help you to save a bit of time')
)
parser.add_argument(
'--no-text-colors',
action='store_false',
default=True,
dest='text_col',
help=("By default warnings are displayed with colored text. You can "
"disable this feature using this flag.")
)
parser.add_argument(
'--warnall',
action='store_true',
default=False,
dest='warnall',
help="Show all warnings. By default some warnings are hided"
)
parser.add_argument(
'--fuzzy',
action='store_true',
default=False,
dest='fuzzy',
help=("If you specify this flag, all sentences contained on the POT "
"file created by wmlxgettext will be setted as fuzzy.\n"
"By default sentences are NOT setted as fuzzy")
)
parser.add_argument(
'--recursive',
action='store_true',
default=False,
help=("If this option is used, wmlxgettext will scan recursively the"
" directory setted on the '--directory' parameter. "
"If this option is used, EXPLICIT LIST of files will be "
"ignored.")
)
parser.add_argument(
'--DMode',
action='store_true',
dest='debugmode',
default=False,
help=("DON'T USE THIS OPTION. It is reserved to test how wmlxgettext "
"internally works. If this option is enabled, an extra "
"file (debug.txt) will be created. ")
)
parser.add_argument(
'filelist',
help='List of WML/lua files of your UMC (source files)',
nargs='*'
)
return parser.parse_args(args)
def main():
args = commandline(sys.argv[1:])
pywmlx.ansi_setEnabled(args.text_col)
pywmlx.wincol_setEnabled(args.text_col)
pywmlx.set_warnall(args.warnall)
startPath = os.path.realpath(os.path.normpath(args.start_path))
sentlist = dict()
fileno = 0
fdebug = None
if args.outfile == '-':
args.outfile = None
if args.debugmode:
fdebug = open('debug.txt', 'w', encoding='utf-8')
pywmlx.statemachine.setup(sentlist, args.initdom, args.domain,
args.warnall, fdebug)
filelist = None
if args.recursive is False and args.filelist is None:
pywmlx.wmlerr("bad command line", "FILELIST must not be empty. "
"Please, run wmlxgettext again and, this time, add some file "
"in FILELIST or use the --recursive option.")
elif args.recursive is False and len(args.filelist) <= 0:
pywmlx.wmlerr("bad command line", "FILELIST must not be empty. "
"Please, run wmlxgettext again and, this time, add some file "
"in FILELIST or use the --recursive option.")
elif args.recursive is False:
filelist = args.filelist
# the following elif case implicitly expects that args.recursive is True
elif args.filelist is not None:
if len(args.filelist) > 0:
pywmlx.wmlwarn("command line warning", "Option --recursive was "
"used, but FILELIST is not empty. All extra file listed in "
"FILELIST will be ignored.")
# If we use the --recursive option we recursively scan the add-on
# directory.
# But we want that the file reference informations placed
# in the .po file will remember the (relative) root name of the
# addon.
# This is why the autof.autoscan function returns a tuple of
# values:
# the first one is the parent directory of the original startPath
# the second one is the filelist (with the "fixed" file references)
# This way, we can override startPath with its parent directory
# containing the main directory of the wesnoth add-on, without
# introducing bugs.
startPath, filelist = pywmlx.autof.autoscan(startPath)
# this last case is equal to:
# if args.recursive is True and args.filelist is None:
else:
startPath, filelist = pywmlx.autof.autoscan(startPath)
for fileno, fx in enumerate(filelist):
fname = os.path.join(startPath, os.path.normpath(fx))
is_file = os.path.isfile(fname)
if is_file:
infile = None
try:
infile = open(fname, 'r', encoding="utf-8")
except OSError as e:
errmsg = 'cannot read file: ' + e.args[1]
pywmlx.wmlerr(e.filename, errmsg, OSError)
if fname.lower().endswith('.cfg'):
pywmlx.statemachine.run(filebuf=infile, fileref=fx,
fileno=fileno, startstate='wml_idle', waitwml=True)
if fname.lower().endswith('.lua'):
pywmlx.statemachine.run(filebuf=infile, fileref=fx,
fileno=fileno, startstate='lua_idle', waitwml=False)
infile.close()
outfile = None
if args.outfile is None:
outfile = sys.stdout
else:
outfile_name = os.path.realpath(os.path.normpath(args.outfile))
try:
outfile = open(outfile_name, 'w', encoding="utf-8")
except OSError as e:
errmsg = 'cannot write file: ' + e.args[1]
pywmlx.wmlerr(e.filename, errmsg, OSError)
pkgversion = args.package_version + '\\n"'
print('msgid ""\nmsgstr ""', file=outfile)
print('"Project-Id-Version:', pkgversion, file=outfile)
print('"Report-Msgid-Bugs-To: http://bugs.wesnoth.org/\\n"', file=outfile)
now = datetime.utcnow()
cdate = '{:04d}-{:02d}-{:02d} {:02d}:{:02d} UTC\\n"'.format(now.year,
now.month,
now.day,
now.hour,
now.minute)
print('"POT-Creation-Date:', cdate, file=outfile)
print('"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n"', file=outfile)
print('"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"', file=outfile)
print('"Language-Team: LANGUAGE <LL@li.org>\\n"', file=outfile)
print('"MIME-Version: 1.0\\n"', file=outfile)
print('"Content-Type: text/plain; charset=UTF-8\\n"', file=outfile)
print('"Content-Transfer-Encoding: 8bit\\n"\n', file=outfile)
for posentence in sorted(sentlist.values(), key=lambda x: x.orderid):
posentence.write(outfile, args.fuzzy)
print('', file=outfile)
if args.outfile is not None:
outfile.close()
if args.debugmode:
fdebug.close()
if __name__ == "__main__":
main()