WTS/game/scripts/utility/translation.rpy
LoafyLemon 5c952fe7da Translation support - Part 1
* Added language switch option (WIP)
* Fixed translation generation cache cleanup
* Fixed python strings being untranslatable (partially)
2022-10-31 20:35:00 +00:00

212 lines
6.9 KiB
Plaintext

rpy python 3
init python in cli:
import os
import collections
import itertools
from renpy.translation import quote_unicode
from renpy.parser import elide_filename
tl_file_cache = {}
def open_tl_file(fn, mode):
if fn in tl_file_cache:
f = tl_file_cache[fn]
if f.mode == mode:
return f
# elif not f.closed:
# # PY 2 only
# f.close()
if not os.path.exists(fn):
dn = os.path.dirname(fn)
try:
os.makedirs(dn)
except Exception:
pass
f = open(fn, mode, encoding="utf-8")
f.write(u"\ufeff")
else:
f = open(fn, mode, encoding="utf-8")
tl_file_cache[fn] = f
return f
def scan_strings(strings, min_priority=0, max_priority=299, common_only=False):
strings.sort(key=lambda s : s.sort_key)
rv = [ ]
seen = set()
for s in strings:
if s.priority < min_priority:
continue
if s.priority > max_priority:
continue
if common_only and not s.common:
continue
if s.text in seen:
continue
seen.add(s.text)
rv.append(s)
return rv
def write_strings(language, strings):
stl = renpy.game.script.translator.strings[language]
stringfiles = collections.defaultdict(list)
seen = set()
nstrings = len(strings)-1
for i, s in enumerate(strings):
n = round(float(i)/(nstrings)*100)
print("\rGenerating strings for {} ... Total progress:{} % ... Stage 2/2".format(language, n), end="")
tlfn = renpy.translation.generation.translation_filename(s)
if tlfn is None:
continue
if s.text in seen:
continue
seen.add(s.text)
if language == "None" and tlfn == "common.rpy":
tlfn = "common.rpym"
stringfiles[tlfn].append(s)
for tlfn, sl in list(stringfiles.items()):
tlfn = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, tlfn)
f = open_tl_file(tlfn, mode="w")
f.write(u"translate {} strings:\n".format(language))
f.write(u"\n")
for s in sl:
original = s.text
translation = stl.translate(s.text) # Keeps translated strings
f.write(u" # {}:{}\n".format(elide_filename(s.filename), s.line))
f.write(u" old \"{}\"\n".format(quote_unicode(original)))
f.write(u" new \"{}\"\n".format(quote_unicode(translation)))
f.write(u"\n")
def retranslate():
translator = renpy.game.script.translator
generation = renpy.translation.generation
scanstrings = renpy.translation.scanstrings
parser = renpy.arguments.ArgumentParser()
parser.add_argument("--rebuild", action="store_true", help="Rebuilds the translation pointers and adds missing entries.")
parser.add_argument("--empty", action="store_true", help="When combined with rebuild parameter, it will insert an empty string into added entires. Does nothing on its own.")
parser.add_argument("--clean", action="store_true", help="Removes translation files that are no longer present within the game files.")
parser.add_argument("--dry", action="store_true", help="Simulates the removal of translation files that are no longer present within the game files.")
parser.add_argument("--include-mods", action="store_true", help="Include mod files when generating translations.")
args = parser.parse_args()
scripts = generation.translate_list_files()
if not args.include_mods:
mods_dir = os.path.join(renpy.config.gamedir, "mods")
scripts = [f for f in scripts if not f.startswith(mods_dir)]
strings = []
nscripts = len(scripts)-1
for i, filepath in enumerate(scripts):
n = round(float(i)/(nscripts)*100)
for language in translator.languages:
print("\rGenerating dialogues for {} ... Total progress:{} % ... Stage 1/2".format(language, n), end="")
for _, trans in translator.file_translates[filepath]:
trans_new = translator.language_translates.get((trans.identifier, language))
filter = generation.null_filter
if trans_new is None:
if not args.rebuild:
continue
trans_new = trans
if args.empty:
filter = generation.empty_filter
if hasattr(trans, "alternate") and (trans.alternate, language) in translator.language_translates:
continue
fp = os.path.relpath(filepath, renpy.config.gamedir)
fp = os.path.join(renpy.config.gamedir, renpy.config.tl_directory, language, fp)
f = open_tl_file(fp, mode="w")
f.write(u"# {}:{}\n".format(trans.filename, trans.linenumber))
f.write(u"translate {} {}:\n".format(language, trans.identifier.replace(".", "_")))
f.write(u"\n")
for n in trans.block:
f.write(u" # " + n.get_code() + "\n")
for n in trans_new.block:
f.write(u" " + n.get_code(filter) + "\n")
f.write(u"\n")
strings.extend(scanstrings.scan_strings(filepath))
strings = scan_strings(strings)
for language in translator.languages:
write_strings(language, strings)
if args.clean:
translations = [f for f in renpy.list_files() if f.startswith(renpy.config.tl_directory) and f.endswith((".rpy", ".rpym"))]
for filepath in translations:
fn = os.path.basename(filepath)
fp = os.path.relpath(filepath, os.path.join(renpy.config.tl_directory, language))
fp = os.path.join(renpy.config.gamedir, fp)
if fp not in scripts:
if fn == "common.rpy":
continue
if filepath in tl_file_cache:
f = tl_file_cache.pop(tl_file_cache)
f.close()
if args.dry:
print("Removal required: {}".format(filepath))
else:
os.unlink(filepath)
os.unlink(filepath + "c")
for f in list(tl_file_cache.values()):
f.close()
tl_file_cache.clear()
return False
renpy.arguments.register_command("retranslate", retranslate)