Refactor/i18n (#115)

重构i18n,现在game configs的配表,除了姓名这种外,都是统一的配表了。
对应的配表的名称和desc需要去i18n里取,但是其他配置不需要重复配置了。
这大大简化了之后新增i18n的心智负担。
This commit is contained in:
4thfever
2026-02-01 01:09:24 +08:00
committed by GitHub
parent 5d46b47672
commit bc3ebc006c
79 changed files with 10082 additions and 892 deletions

View File

@@ -79,14 +79,19 @@ def update_paths_for_language(lang_code: str = None):
# 语言无关的配置目录
CONFIG.paths.shared_game_configs = Path("static/game_configs")
# 语言相关的配置目录
CONFIG.paths.game_configs = target_dir / "game_configs"
CONFIG.paths.localized_game_configs = target_dir / "game_configs"
# CONFIG.paths.game_configs 指向统一的数据源,不再区分语言目录
# 这里我们保留 CONFIG.paths.game_configs 作为"逻辑概念上的"配置集合根目录(虽然物理上分开了)
# 但实际上加载逻辑会在 df.py 中处理合并
CONFIG.paths.game_configs = Path("static/game_configs")
CONFIG.paths.templates = target_dir / "templates"
# 简单的存在性检查日志
if not CONFIG.paths.game_configs.exists():
print(f"[Config] Warning: Game configs dir not found at {CONFIG.paths.game_configs}")
else:
print(f"[Config] Switched paths to {lang_code}")
print(f"[Config] Switched language context to {lang_code} (Configs using Single Source)")
# 模块加载时自动初始化默认路径,确保 CONFIG.paths.game_configs 存在,避免 import 时 KeyError
update_paths_for_language()

View File

@@ -3,6 +3,7 @@ from pathlib import Path
from typing import Any, Dict, List, Optional
from src.utils.config import CONFIG
from src.i18n import t
def load_csv(path: Path) -> List[Dict[str, Any]]:
@@ -59,6 +60,32 @@ def load_csv(path: Path) -> List[Dict[str, Any]]:
else:
row_dict[header] = None
# -----------------------------------------------------------
# I18N Translation Injection
# -----------------------------------------------------------
# Try to translate name, desc and title using their IDs.
# If translation exists (and is not just the key itself), overwrite the value.
# Fallback is keeping the original value from CSV (usually Chinese reference).
title_id = row_dict.get("title_id")
if title_id and isinstance(title_id, str):
trans = t(title_id)
if trans != title_id and trans:
row_dict["title"] = trans
name_id = row_dict.get("name_id")
if name_id and isinstance(name_id, str):
trans = t(name_id)
if trans != name_id and trans:
row_dict["name"] = trans
desc_id = row_dict.get("desc_id")
if desc_id and isinstance(desc_id, str):
trans = t(desc_id)
if trans != desc_id and trans:
row_dict["desc"] = trans
# -----------------------------------------------------------
data.append(row_dict)
return data
@@ -66,17 +93,17 @@ def load_csv(path: Path) -> List[Dict[str, Any]]:
def load_game_configs() -> dict[str, List[Dict[str, Any]]]:
game_configs = {}
# 1. 加载共享配置 (Shared)
# 1. 加载共享配置 (static/game_configs/*.csv)
if hasattr(CONFIG.paths, "shared_game_configs") and CONFIG.paths.shared_game_configs.exists():
for path in CONFIG.paths.shared_game_configs.glob("*.csv"):
data = load_csv(path)
game_configs[path.stem] = data
# 2. 加载本地化配置 (Localized) - 会覆盖同名文件
if hasattr(CONFIG.paths, "game_configs") and CONFIG.paths.game_configs.exists():
for path in CONFIG.paths.game_configs.glob("*.csv"):
# 2. 加载本地化配置 (static/locales/{lang}/game_configs/*.csv)
# 如果文件名相同,覆盖共享配置
if hasattr(CONFIG.paths, "localized_game_configs") and CONFIG.paths.localized_game_configs.exists():
for path in CONFIG.paths.localized_game_configs.glob("*.csv"):
data = load_csv(path)
# 如果存在同名配置,这里会进行覆盖
game_configs[path.stem] = data
return game_configs