init
This commit is contained in:
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import twlang
|
||||
|
||||
os.chdir(os.path.dirname(__file__) + "/../..")
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
langs = sys.argv[1:]
|
||||
else:
|
||||
langs = twlang.languages()
|
||||
local = twlang.localizes()
|
||||
table = []
|
||||
for lang in langs:
|
||||
trans = twlang.translations(lang)
|
||||
empty = 0
|
||||
supported = 0
|
||||
unused = 0
|
||||
for tran, (_, expr, _) in trans.items():
|
||||
if not expr:
|
||||
empty += 1
|
||||
else:
|
||||
if tran in local:
|
||||
supported += 1
|
||||
else:
|
||||
unused += 1
|
||||
table.append([lang, len(trans), empty, len(local)-supported, unused])
|
||||
|
||||
table.sort(key=lambda l: l[3])
|
||||
table = [["filename", "total", "empty", "missing", "unused"]] + table
|
||||
s = [[str(e) for e in row] for row in table]
|
||||
lens = [max(map(len, col)) for col in zip(*s)]
|
||||
fmt = " ".join(f"{{:{x}}}" for x in lens)
|
||||
t = [fmt.format(*row) for row in s]
|
||||
print("\n".join(t))
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
|
||||
import twlang
|
||||
|
||||
def copy_fix(infile, delete_unused, append_missing, delete_empty):
|
||||
with open(infile, encoding="utf-8") as f:
|
||||
content = f.readlines()
|
||||
trans = twlang.translations(infile)
|
||||
if delete_unused or append_missing:
|
||||
local = twlang.localizes()
|
||||
if append_missing:
|
||||
supported = []
|
||||
for tran, (start, expr, end) in trans.items():
|
||||
if delete_unused and tran not in local:
|
||||
content[start:end] = [None]*(end-start)
|
||||
if append_missing and tran in local:
|
||||
if expr or (not expr and delete_empty):
|
||||
supported.append(local.index(tran))
|
||||
else:
|
||||
content[start:end] = [None]*(end-start)
|
||||
if delete_empty and not expr:
|
||||
content[start:end] = [None]*(end-start)
|
||||
content = [line for line in content if line is not None]
|
||||
if append_missing:
|
||||
missing = [index for index in range(len(local)) if index not in supported]
|
||||
if missing:
|
||||
if content[-1] != "\n":
|
||||
content.append("\n")
|
||||
for miss in missing:
|
||||
if local[miss][1] != "":
|
||||
content.append("["+local[miss][1]+"]\n")
|
||||
content.append(local[miss][0]+"\n== \n\n")
|
||||
content[-1] = content[-1][:-1]
|
||||
return "".join(content)
|
||||
|
||||
def main(argv):
|
||||
os.chdir(os.path.dirname(__file__) + "/../..")
|
||||
|
||||
if len(argv) < 3:
|
||||
print("usage: python copy_fix.py <infile> <outfile> [--delete-unused] [--append-missing] [--delete-empty]")
|
||||
sys.exit()
|
||||
infile = argv[1]
|
||||
outfile = argv[2]
|
||||
args = argv[3:]
|
||||
delete_unused = False
|
||||
append_missing = False
|
||||
delete_empty = False
|
||||
for arg in args:
|
||||
if arg == "--delete-unused":
|
||||
delete_unused = True
|
||||
elif arg == "--append-missing":
|
||||
append_missing = True
|
||||
elif arg == "--delete-empty":
|
||||
delete_empty = True
|
||||
else:
|
||||
print("No such argument '"+arg+"'.")
|
||||
sys.exit()
|
||||
|
||||
content = copy_fix(infile, delete_unused, append_missing, delete_empty)
|
||||
|
||||
with open(outfile, "w", encoding="utf-8") as f:
|
||||
f.write("".join(content))
|
||||
print("Successfully created '" + outfile + "'.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import twlang
|
||||
|
||||
os.chdir(os.path.dirname(__file__) + "/../..")
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: python find_unchanged.py <file>")
|
||||
sys.exit()
|
||||
infile = sys.argv[1]
|
||||
|
||||
trans = twlang.translations(infile)
|
||||
for tran, (_, expr, _) in trans.items():
|
||||
if tran == expr:
|
||||
print(tran)
|
||||
@@ -0,0 +1,45 @@
|
||||
Teeworlds language scripts by timakro
|
||||
|
||||
These scripts can help you to improve the language files. This is a short tutorial
|
||||
about how to use the scripts.
|
||||
|
||||
|
||||
You can start by analyzing the current languages using analyze.py
|
||||
$ ./analyze.py
|
||||
|
||||
analyze.py outputs several columns. The column 'total' is the number of
|
||||
translations in the file. 'empty' is the number of untranslated phrases in the
|
||||
file. The 2nd and 3rd columns are calculated by looking into the source. The script
|
||||
searches through the source for all phrases. 'missing' is the number of phrases in
|
||||
the source but not in the file. 'unused' is the number of phrases in the file but
|
||||
not in the source.
|
||||
|
||||
|
||||
To update a language you should first copy it using the copy_fix.py script.
|
||||
$ ./copy_fix.py ../spanish.txt newspanish.txt --delete-unused --append-missing
|
||||
|
||||
Then you can start to modify newspanish.txt. Search in the file for the following
|
||||
line and remove it:
|
||||
##### generated by copy_fix.py, please translate this #####
|
||||
|
||||
Every phrase below this line should be empty. Now you can fill in the translations
|
||||
you know. It's also okay to write just the same phrase as in english for words like
|
||||
'Hookcollision' or 'Screenshot'. If you don't know how to translate something just
|
||||
remove it.
|
||||
|
||||
That's all, you improved the translation. If you want you can add your name at the
|
||||
start of the file. Now you can move the file back to its original location.
|
||||
$ mv newspanish.txt ../spanish.txt
|
||||
|
||||
|
||||
Often people know better phrases for translations where the english phrase was just
|
||||
copied. To find these you can use find_unchanged.py
|
||||
$ ./find_unchanged.py ../spanish.txt
|
||||
|
||||
To update all languages:
|
||||
|
||||
$ ./update_all.py
|
||||
|
||||
To get a statistic of how complete the translation is:
|
||||
|
||||
$ for i in data/languages/*.txt; do COVERED=$(cat $i|grep "^== "|grep -v "^== $"|wc -l); TOTAL=$(cat $i|grep "^== "|wc -l); [ "${i:t}" != "license.txt" ] && [ "${i:t}" != "index.txt" ] && echo "$(($COVERED*100/$TOTAL))% ${i:r:t}"; done | sort -n -r
|
||||
@@ -0,0 +1,106 @@
|
||||
import os
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
class LanguageDecodeError(Exception):
|
||||
def __init__(self, message, filename, line):
|
||||
error = f"File \"{filename}\", line {line+1}: {message}"
|
||||
super().__init__(error)
|
||||
|
||||
|
||||
# Taken from https://stackoverflow.com/questions/30011379/how-can-i-parse-a-c-format-string-in-python
|
||||
cfmt = r'''\
|
||||
( # start of capture group 1
|
||||
% # literal "%"
|
||||
(?: # first option
|
||||
(?:[-+0 #]{0,5}) # optional flags
|
||||
(?:\d+|\*)? # width
|
||||
(?:\.(?:\d+|\*))? # precision
|
||||
(?:h|l|ll|w|I|I32|I64)? # size
|
||||
[cCdiouxXeEfgGaAnpsSZ] # type
|
||||
) | # OR
|
||||
%%) # literal "%%"
|
||||
'''
|
||||
|
||||
|
||||
def decode(fileobj, elements_per_key):
|
||||
data = {}
|
||||
current_context = ""
|
||||
current_key = None
|
||||
index = -1
|
||||
for index, line in enumerate(fileobj):
|
||||
line = line.encode("utf-8").decode("utf-8-sig")
|
||||
line = line[:-1]
|
||||
if line and line[-1] == "\r":
|
||||
line = line[:-1]
|
||||
if not line or line[:1] == "#":
|
||||
current_context = ""
|
||||
continue
|
||||
|
||||
if line[0] == "[":
|
||||
if line[-1] != "]":
|
||||
raise LanguageDecodeError("Invalid context string", fileobj.name, index)
|
||||
current_context = line[1:-1]
|
||||
elif line[:3] == "== ":
|
||||
if len(data[current_key]) >= 1+elements_per_key:
|
||||
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
|
||||
if current_key:
|
||||
original = current_key[0] # pylint: disable=unsubscriptable-object
|
||||
translation = line[3:]
|
||||
if translation and [m.group(1) for m in re.finditer(cfmt, original, flags=re.X)] != [m.group(1) for m in re.finditer(cfmt, translation, flags=re.X)]:
|
||||
raise LanguageDecodeError("Non-matching formatting string", fileobj.name, index)
|
||||
data[current_key].extend([translation])
|
||||
else:
|
||||
raise LanguageDecodeError("Element before key given", fileobj.name, index)
|
||||
else:
|
||||
if current_key:
|
||||
if len(data[current_key]) != 1+elements_per_key:
|
||||
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
|
||||
data[current_key].append(index)
|
||||
if line in data:
|
||||
raise LanguageDecodeError("Key defined multiple times: " + line, fileobj.name, index)
|
||||
data[(line, current_context)] = [index - 1 if current_context else index]
|
||||
current_key = (line, current_context)
|
||||
if len(data[current_key]) != 1+elements_per_key:
|
||||
raise LanguageDecodeError("Wrong number of elements per key", fileobj.name, index)
|
||||
data[current_key].append(index+1)
|
||||
new_data = {}
|
||||
for key, value in data.items():
|
||||
if key[0]:
|
||||
new_data[key] = value
|
||||
return new_data
|
||||
|
||||
|
||||
def check_file(path):
|
||||
with open(path, encoding="utf-8") as fileobj:
|
||||
matches = re.findall(r"(Localize|Localizable)\s*\(\s*\"([^\"]+)\"(?:\s*,\s*\"([^\"]+)\")?\s*\)", fileobj.read())
|
||||
return matches
|
||||
|
||||
|
||||
def check_folder(path):
|
||||
englishlist = OrderedDict()
|
||||
for path2, dirs, files in os.walk(path):
|
||||
dirs.sort()
|
||||
for f in sorted(files):
|
||||
if not any(f.endswith(x) for x in [".cpp", ".c", ".h"]):
|
||||
continue
|
||||
for sentence in check_file(os.path.join(path2, f)):
|
||||
englishlist[sentence[1:]] = None
|
||||
return englishlist
|
||||
|
||||
|
||||
def languages():
|
||||
with open("data/languages/index.txt", encoding="utf-8") as f:
|
||||
index = decode(f, 3)
|
||||
langs = {"data/languages/"+key[0]+".txt" : [key[0]]+elements for key, elements in index.items()}
|
||||
return langs
|
||||
|
||||
|
||||
def translations(filename):
|
||||
with open(filename, encoding="utf-8") as f:
|
||||
return decode(f, 1)
|
||||
|
||||
|
||||
def localizes():
|
||||
englishlist = list(check_folder("src"))
|
||||
return englishlist
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from copy_fix import copy_fix
|
||||
import twlang
|
||||
|
||||
os.chdir(os.path.dirname(__file__) + "/../..")
|
||||
|
||||
for lang in twlang.languages():
|
||||
content = copy_fix(lang, delete_unused=True, append_missing=True, delete_empty=False)
|
||||
with open(lang, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
Reference in New Issue
Block a user