diff --git a/tools/bin/cldr-plurals.exe b/tools/bin/cldr-plurals.exe new file mode 100644 index 00000000..2e6ae796 Binary files /dev/null and b/tools/bin/cldr-plurals.exe differ diff --git a/tools/bin/iconv.exe b/tools/bin/iconv.exe new file mode 100644 index 00000000..c8ffe893 Binary files /dev/null and b/tools/bin/iconv.exe differ diff --git a/tools/bin/libcharset-1.dll b/tools/bin/libcharset-1.dll new file mode 100644 index 00000000..0540bd78 Binary files /dev/null and b/tools/bin/libcharset-1.dll differ diff --git a/tools/bin/libgcc_s_sjlj-1.dll b/tools/bin/libgcc_s_sjlj-1.dll new file mode 100644 index 00000000..3a609830 Binary files /dev/null and b/tools/bin/libgcc_s_sjlj-1.dll differ diff --git a/tools/bin/libgettextlib-0-19-8-1.dll b/tools/bin/libgettextlib-0-19-8-1.dll new file mode 100644 index 00000000..e7dc62a0 Binary files /dev/null and b/tools/bin/libgettextlib-0-19-8-1.dll differ diff --git a/tools/bin/libgettextpo-0.dll b/tools/bin/libgettextpo-0.dll new file mode 100644 index 00000000..80546de7 Binary files /dev/null and b/tools/bin/libgettextpo-0.dll differ diff --git a/tools/bin/libgettextsrc-0-19-8-1.dll b/tools/bin/libgettextsrc-0-19-8-1.dll new file mode 100644 index 00000000..98fa021d Binary files /dev/null and b/tools/bin/libgettextsrc-0-19-8-1.dll differ diff --git a/tools/bin/libiconv-2.dll b/tools/bin/libiconv-2.dll new file mode 100644 index 00000000..39191a6b Binary files /dev/null and b/tools/bin/libiconv-2.dll differ diff --git a/tools/bin/libintl-8.dll b/tools/bin/libintl-8.dll new file mode 100644 index 00000000..358d0826 Binary files /dev/null and b/tools/bin/libintl-8.dll differ diff --git a/tools/bin/libstdc++-6.dll b/tools/bin/libstdc++-6.dll new file mode 100644 index 00000000..409dd3bf Binary files /dev/null and b/tools/bin/libstdc++-6.dll differ diff --git a/tools/bin/msgattrib.exe b/tools/bin/msgattrib.exe new file mode 100644 index 00000000..d2e155d9 Binary files /dev/null and b/tools/bin/msgattrib.exe differ diff --git a/tools/bin/msgcat.exe b/tools/bin/msgcat.exe new file mode 100644 index 00000000..486182b7 Binary files /dev/null and b/tools/bin/msgcat.exe differ diff --git a/tools/bin/msgcmp.exe b/tools/bin/msgcmp.exe new file mode 100644 index 00000000..8b273256 Binary files /dev/null and b/tools/bin/msgcmp.exe differ diff --git a/tools/bin/msgcomm.exe b/tools/bin/msgcomm.exe new file mode 100644 index 00000000..b78b872c Binary files /dev/null and b/tools/bin/msgcomm.exe differ diff --git a/tools/bin/msgconv.exe b/tools/bin/msgconv.exe new file mode 100644 index 00000000..e7030376 Binary files /dev/null and b/tools/bin/msgconv.exe differ diff --git a/tools/bin/msgen.exe b/tools/bin/msgen.exe new file mode 100644 index 00000000..78ab5b53 Binary files /dev/null and b/tools/bin/msgen.exe differ diff --git a/tools/bin/msgexec.exe b/tools/bin/msgexec.exe new file mode 100644 index 00000000..17cc65fa Binary files /dev/null and b/tools/bin/msgexec.exe differ diff --git a/tools/bin/msgfilter.exe b/tools/bin/msgfilter.exe new file mode 100644 index 00000000..5ba83f7e Binary files /dev/null and b/tools/bin/msgfilter.exe differ diff --git a/tools/bin/msgfmt.exe b/tools/bin/msgfmt.exe new file mode 100644 index 00000000..5680382d Binary files /dev/null and b/tools/bin/msgfmt.exe differ diff --git a/tools/bin/msgfmt.py b/tools/bin/msgfmt.py new file mode 100644 index 00000000..63d52d1f --- /dev/null +++ b/tools/bin/msgfmt.py @@ -0,0 +1,238 @@ +#! /usr/bin/env python3 +# Written by Martin v. Löwis + +"""Generate binary message catalog from textual translation description. + +This program converts a textual Uniforum-style message catalog (.po file) into +a binary GNU catalog (.mo file). This is essentially the same function as the +GNU msgfmt program, however, it is a simpler implementation. + +Usage: msgfmt.py [OPTIONS] filename.po + +Options: + -o file + --output-file=file + Specify the output file to write to. If omitted, output will go to a + file named filename.mo (based off the input file name). + + -h + --help + Print this message and exit. + + -V + --version + Display version information and exit. +""" + +import os +import sys +import ast +import getopt +import struct +import array +from email.parser import HeaderParser + +__version__ = "1.1" + +MESSAGES = {} + + + +def usage(code, msg=''): + print(__doc__, file=sys.stderr) + if msg: + print(msg, file=sys.stderr) + sys.exit(code) + + + +def add(id, str, fuzzy): + "Add a non-fuzzy translation to the dictionary." + global MESSAGES + if not fuzzy and str: + MESSAGES[id] = str + + + +def generate(): + "Return the generated output." + global MESSAGES + # the keys are sorted in the .mo file + keys = sorted(MESSAGES.keys()) + offsets = [] + ids = strs = b'' + for id in keys: + # For each string, we need size and file offset. Each string is NUL + # terminated; the NUL does not count into the size. + offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id]))) + ids += id + b'\0' + strs += MESSAGES[id] + b'\0' + output = '' + # The header is 7 32-bit unsigned integers. We don't use hash tables, so + # the keys start right after the index tables. + # translated string. + keystart = 7*4+16*len(keys) + # and the values start after the keys + valuestart = keystart + len(ids) + koffsets = [] + voffsets = [] + # The string table first has the list of keys, then the list of values. + # Each entry has first the size of the string, then the file offset. + for o1, l1, o2, l2 in offsets: + koffsets += [l1, o1+keystart] + voffsets += [l2, o2+valuestart] + offsets = koffsets + voffsets + output = struct.pack("Iiiiiii", + 0x950412de, # Magic + 0, # Version + len(keys), # # of entries + 7*4, # start of key index + 7*4+len(keys)*8, # start of value index + 0, 0) # size and offset of hash table + output += array.array("i", offsets).tobytes() + output += ids + output += strs + return output + + + +def make(filename, outfile): + ID = 1 + STR = 2 + + # Compute .mo name from .po name and arguments + if filename.endswith('.po'): + infile = filename + else: + infile = filename + '.po' + if outfile is None: + outfile = os.path.splitext(infile)[0] + '.mo' + + try: + with open(infile, 'rb') as f: + lines = f.readlines() + except IOError as msg: + print(msg, file=sys.stderr) + sys.exit(1) + + section = None + fuzzy = 0 + + # Start off assuming Latin-1, so everything decodes without failure, + # until we know the exact encoding + encoding = 'latin-1' + + # Parse the catalog + lno = 0 + for l in lines: + l = l.decode(encoding) + lno += 1 + # If we get a comment line after a msgstr, this is a new entry + if l[0] == '#' and section == STR: + add(msgid, msgstr, fuzzy) + section = None + fuzzy = 0 + # Record a fuzzy mark + if l[:2] == '#,' and 'fuzzy' in l: + fuzzy = 1 + # Skip comments + if l[0] == '#': + continue + # Now we are in a msgid section, output previous section + if l.startswith('msgid') and not l.startswith('msgid_plural'): + if section == STR: + add(msgid, msgstr, fuzzy) + if not msgid: + # See whether there is an encoding declaration + p = HeaderParser() + charset = p.parsestr(msgstr.decode(encoding)).get_content_charset() + if charset: + encoding = charset + section = ID + l = l[5:] + msgid = msgstr = b'' + is_plural = False + # This is a message with plural forms + elif l.startswith('msgid_plural'): + if section != ID: + print('msgid_plural not preceded by msgid on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[12:] + msgid += b'\0' # separator of singular and plural + is_plural = True + # Now we are in a msgstr section + elif l.startswith('msgstr'): + section = STR + if l.startswith('msgstr['): + if not is_plural: + print('plural without msgid_plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l.split(']', 1)[1] + if msgstr: + msgstr += b'\0' # Separator of the various plural forms + else: + if is_plural: + print('indexed msgstr required for plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[6:] + # Skip empty lines + l = l.strip() + if not l: + continue + l = ast.literal_eval(l) + if section == ID: + msgid += l.encode(encoding) + elif section == STR: + msgstr += l.encode(encoding) + else: + print('Syntax error on %s:%d' % (infile, lno), \ + 'before:', file=sys.stderr) + print(l, file=sys.stderr) + sys.exit(1) + # Add last entry + if section == STR: + add(msgid, msgstr, fuzzy) + + # Compute output + output = generate() + + try: + with open(outfile,"wb") as f: + f.write(output) + except IOError as msg: + print(msg, file=sys.stderr) + + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hVo:', + ['help', 'version', 'output-file=']) + except getopt.error as msg: + usage(1, msg) + + outfile = None + # parse options + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-V', '--version'): + print("msgfmt.py", __version__) + sys.exit(0) + elif opt in ('-o', '--output-file'): + outfile = arg + # do it + if not args: + print('No input file given', file=sys.stderr) + print("Try `msgfmt --help' for more information.", file=sys.stderr) + return + + for filename in args: + make(filename, outfile) + + +if __name__ == '__main__': + main() diff --git a/tools/bin/msggrep.exe b/tools/bin/msggrep.exe new file mode 100644 index 00000000..2a55d77a Binary files /dev/null and b/tools/bin/msggrep.exe differ diff --git a/tools/bin/msginit.exe b/tools/bin/msginit.exe new file mode 100644 index 00000000..bccf3c47 Binary files /dev/null and b/tools/bin/msginit.exe differ diff --git a/tools/bin/msgmerge.exe b/tools/bin/msgmerge.exe new file mode 100644 index 00000000..87e06105 Binary files /dev/null and b/tools/bin/msgmerge.exe differ diff --git a/tools/bin/msgunfmt.exe b/tools/bin/msgunfmt.exe new file mode 100644 index 00000000..cf748565 Binary files /dev/null and b/tools/bin/msgunfmt.exe differ diff --git a/tools/bin/msguniq.exe b/tools/bin/msguniq.exe new file mode 100644 index 00000000..7b0e6124 Binary files /dev/null and b/tools/bin/msguniq.exe differ diff --git a/tools/bin/recode-sr-latin.exe b/tools/bin/recode-sr-latin.exe new file mode 100644 index 00000000..9b98e13c Binary files /dev/null and b/tools/bin/recode-sr-latin.exe differ diff --git a/tools/bin/xgettext.exe b/tools/bin/xgettext.exe new file mode 100644 index 00000000..377d1fb5 Binary files /dev/null and b/tools/bin/xgettext.exe differ diff --git a/tools/buildTranslation.py b/tools/buildTranslation.py new file mode 100644 index 00000000..2dd0267f --- /dev/null +++ b/tools/buildTranslation.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +#Translation building Tool +#Copyright (C) 2019 Yukio Nozawa +#Copyright (C) 2020-2021 guredora + +import sys +import os +import subprocess +import glob +import shutil + +if not os.path.exists("src/locales"): + print("Error: no locale folder found. Your working directory must be the root of the project. You shouldn't cd to tools and run this script.") + sys.exit() +if not os.path.exists("tools/bin/msgfmt.exe"): + print("Error: msgfmt is missing.") + sys.exit() + +langs=[] +for elem in glob.glob("src/locales/*"): + if os.path.isdir(elem): langs.append(os.path.basename(elem)) + +print("Detected languages:") +for l in langs: + print(l) + +print("Building mo files") +for l in langs: + subprocess.call(("tools\\bin\\msgfmt.exe -o src/locales/%s/LC_MESSAGES/twblue.mo src/locales/%s/LC_MESSAGES/twblue.po" % (l,l)).split()) +print("Done") +sys.exit(0) diff --git a/tools/updateTranslation.py b/tools/updateTranslation.py new file mode 100644 index 00000000..138c3fa9 --- /dev/null +++ b/tools/updateTranslation.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +#Translation update Tool +#Copyright (C) 2019 Yukio Nozawa +#Copyright (C) 2020-2021 guredora + +import sys +import os +import subprocess +import glob +import shutil + +if not os.path.exists("src/locales"): + print("Error: no locale folder found. Your working directory must be the root of the project. You shouldn't cd to tools and run this script.") + sys.exit() +if not os.path.exists("tools/bin/xgettext.exe") or not os.path.exists("tools/bin/msgmerge.exe"): + print("Error: xgettext or msgmerge is missing.") + sys.exit() + +BASE_LOCALE_DIR = "src/locales" +langs=[] +for elem in glob.glob("src/locales/*"): + if os.path.isdir(elem): langs.append(os.path.basename(elem)) + +print("Detected languages:") +for l in langs: + print(l) +files = glob.glob("src/*.py") +files.extend(glob.glob("src/**/*.py", recursive=True)) +print("Detected files:") +print("Detected files: %d" % len(files)) +print("Updating the base dictionary(pot)") +subprocess.call(("tools/bin/xgettext.exe -p %s -d twblue --from-code utf-8 --package-name=twblue %s" % (BASE_LOCALE_DIR, " ".join(files))).split()) +for l in langs: + lang_file = "%s/%s/LC_MESSAGES/twblue.po" % (BASE_LOCALE_DIR, l) + if os.path.exists(lang_file): + print("Merging %s" % l) + subprocess.call(("tools/bin/msgmerge.exe -U %s %s/twblue.po" % (lang_file, BASE_LOCALE_DIR)).split()) + else: + print("Creating %s" % l) + if not os.path.exists("%s/%s/LC_MESSAGES" % (BASE_LOCALE_DIR, l)): + print("Creating LC_MESSAGES") + os.mkdir("%s/%s/LC_MESSAGES" % (BASE_LOCALE_DIR, l)) + shutil.copyfile("%s/twblue.po"% BASE_LOCALE_DIR, lang_file) +print("Done") +sys.exit(0)