#!/usr/bin/env python3 """Put Chinese into the text the 40250 quests write inline, outside gameforge.* (translate.lua). data/zh_40250/quest_inline_zh.tsv has one `file\\tline\\tEnglish\\tChinese` row per string literal (UTF-8). The row's line must hold "" exactly; it becomes "" in GBK, the code page of the newcibn locale. Only changed files are written to the output directory; copy them over the server's quest directory and run make.py (qc) there. questlib.lua is read at run time, not compiled. build_zh_quest_inline.py """ import argparse from collections import defaultdict from pathlib import Path REPO = Path(__file__).resolve().parents[1] DEFAULT_TABLE = REPO / "data/zh_40250/quest_inline_zh.tsv" def table_rows(path: Path): rows = defaultdict(list) for number, line in enumerate(path.read_text(encoding="utf-8").splitlines(), 1): if not line or line.startswith("#"): continue parts = line.split("\t") if len(parts) != 4: raise ValueError(f"{path}:{number}: want 4 tab-separated columns") name, line_no, english, chinese = parts rows[name].append((int(line_no), english, chinese, number)) return rows def encode(chinese: str, where: str) -> bytes: data = chinese.encode("gbk") # A GBK trail byte 0x5C is a backslash to Lua and qc; reword such a translation. if b"\\" in data or b'"' in data: raise ValueError(f"{where}: {chinese!r} has a quote or backslash byte in GBK") return data def build(source: Path, table: Path, output: Path): output.mkdir(parents=True, exist_ok=True) total = 0 for name, rows in sorted(table_rows(table).items()): lines = (source / name).read_bytes().split(b"\n") for line_no, english, chinese, number in rows: where = f"{table.name}:{number} ({name}:{line_no})" old = b'"' + english.encode("ascii") + b'"' if old not in lines[line_no - 1]: raise ValueError(f"{where}: {english!r} not on that line") lines[line_no - 1] = lines[line_no - 1].replace(old, b'"' + encode(chinese, where) + b'"', 1) total += 1 (output / name).write_bytes(b"\n".join(lines)) return total def main(): parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("source", type=Path) parser.add_argument("output", type=Path) parser.add_argument("--table", type=Path, default=DEFAULT_TABLE) args = parser.parse_args() print(f"{build(args.source, args.table, args.output)} strings replaced in {args.output}") if __name__ == "__main__": main()