Files
4thfever bc3ebc006c Refactor/i18n (#115)
重构i18n,现在game configs的配表,除了姓名这种外,都是统一的配表了。
对应的配表的名称和desc需要去i18n里取,但是其他配置不需要重复配置了。
这大大简化了之后新增i18n的心智负担。
2026-02-01 01:09:24 +08:00

116 lines
3.5 KiB
Python

import csv
import sys
import time
from pathlib import Path
from typing import Dict, List, Optional
# Configuration
PROJECT_ROOT = Path(__file__).parent.parent.parent
SOURCE_DIR = PROJECT_ROOT / "static" / "game_configs"
TEMPLATE_DIR = PROJECT_ROOT / "src" / "i18n" / "locales" / "templates"
POT_FILE = TEMPLATE_DIR / "game_configs.pot"
def ensure_dir(path: Path):
if not path.exists():
path.mkdir(parents=True)
def read_csv(path: Path) -> List[Dict[str, str]]:
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
reader = csv.reader(f)
lines = list(reader)
if len(lines) < 2:
return []
headers = lines[0]
if headers and headers[0].startswith('\ufeff'):
headers[0] = headers[0][1:]
data = []
# Skip headers and comment row
# Heuristic: if row 2 looks like comments (Chinese/Types), skip it
start_idx = 1
if len(lines) > 1:
# Check if second row is likely a comment row (contains non-ascii or matches known structure)
if any(ord(c) > 127 for c in "".join(lines[1])):
start_idx = 2
for row in lines[start_idx:]:
if not row: continue
item = {}
for i, h in enumerate(headers):
if i < len(row):
item[h.strip()] = row[i].strip()
data.append(item)
return data
def escape_po_string(s: str) -> str:
return s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
def generate_pot_entry(msgid: str, comment: str = "") -> str:
s = ""
if comment:
s += f"#. {comment}\n"
s += f'msgid "{escape_po_string(msgid)}"\n'
s += f'msgstr ""\n\n'
return s
def main():
print(f"Extracting translations from {SOURCE_DIR}...")
ensure_dir(TEMPLATE_DIR)
entries = []
# Header
header = f"""# Game Configs Translations
# Generated by tools/i18n/extract_csv.py
#
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\\n"
"Content-Transfer-Encoding: 8bit\\n"
"Project-Id-Version: Cultivation World Simulator\\n"
"""
entries.append(header)
count = 0
# Sort files for stable output
for csv_file in sorted(SOURCE_DIR.glob("*.csv")):
filename = csv_file.name
# Skip name files as they are handled differently (file suffix)
if "given_name" in filename or "last_name" in filename:
continue
data = read_csv(csv_file)
for item in data:
# Check for name_id
name_id = item.get("name_id")
if name_id:
ref_text = item.get("name", "")
entries.append(generate_pot_entry(name_id, f"{filename}: {ref_text}"))
count += 1
# Check for desc_id
desc_id = item.get("desc_id")
if desc_id:
ref_text = item.get("desc", "")
# Truncate long descriptions in comments
if len(ref_text) > 50:
ref_text = ref_text[:47] + "..."
entries.append(generate_pot_entry(desc_id, f"{filename}: {ref_text}"))
count += 1
with open(POT_FILE, "w", encoding="utf-8") as f:
f.write("".join(entries))
print(f"Extracted {count} keys to {POT_FILE}")
print("Don't forget to update your .po files using msgmerge or Poedit!")
if __name__ == "__main__":
main()