forked from SilverStudioGames/WTS
Gouvernathor
36582d0f9c
some uses of str.format remain, but converting them would be more trouble than it's worth (cherry picked from commit f17cffa3ec5329988a58c76f8fa4f3fe4846a6fc)
212 lines
6.8 KiB
Plaintext
212 lines
6.8 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(f"\rGenerating strings for {language} ... Total progress:{n} % ... Stage 2/2", 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(f"translate {language} strings:\n")
|
|
f.write("\n")
|
|
|
|
for s in sl:
|
|
original = s.text
|
|
translation = stl.translate(s.text) # Keeps translated strings
|
|
|
|
f.write(f" # {elide_filename(s.filename)}:{s.line}\n")
|
|
f.write(f" old \"{quote_unicode(original)}\"\n")
|
|
f.write(f" new \"{quote_unicode(translation)}\"\n")
|
|
f.write("\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(f"\rGenerating dialogues for {language} ... Total progress:{n} % ... Stage 1/2", 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(f"# {trans.filename}:{trans.linenumber}\n")
|
|
f.write("translate {} {}:\n".format(language, trans.identifier.replace(".", "_")))
|
|
f.write("\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 fp in tl_file_cache:
|
|
f = tl_file_cache.pop(tl_file_cache)
|
|
f.close()
|
|
|
|
if args.dry:
|
|
print(f"Removal required: {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)
|