shadow-over-bishkek001/dialogue_translations_from_xlsx.py
2026-07-05 21:52:37 +03:00

62 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""
dialogue_translations_from_xlsx.py - Import a translated XLSX spreadsheet back
into dialogue_translations.json.
Reads a spreadsheet with a "key" header column followed by one column per
language (as produced by dialogue_translations_to_xlsx.py, possibly edited by a
translator), and writes it back out as {"dialogue_translations": [{"key":...,
"<lang>":...}, ...]}. Rows with an empty key are skipped. Cell values are
stripped; missing/empty cells become "".
Usage:
python dialogue_translations_from_xlsx.py <input.xlsx> <translations.json>
"""
import json
import os
import sys
try:
from openpyxl import load_workbook
except ImportError:
raise SystemExit("openpyxl is required: pip install openpyxl")
def import_from_xlsx(xlsx_path: str, json_path: str) -> None:
wb = load_workbook(xlsx_path, read_only=True, data_only=True)
ws = wb.active
rows = ws.iter_rows(values_only=True)
header = next(rows, None)
if not header or header[0] != "key":
raise SystemExit(f"Expected first column header to be 'key', got: {header}")
languages = [str(col) for col in header[1:] if col is not None]
entries = []
for row in rows:
key = row[0]
if key is None or str(key).strip() == "":
continue
entry = {"key": str(key)}
for i, lang in enumerate(languages):
value = row[i + 1] if i + 1 < len(row) else None
entry[lang] = str(value).strip() if value is not None else ""
entries.append(entry)
os.makedirs(os.path.dirname(os.path.abspath(json_path)), exist_ok=True)
with open(json_path, 'w', encoding='utf-8') as f:
json.dump({"dialogue_translations": entries}, f, indent=4, ensure_ascii=False)
print(f"Saved: {json_path} ({len(entries)} row(s), languages: {', '.join(languages)})")
if __name__ == '__main__':
if len(sys.argv) != 3:
print(f"Usage: {sys.argv[0]} <input.xlsx> <translations.json>")
sys.exit(1)
import_from_xlsx(sys.argv[1], sys.argv[2])