i18n Python scripts: allow autodetection of translation files
- Add class method availableTranslations() to AbstractFormatHandler in i18n.py. - Use it in fg-update-translation-files to allow autodetection of the available translations when no LANGUAGE_CODE is passed to fg-update-translation-files. This should address James' wish at <https://sourceforge.net/p/flightgear/mailman/message/37003967/>.
This commit is contained in:
@@ -36,6 +36,10 @@ localization files in $FG_ROOT/Translations/<language_code>):
|
|||||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||||
merge-new-master $languages
|
merge-new-master $languages
|
||||||
|
|
||||||
|
Note: you may omit $languages in the fg-update-translation-files command if
|
||||||
|
you want to autodetect the FlightGear-nonQt.xlf files present in
|
||||||
|
$FG_ROOT/Translations.
|
||||||
|
|
||||||
Updating XLIFF files to reflect changes in the default translation
|
Updating XLIFF files to reflect changes in the default translation
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -45,6 +49,9 @@ modified or removed, or categories added or removed[3]):
|
|||||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||||
merge-new-master $languages
|
merge-new-master $languages
|
||||||
|
|
||||||
|
Note: you may omit $languages in this command if you want to autodetect the
|
||||||
|
FlightGear-nonQt.xlf files present in $FG_ROOT/Translations.
|
||||||
|
|
||||||
Updating XLIFF files to mark or remove obsolete translated strings
|
Updating XLIFF files to mark or remove obsolete translated strings
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -53,9 +60,14 @@ To remove unused translated strings (not to be done too often in my opinion):
|
|||||||
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \
|
||||||
remove-unused $languages
|
remove-unused $languages
|
||||||
|
|
||||||
(you may replace 'remove-unused' with 'mark-unused' to just mark the strings
|
Notes:
|
||||||
as not-to-be-translated, however 'merge-new-master' presented above already
|
|
||||||
does that)
|
- You may omit $languages in this command if you want to autodetect the
|
||||||
|
FlightGear-nonQt.xlf files present in $FG_ROOT/Translations.
|
||||||
|
|
||||||
|
- It is possible to replace 'remove-unused' with 'mark-unused' to just mark
|
||||||
|
the strings as not-to-be-translated; however, 'merge-new-master' presented
|
||||||
|
above already does that.
|
||||||
|
|
||||||
Merging contents from an XLIFF file into another one
|
Merging contents from an XLIFF file into another one
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import sys
|
|||||||
|
|
||||||
import flightgear.meta.logging
|
import flightgear.meta.logging
|
||||||
import flightgear.meta.i18n as fg_i18n
|
import flightgear.meta.i18n as fg_i18n
|
||||||
|
from flightgear.meta.i18n import XliffFormatHandler
|
||||||
|
|
||||||
|
|
||||||
PROGNAME = os.path.basename(sys.argv[0])
|
PROGNAME = os.path.basename(sys.argv[0])
|
||||||
@@ -45,7 +46,7 @@ def processCommandLine():
|
|||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
usage="""\
|
usage="""\
|
||||||
%(prog)s [OPTION ...] ACTION LANGUAGE_CODE...
|
%(prog)s [OPTION ...] ACTION [LANGUAGE_CODE]...
|
||||||
Update FlightGear XLIFF localization files.""",
|
Update FlightGear XLIFF localization files.""",
|
||||||
description="""\
|
description="""\
|
||||||
This program performs the following operations (actions) on FlightGear XLIFF
|
This program performs the following operations (actions) on FlightGear XLIFF
|
||||||
@@ -68,6 +69,13 @@ translation files (*.xlf):
|
|||||||
In the XLIFF localization files corresponding to the specified
|
In the XLIFF localization files corresponding to the specified
|
||||||
language(s), remove all translated strings that are marked as unused.
|
language(s), remove all translated strings that are marked as unused.
|
||||||
|
|
||||||
|
If no LANGUAGE_CODE is provided as an argument, then assuming $transl_dir
|
||||||
|
represents the value passed to --transl-dir, all directories $d such that a
|
||||||
|
file named FlightGear-nonQt.xlf is found in $transl_dir/$d will be acted on as
|
||||||
|
if they had been passed as LANGUAGE_CODE arguments (actually, the directory
|
||||||
|
$transl_dir/default is not considered as a candidate; it is simply skipped).
|
||||||
|
Typically, $transl_dir is /path/to/FGData/Translations.
|
||||||
|
|
||||||
A translated string that is marked as unused is still present in the XLIFF
|
A translated string that is marked as unused is still present in the XLIFF
|
||||||
localization file; it is just presented in a way that tells translators they
|
localization file; it is just presented in a way that tells translators they
|
||||||
don't need to worry about it. On the other hand, when a translated string is
|
don't need to worry about it. On the other hand, when a translated string is
|
||||||
@@ -105,7 +113,7 @@ general on the short or mid-term: they only take some space.
|
|||||||
remove those already marked as unused from the XLIFF
|
remove those already marked as unused from the XLIFF
|
||||||
files corresponding to each given LANGUAGE_CODE (i.e.,
|
files corresponding to each given LANGUAGE_CODE (i.e.,
|
||||||
those that are not in the default translation)""")
|
those that are not in the default translation)""")
|
||||||
parser.add_argument("lang_code", metavar="LANGUAGE_CODE", nargs="+",
|
parser.add_argument("lang_code", metavar="LANGUAGE_CODE", nargs="*",
|
||||||
help="""\
|
help="""\
|
||||||
codes of languages to operate on (e.g., fr, en_GB, it,
|
codes of languages to operate on (e.g., fr, en_GB, it,
|
||||||
es_ES...)""")
|
es_ES...)""")
|
||||||
@@ -125,11 +133,19 @@ class MarkOrRemoveUnusedAction(enum.Enum):
|
|||||||
mark, remove = range(2)
|
mark, remove = range(2)
|
||||||
|
|
||||||
|
|
||||||
|
def langCodesToActOn():
|
||||||
|
"""Return an iterable of all language codes we were told to work on."""
|
||||||
|
if params.lang_code:
|
||||||
|
return params.lang_code
|
||||||
|
else:
|
||||||
|
return XliffFormatHandler.availableTranslations(params.transl_dir)
|
||||||
|
|
||||||
|
|
||||||
def markOrRemoveUnused(l10nResPoolMgr, action):
|
def markOrRemoveUnused(l10nResPoolMgr, action):
|
||||||
formatHandler = fg_i18n.XliffFormatHandler()
|
formatHandler = fg_i18n.XliffFormatHandler()
|
||||||
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
||||||
|
|
||||||
for langCode in params.lang_code:
|
for langCode in langCodesToActOn():
|
||||||
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
||||||
transl = formatHandler.readTranslation(xliffPath)
|
transl = formatHandler.readTranslation(xliffPath)
|
||||||
|
|
||||||
@@ -148,7 +164,7 @@ def mergeNewMaster(l10nResPoolMgr):
|
|||||||
formatHandler = fg_i18n.XliffFormatHandler()
|
formatHandler = fg_i18n.XliffFormatHandler()
|
||||||
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl
|
||||||
|
|
||||||
for langCode in params.lang_code:
|
for langCode in langCodesToActOn():
|
||||||
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode)
|
||||||
transl = formatHandler.readTranslation(xliffPath)
|
transl = formatHandler.readTranslation(xliffPath)
|
||||||
transl.mergeMasterTranslation(masterTransl, logger=logger)
|
transl.mergeMasterTranslation(masterTransl, logger=logger)
|
||||||
|
|||||||
@@ -1001,6 +1001,33 @@ class AbstractFormatHandler(metaclass=abc.ABCMeta):
|
|||||||
baseName = cls.defaultFileBaseName(targetLanguage)
|
baseName = cls.defaultFileBaseName(targetLanguage)
|
||||||
return os.path.join(translationsDir, targetLanguage, baseName)
|
return os.path.join(translationsDir, targetLanguage, baseName)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def availableTranslations(cls, translationsDir):
|
||||||
|
"""Return a list of all available translations in translationsDir.
|
||||||
|
|
||||||
|
This method expects a particular layout for translation files:
|
||||||
|
the one used in $FG_ROOT/Translations. More precisely, it looks
|
||||||
|
for all files named LANG_CODE/NAME in translationsDir, where
|
||||||
|
NAME is cls.defaultFileBaseName(LANG_CODE). The special
|
||||||
|
directory translationsDir/DEFAULT_LANG_DIR is not explored;
|
||||||
|
thus, the result cannot contain DEFAULT_LANG_DIR.
|
||||||
|
|
||||||
|
Return a list of language codes, sorted with list.sort().
|
||||||
|
|
||||||
|
"""
|
||||||
|
res = []
|
||||||
|
with os.scandir(translationsDir) as it:
|
||||||
|
for entry in it:
|
||||||
|
if (entry.name != DEFAULT_LANG_DIR and entry.is_dir() and
|
||||||
|
os.path.isfile(
|
||||||
|
os.path.join(
|
||||||
|
translationsDir, entry.name,
|
||||||
|
cls.defaultFileBaseName(entry.name)))):
|
||||||
|
res.append(entry.name)
|
||||||
|
|
||||||
|
res.sort()
|
||||||
|
return res
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def writeTranslation(self, transl, filePath):
|
def writeTranslation(self, transl, filePath):
|
||||||
"""Write a Translation instance to a file."""
|
"""Write a Translation instance to a file."""
|
||||||
|
|||||||
Reference in New Issue
Block a user