#!/usr/bin/python3 -OO # -*- coding: utf-8 -*- # Copyright 2010-2019 The SABnzbd-Team # # 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. """ make_mo - Compile PO files to MO files """ import glob import os import re import sys import gettext import subprocess PO_DIR = "po/main" POE_DIR = "po/email" PON_DIR = "po/nsis" MO_DIR = "locale" EMAIL_DIR = "email" MO_LOCALE = "/LC_MESSAGES" DOMAIN = "SABnzbd" DOMAIN_E = "SABemail" DOMAIN_N = "SABnsis" LANG_MARKER = "language.txt" NSIS = "NSIS_Installer.nsi" LanguageTable = { "aa": ("Afar", "Afaraf"), "af": ("Afrikaans", "Afrikaans"), "ak": ("Akan", "Akan"), "sq": ("Albanian", "Shqip"), "an": ("Aragonese", "Aragonés"), "ae": ("Avestan", "Avesta"), "ay": ("Aymara", "Aymararu"), "bm": ("Bambara", "Bamanankan"), "eu": ("Basque", "Euskara"), "bi": ("Bislama", "Bislama"), "bs": ("Bosnian", "Bosanskijezik"), "br": ("Breton", "Brezhoneg"), "ca": ("Catalan", "Català"), "ch": ("Chamorro", "Chamoru"), "kw": ("Cornish", "Kernewek"), "co": ("Corsican", "Corsu"), "hr": ("Croatian", "Hrvatski"), "cs": ("Czech", "Cesky, ceština"), "da": ("Danish", "Dansk"), "nl": ("Dutch", "Nederlands"), "en": ("English", "English"), "eo": ("Esperanto", "Esperanto"), "et": ("Estonian", "Eesti"), "fo": ("Faroese", "Føroyskt"), "fj": ("Fijian", "Vosa Vakaviti"), "fi": ("Finnish", "Suomi"), "fr": ("French", "Français"), "gl": ("Galician", "Galego"), "de": ("German", "Deutsch"), "he": ("Hebrew", "עִבְרִית‎"), "hz": ("Herero", "Otjiherero"), "ho": ("Hiri Motu", "Hiri Motu"), "hu": ("Hungarian", "Magyar"), "id": ("Indonesian", "Bahasa Indonesia"), "ga": ("Irish", "Gaeilge"), "io": ("Ido", "Ido"), "is": ("Icelandic", "Íslenska"), "it": ("Italian", "Italiano"), "jv": ("Javanese", "BasaJawa"), "rw": ("Kinyarwanda", "Ikinyarwanda"), "kg": ("Kongo", "KiKongo"), "kj": ("Kwanyama", "Kuanyama"), "la": ("Latin", "Lingua latina"), "lb": ("Luxembourgish", "Lëtzebuergesch"), "lg": ("Luganda", "Luganda"), "li": ("Limburgish", "Limburgs"), "ln": ("Lingala", "Lingála"), "lt": ("Lithuanian", "Lietuviukalba"), "lv": ("Latvian", "Latviešuvaloda"), "gv": ("Manx", "Gaelg"), "mg": ("Malagasy", "Malagasy fiteny"), "mt": ("Maltese", "Malti"), "nb": ("Norwegian", "Norsk"), # Bokmål "nn": ("Norwegian", "Norsk"), # Nynorsk "no": ("Norwegian", "Norsk"), "oc": ("Occitan", "Occitan"), "om": ("Oromo", "Afaan Oromoo"), "pl": ("Polish", "Polski"), "pt": ("Portuguese", "Português"), "pt_BR": ("PortugueseBR", "Português, Brasil"), # NSIS uses "PortugueseBR" "rm": ("Romansh", "Rumantsch grischun"), "rn": ("Kirundi", "kiRundi"), "ro": ("Romanian", "Româna"), "sc": ("Sardinian", "Sardu"), "se": ("Northern Sami", "Davvisámegiella"), "sm": ("Samoan", "Gagana fa'a Samoa"), "gd": ("Gaelic", "Gàidhlig"), "ru": ("Russian", "русский язык"), "sr": ("Serbian", "српски"), "sn": ("Shona", "Chi Shona"), "sk": ("Slovak", "Slovencina"), "sl": ("Slovene", "Slovenšcina"), "st": ("Southern Sotho", "Sesotho"), "es": ("Spanish", "Español, castellano"), # NSIS cannot handle "Spanish Castilian" "su": ("Sundanese", "Basa Sunda"), "sw": ("Swahili", "Kiswahili"), "ss": ("Swati", "SiSwati"), "sv": ("Swedish", "Svenska"), "tn": ("Tswana", "Setswana"), "to": ("Tonga (Tonga Islands)", "faka Tonga"), "tr": ("Turkish", "Türkçe"), "ts": ("Tsonga", "Xitsonga"), "tw": ("Twi", "Twi"), "ty": ("Tahitian", "Reo Tahiti"), "wa": ("Walloon", "Walon"), "cy": ("Welsh", "Cymraeg"), "wo": ("Wolof", "Wollof"), "fy": ("Western Frisian", "Frysk"), "xh": ("Xhosa", "isi Xhosa"), "yo": ("Yoruba", "Yorùbá"), "zu": ("Zulu", "isi Zulu"), "zh_CN": ("SimpChinese", "简体中文"), } # Filter for retrieving readable language from PO file RE_LANG = re.compile(r'"Language-Description:\s([^"]+)\\n') def run(cmd): """ Run system command, returns exit-code and stdout """ try: txt = subprocess.check_output(cmd, universal_newlines=True) ret = 0 except subprocess.CalledProcessError as e: txt = e.output ret = e.returncode return ret, txt def process_po_folder(domain, folder, extra=""): """ Process each PO file in folder """ result = True for fname in glob.glob(os.path.join(folder, "*.po")): basename = os.path.split(fname)[1] name = os.path.splitext(basename)[0] mo_path = os.path.normpath("%s/%s%s" % (MO_DIR, name, MO_LOCALE)) mo_name = "%s.mo" % domain if not os.path.exists(mo_path): os.makedirs(mo_path) # Create the MO file mo_file = os.path.join(mo_path, mo_name) print(("Compile %s" % mo_file)) if extra: cmd = TOOL + [extra, "-o", mo_file, fname] else: cmd = TOOL + ["-o", mo_file, fname] ret, output = run(cmd) if ret != 0: print(("\nMissing %s. Please install this package first." % TOOL)) exit(1) if "WARNING:" in output: print(output) result = False return result def remove_mo_files(): """ Remove MO files in locale """ for root, dirs, files in os.walk(MO_DIR, topdown=False): for f in files: if not f.startswith(DOMAIN): os.remove(os.path.join(root, f)) def translate_tmpl(prefix, lng): """ Translate template 'prefix' into language 'lng' """ # Open the original file with open(EMAIL_DIR + "/%s-en.tmpl" % prefix, "r", encoding="utf-8") as src: data = src.read() # Run through translator data = _(data) # Save the translation with open("email/%s-%s.tmpl" % (prefix, lng), "w", encoding="utf-8") as fp: if not -1 < data.find("UTF-8") < 30: fp.write("#encoding UTF-8\n") fp.write(data) def make_templates(): """ Create email templates """ if not os.path.exists("email"): os.makedirs("email") for path in glob.glob(os.path.join(MO_DIR, "*")): lng = os.path.split(path)[1] if lng != "en" and os.path.exists(os.path.join(POE_DIR, lng + ".po")): print(("Create email template for %s" % lng)) trans = gettext.translation(DOMAIN_E, MO_DIR, [lng], fallback=False, codeset="latin-1") trans.install(names=["lgettext"]) translate_tmpl("email", lng) translate_tmpl("rss", lng) translate_tmpl("badfetch", lng) mo_path = os.path.normpath("%s/%s%s/%s.mo" % (MO_DIR, path, MO_LOCALE, DOMAIN_E)) if os.path.exists(mo_path): os.remove(mo_path) def patch_nsis(): """ Patch translation into the NSIS script """ RE_NSIS = re.compile(r'^(\s*LangString\s+)(\w+)(\s+\$\{LANG_)(\w+)\}\s+(".*)', re.I) languages = [os.path.split(path)[1] for path in glob.glob(os.path.join(MO_DIR, "*"))] src = open(NSIS, "r") new = [] for line in src: m = RE_NSIS.search(line) if m: leader = m.group(1) item = m.group(2) rest = m.group(3) langname = m.group(4).upper() text = m.group(5).strip('"\n') if langname == "ENGLISH": # Write back old content new.append(line) # Replace silly $\ construction with just a \ text = text.replace('$\\"', '"').replace("$\\", "\\") for lcode in languages: lng = LanguageTable.get(lcode) if lng and lcode != "en": lng = lng[0].decode("utf-8").encode("latin-1").upper() if item == "MsgLangCode": trans = lcode else: trans = gettext.translation(DOMAIN_N, MO_DIR, [lcode], fallback=False, codeset="latin-1") trans.install(names=["lgettext"]) trans = trans.replace("\r", "").replace("\n", "\\r\\n") trans = trans.replace("\\", "$\\").replace('"', '$\\"') line = '%s%s%s%s} "%s"\n' % (leader, item, rest, lng, trans) new.append(line) elif lng is None: print("Warning: unsupported language %s (%s), add to table in this script" % (langname, lcode)) else: new.append(line) src.close() dst = open(NSIS + ".tmp", "w") for line in new: dst.write(line) dst.close() # ---------------------------------------------------------------------------- # Determine location of MsgFmt tool path, py = os.path.split(sys.argv[0]) tl = os.path.abspath(os.path.normpath(os.path.join(path, "msgfmt.py"))) if os.path.exists(tl): if os.name == "nt": TOOL = [sys.executable, tl] else: TOOL = [tl] result = True if len(sys.argv) > 1 and sys.argv[1] == "all": print("NSIS MO file") result = result and process_po_folder(DOMAIN_N, PON_DIR) print("Patch NSIS script") patch_nsis() print("Email MO files") result = result and process_po_folder(DOMAIN_E, POE_DIR) print("Create email templates from MO files") make_templates() print("Main program MO files") # -n option added to remove all newlines from the translations result = result and process_po_folder(DOMAIN, PO_DIR, "-n") print("Remove temporary templates") remove_mo_files() print() if result: exit(0) else: print("WARNINGS present!") exit(1)