diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2012-10-24 00:39:26 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2012-10-24 00:39:26 +0400 |
commit | baa4fc68a80bc6042191bdb6d43298a67ed0a005 (patch) | |
tree | 7ec3913038437b1c3aa4a170a4058cf14510f30e | |
parent | 9edec9f0f32768ddd22d39ef3168f1afdf170f56 (diff) |
Separate languages file generation code into its own script (much better this way, so that we can regenerate that file without update whole trunk!).
Also add es_ES (Spanish from Spain) language, as we have a po for it!
3 files changed, 155 insertions, 42 deletions
diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 07dcf213fb1..bfe040e7aa7 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -49,7 +49,7 @@ LANGUAGES = ( ( 6, "Finnish (Suomi)", "fi_FI"), ( 7, "Swedish (Svenska)", "sv_SE"), ( 8, "French (Français)", "fr_FR"), - ( 9, "Spanish (Español)", "es"), + ( 9, "Spanish (Castellano)", "es"), (10, "Catalan (Català)", "ca_AD"), (11, "Czech (Český)", "cs_CZ"), (12, "Portuguese (Português)", "pt_PT"), @@ -79,6 +79,7 @@ LANGUAGES = ( (33, "Hebrew (תירִבְעִ)", "he_IL"), (34, "Estonian (Eestlane)", "et_EE"), (35, "Esperanto (Esperanto)", "eo"), + (36, "Spanish from Spain (Castellano de España)", "es_ES"), ) # Name of language file used by Blender to generate translations' menu. diff --git a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py new file mode 100755 index 00000000000..5eeeb152af7 --- /dev/null +++ b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py @@ -0,0 +1,148 @@ +#!/usr/bin/python3 + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +# <pep8 compliant> + +# Update "languages" text file used by Blender at runtime to build translations menu. + +import os +import sys +import shutil + +try: + import settings + import utils +except: + from . import (settings, utils) + +TRUNK_PO_DIR = settings.TRUNK_PO_DIR +TRUNK_MO_DIR = settings.TRUNK_MO_DIR + +LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES +LANGUAGES = settings.LANGUAGES +LANGUAGES_FILE = settings.LANGUAGES_FILE + +OK = 0 +MISSING = 1 +TOOLOW = 2 +FORBIDDEN = 3 +FLAG_MESSAGES = { + OK: "", + MISSING: "No translation yet!", + TOOLOW: "Not enough advanced to be included...", + FORBIDDEN: "Explicitly forbidden!", +} + +def find_matching_po(languages, stats, forbidden): + """Match languages defined in LANGUAGES setting to relevant po, if possible!""" + ret = [] + for uid, label, org_key in languages: + key = org_key + if key not in stats: + # Try to simplify the key (eg from es_ES to es). + if '_' in org_key: + key = org_key[0:org_key.index('_')] + # For stuff like sr_SR@latin -> sr@latin... + if '@' in org_key: + key = key + org_key[org_key.index('@'):] + if key in stats: + if key in forbidden: + ret.append((stats[key], uid, label, org_key, FORBIDDEN)) + else: + ret.append((stats[key], uid, label, org_key, OK)) + else: + ret.append((0.0, uid, label, org_key, MISSING)) + return ret + +def main(): + import argparse + parser = argparse.ArgumentParser(description="" + "Update 'languages' text file used by Blender at runtime to build translations menu.") + parser.add_argument('-m', '--min_translation', type=int, default=-100, + help="Minimum level of translation, as a percentage " + "(translations below this are commented out in menu).") + parser.add_argument('langs', metavar='ISO_code', nargs='*', + help="Unconditionally exclude those languages from the menu.") + args = parser.parse_args() + + ret = 0 + min_trans = args.min_translation / 100.0 + forbidden = set(args.langs) + # 'DEFAULT' and en_US are always valid, fully-translated "languages"! + stats = {"DEFAULT": 1.0, "en_US": 1.0} + + # Get the "done level" of each po in trunk... + for po in os.listdir(TRUNK_PO_DIR): + if po.endswith(".po") and not po.endswith("_raw.po"): + lang = os.path.basename(po)[:-3] + u1, u2, _stats = utils.parse_messages(os.path.join(TRUNK_PO_DIR, po)) + stats[lang] = _stats["trans_msg"] / _stats["tot_msg"] + + # Generate languages file used by Blender's i18n system. + # First, match all entries in LANGUAGES to a lang in stats, if possible! + stats = find_matching_po(LANGUAGES, stats, forbidden) + limits = sorted(LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True) + idx = 0 + stats = sorted(stats, key=lambda it: it[0], reverse=True) + langs_cats = [[] for i in range(len(limits))] + highest_uid = 0 + for prop, uid, label, key, flag in stats: + if prop < limits[idx][0]: + # Sub-sort languages by iso-codes. + langs_cats[idx].sort(key=lambda it: it[2]) + idx += 1 + if prop < min_trans and flag == OK: + flag = TOOLOW + langs_cats[idx].append((uid, label, key, flag)) + if abs(uid) > highest_uid: + highest_uid = abs(uid) + # Sub-sort last group of languages by iso-codes! + langs_cats[idx].sort(key=lambda it: it[2]) + with open(os.path.join(TRUNK_MO_DIR, LANGUAGES_FILE), 'w', encoding="utf-8") as f: + f.write("# File used by Blender to know which languages (translations) are available, \n") + f.write("# and to generate translation menu.\n") + f.write("#\n") + f.write("# File format:\n") + f.write("# ID:MENULABEL:ISOCODE\n") + f.write("# ID must be unique, except for 0 value (marks categories for menu).\n") + f.write("# Line starting with a # are comments!\n") + f.write("#\n") + f.write("# Automatically generated by bl_i18n_utils/update_languages_menu.py script.\n") + f.write("# Highest ID currently in use: {}\n".format(highest_uid)) + for cat, langs_cat in zip(limits, langs_cats): + f.write("#\n") + # Write "category menu label"... + if langs_cat: + f.write("0:{}:\n".format(cat[1])) + else: + # Do not write the category if it has no language! + f.write("# Void category! #0:{}:\n".format(cat[1])) + # ...and all matching language entries! + for uid, label, key, flag in langs_cat: + if flag == OK: + f.write("{}:{}:{}\n".format(uid, label, key)) + else: + # Non-existing, commented entry! + f.write("# {} #{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key)) + + +if __name__ == "__main__": + print("\n\n *** Running {} *** \n".format(__file__)) + sys.exit(main()) diff --git a/release/scripts/modules/bl_i18n_utils/update_trunk.py b/release/scripts/modules/bl_i18n_utils/update_trunk.py index 859045eafda..9b904ec861a 100755 --- a/release/scripts/modules/bl_i18n_utils/update_trunk.py +++ b/release/scripts/modules/bl_i18n_utils/update_trunk.py @@ -76,8 +76,7 @@ def main(): "* Remove po’s in trunk.\n" "* Copy po’s from branches advanced enough.\n" "* Clean po’s in trunk.\n" - "* Compile po’s in trunk in mo’s, keeping " - "track of those failing.\n" + "* Compile po’s in trunk in mo’s, keeping track of those failing.\n" "* Remove po’s and mo’s (and their dir’s) that " "failed to compile or are no more present in trunk." "* Generate languages file used by Blender's i18n.") @@ -89,8 +88,6 @@ def main(): ret = 0 failed = set() - # 'DEFAULT' and en_US are always valid, fully-translated "languages"! - stats = {"DEFAULT": 1.0, "en_US": 1.0} # Remove po’s in trunk. for po in os.listdir(TRUNK_PO_DIR): @@ -141,44 +138,11 @@ def main(): failed.add(lang) continue - # Yes, I know, it's the third time we parse each po's here. :/ - u1, u2, _stats = utils.parse_messages(os.path.join(BRANCHES_DIR, lang, po)) - stats[lang] = _stats["trans_msg"] / _stats["tot_msg"] - # Generate languages file used by Blender's i18n system. - # First, match all entries in LANGUAGES to a lang in stats, if possible! - stats = find_matching_po(LANGUAGES, stats) - limits = sorted(LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True) - print(limits) - idx = 0 - stats = sorted(stats, key=lambda it: it[0], reverse=True) - print(stats) - langs_cats = [[] for i in range(len(limits))] - highest_uid = 0 - for prop, uid, label, key in stats: - print(key, prop) - if prop < limits[idx][0]: - # Sub-sort languages by iso-codes. - langs_cats[idx].sort(key=lambda it: it[2]) - print(langs_cats) - idx += 1 - langs_cats[idx].append((uid, label, key)) - if abs(uid) > highest_uid: - highest_uid = abs(uid) - # Sub-sort last group of languages by iso-codes! - langs_cats[idx].sort(key=lambda it: it[2]) - with open(os.path.join(TRUNK_MO_DIR, LANGUAGES_FILE), 'w', encoding="utf-8") as f: - f.write("# Highest ID currently in use: {}\n".format(highest_uid)) - for cat, langs_cat in zip(limits, langs_cats): - # Write "category menu label"... - f.write("0:{}:\n".format(cat[1])) - # ...and all matching language entries! - for uid, label, key in langs_cat: - if uid < 0: - # Non-existing, commented entry! - f.write("# No translation yet! #{}:{}:{}\n".format(-uid, label, key)) - else: - f.write("{}:{}:{}\n".format(uid, label, key)) + cmd = [PY3, "./update_languages_menu.py"] + t = subprocess.call(cmd) + if t: + ret = t # Remove failing po’s, mo’s and related dir’s. for lang in failed: |