Files
moonwell-core/tools/build-playerbots-ru-sql.py
T

96 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Build the static mod-playerbots ruRU SQL update from a reviewed TSV file."""
from __future__ import annotations
import csv
import re
from collections import Counter
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
INPUT = ROOT / "playerbots-phrases-ru-reviewed.tsv"
OUTPUT = (
ROOT
/ "modules/mod-playerbots/data/sql/playerbots/updates/"
/ "2026_07_30_00_ai_playerbot_russian_texts.sql"
)
EXPECTED_FIELDS = ("id", "key", "original_en", "translation_ru")
PLACEHOLDER_RE = re.compile(r"%[A-Za-z_][A-Za-z0-9_]*|<[^>]+>")
def sql_quote(value: str) -> str:
return "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'"
def load_rows() -> list[dict[str, str]]:
with INPUT.open(encoding="utf-8-sig", newline="") as input_file:
reader = csv.DictReader(input_file, delimiter="\t")
if tuple(reader.fieldnames or ()) != EXPECTED_FIELDS:
raise RuntimeError(
f"Unexpected TSV columns: {reader.fieldnames}; "
f"expected {EXPECTED_FIELDS}"
)
rows = list(reader)
if not rows:
raise RuntimeError(f"No translations found in {INPUT}")
seen_ids: set[int] = set()
for line_number, row in enumerate(rows, start=2):
try:
row_id = int(row["id"])
except ValueError as error:
raise RuntimeError(
f"{INPUT}:{line_number}: invalid id {row['id']!r}"
) from error
if row_id in seen_ids:
raise RuntimeError(f"{INPUT}:{line_number}: duplicate id {row_id}")
seen_ids.add(row_id)
if not row["key"]:
raise RuntimeError(f"{INPUT}:{line_number}: empty key")
if not row["translation_ru"].strip():
raise RuntimeError(f"{INPUT}:{line_number}: empty translation")
source_placeholders = Counter(PLACEHOLDER_RE.findall(row["original_en"]))
target_placeholders = Counter(PLACEHOLDER_RE.findall(row["translation_ru"]))
if source_placeholders != target_placeholders:
raise RuntimeError(
f"{INPUT}:{line_number}: placeholder mismatch: "
f"{source_placeholders} != {target_placeholders}"
)
return rows
def write_sql(rows: list[dict[str, str]]) -> None:
lines = [
"-- MoonWell static Russian localization for mod-playerbots.",
f"-- Generated from {INPUT.name}; edit the TSV and rebuild, not this file.",
"-- Placeholder names and counts are validated; their order may differ in Russian.",
"SET NAMES utf8mb4;",
"",
"START TRANSACTION;",
]
for row in rows:
lines.append(
"UPDATE `ai_playerbot_texts` "
f"SET `text_loc8`={sql_quote(row['translation_ru'])} "
f"WHERE `id`={int(row['id'])} AND `name`={sql_quote(row['key'])};"
)
lines.extend(["COMMIT;", ""])
OUTPUT.write_text("\n".join(lines), encoding="utf-8")
print(f"Wrote {len(rows)} reviewed translations to {OUTPUT}")
def main() -> None:
write_sql(load_rows())
if __name__ == "__main__":
main()