diff --git a/python3-flightgear/README-l10n.txt b/python3-flightgear/README-l10n.txt index 8cbb8d8..5317b49 100644 --- a/python3-flightgear/README-l10n.txt +++ b/python3-flightgear/README-l10n.txt @@ -36,6 +36,10 @@ localization files in $FG_ROOT/Translations/): fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \ 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 ------------------------------------------------------------------ @@ -45,6 +49,9 @@ modified or removed, or categories added or removed[3]): fg-update-translation-files --transl-dir="$FG_ROOT/Translations" \ 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 ------------------------------------------------------------------ @@ -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" \ remove-unused $languages -(you may 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) +Notes: + + - 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 ---------------------------------------------------- diff --git a/python3-flightgear/fg-update-translation-files b/python3-flightgear/fg-update-translation-files index 26b35b3..3ae3dad 100755 --- a/python3-flightgear/fg-update-translation-files +++ b/python3-flightgear/fg-update-translation-files @@ -27,6 +27,7 @@ import sys import flightgear.meta.logging import flightgear.meta.i18n as fg_i18n +from flightgear.meta.i18n import XliffFormatHandler PROGNAME = os.path.basename(sys.argv[0]) @@ -45,7 +46,7 @@ def processCommandLine(): parser = argparse.ArgumentParser( usage="""\ -%(prog)s [OPTION ...] ACTION LANGUAGE_CODE... +%(prog)s [OPTION ...] ACTION [LANGUAGE_CODE]... Update FlightGear XLIFF localization files.""", description="""\ 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 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 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 @@ -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 files corresponding to each given LANGUAGE_CODE (i.e., 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="""\ codes of languages to operate on (e.g., fr, en_GB, it, es_ES...)""") @@ -125,11 +133,19 @@ class MarkOrRemoveUnusedAction(enum.Enum): 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): formatHandler = fg_i18n.XliffFormatHandler() masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl - for langCode in params.lang_code: + for langCode in langCodesToActOn(): xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode) transl = formatHandler.readTranslation(xliffPath) @@ -148,7 +164,7 @@ def mergeNewMaster(l10nResPoolMgr): formatHandler = fg_i18n.XliffFormatHandler() masterTransl = l10nResPoolMgr.readFgMasterTranslation().transl - for langCode in params.lang_code: + for langCode in langCodesToActOn(): xliffPath = formatHandler.defaultFilePath(params.transl_dir, langCode) transl = formatHandler.readTranslation(xliffPath) transl.mergeMasterTranslation(masterTransl, logger=logger) diff --git a/python3-flightgear/flightgear/meta/i18n.py b/python3-flightgear/flightgear/meta/i18n.py index 8f94fda..066f71b 100644 --- a/python3-flightgear/flightgear/meta/i18n.py +++ b/python3-flightgear/flightgear/meta/i18n.py @@ -1001,6 +1001,33 @@ class AbstractFormatHandler(metaclass=abc.ABCMeta): baseName = cls.defaultFileBaseName(targetLanguage) 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 def writeTranslation(self, transl, filePath): """Write a Translation instance to a file."""