Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
"""
|
||
i18n 包:报告中英文国际化支持
|
||
|
||
设计原则:
|
||
1. 数据层 key 保持中文(不破坏 PCA / 缓存兼容性)
|
||
2. 仅在显示层(模板/LLM prompt)通过 t() 翻译
|
||
3. 找不到 key 时 fallback 到中文原值,保证渐进式迁移不会爆 Jinja
|
||
"""
|
||
from typing import Dict, Any
|
||
from . import zh_CN, en_US
|
||
|
||
_BUNDLES = {
|
||
"zh": zh_CN.STRINGS,
|
||
"en": en_US.STRINGS,
|
||
}
|
||
|
||
DEFAULT_LANG = "zh"
|
||
|
||
|
||
class Translator:
|
||
"""
|
||
可点号访问的翻译器,供 Jinja 模板使用:
|
||
|
||
Jinja 模板用法:
|
||
{{ t.score }} → "得分" / "Score"
|
||
{{ t.dim('课程领导力') }} → "课程领导力" / "Curriculum Leadership"
|
||
{{ t.sub('国家标准遵循') }} → "国家标准遵循" / "National Standards Compliance"
|
||
{{ t.level_desc('国家标准遵循', 4) }} → 水平 4 的描述
|
||
{{ t.part('part3') }} → "第三部分 课程领导力表现" / "Part III. Curriculum Leadership"
|
||
"""
|
||
|
||
def __init__(self, lang: str = DEFAULT_LANG):
|
||
self.lang = lang if lang in _BUNDLES else DEFAULT_LANG
|
||
self._bundle: Dict[str, Any] = _BUNDLES[self.lang]
|
||
self._fallback: Dict[str, Any] = _BUNDLES[DEFAULT_LANG]
|
||
|
||
# ---- 字符串字段(UI label) ----
|
||
def __getattr__(self, key: str) -> str:
|
||
# 首先在 UI 字典中找,找不到回退到中文
|
||
ui = self._bundle.get("UI", {})
|
||
if key in ui:
|
||
return ui[key]
|
||
ui_zh = self._fallback.get("UI", {})
|
||
return ui_zh.get(key, key)
|
||
|
||
def get(self, key: str, default: str = "") -> str:
|
||
ui = self._bundle.get("UI", {})
|
||
if key in ui:
|
||
return ui[key]
|
||
ui_zh = self._fallback.get("UI", {})
|
||
return ui_zh.get(key, default or key)
|
||
|
||
# ---- 维度名翻译 ----
|
||
def dim(self, name_zh: str) -> str:
|
||
"""7 大二级维度名翻译"""
|
||
d = self._bundle.get("DIMENSIONS", {})
|
||
return d.get(name_zh, name_zh)
|
||
|
||
def sub(self, name_zh: str) -> str:
|
||
"""20 个三级维度名翻译"""
|
||
d = self._bundle.get("SUB_DIMENSIONS", {})
|
||
return d.get(name_zh, name_zh)
|
||
|
||
def part(self, part_id: str) -> str:
|
||
"""部分标题:part0/part1/part3..part9/part10"""
|
||
d = self._bundle.get("PARTS", {})
|
||
return d.get(part_id, part_id)
|
||
|
||
def part_number(self, part_id: str) -> str:
|
||
"""部分编号:第三部分 / Part III."""
|
||
d = self._bundle.get("PART_NUMBERS", {})
|
||
return d.get(part_id, part_id)
|
||
|
||
def level_desc(self, sub_dim_zh: str, level: int) -> str:
|
||
"""子维度水平描述(4 档)"""
|
||
d = self._bundle.get("LEVEL_DESCRIPTIONS", {})
|
||
sub = d.get(sub_dim_zh, {})
|
||
if not sub:
|
||
sub = self._fallback.get("LEVEL_DESCRIPTIONS", {}).get(sub_dim_zh, {})
|
||
return sub.get(level, sub.get(str(level), ""))
|
||
|
||
def dim_def(self, name_zh: str) -> str:
|
||
"""7 大维度的概念定义(用于 LLM prompt + 模板说明)"""
|
||
d = self._bundle.get("DIMENSION_DEFINITIONS", {})
|
||
return d.get(name_zh, "")
|
||
|
||
def sub_def(self, name_zh: str) -> str:
|
||
"""20 个三级维度的概念定义"""
|
||
d = self._bundle.get("SUB_DIMENSION_DEFINITIONS", {})
|
||
return d.get(name_zh, "")
|
||
|
||
def cluster_label(self, kind: str) -> str:
|
||
"""聚类标签:good / weak / mid"""
|
||
d = self._bundle.get("CLUSTERS", {})
|
||
return d.get(kind, kind)
|
||
|
||
def school_type(self, type_zh: str) -> str:
|
||
"""学校类型翻译(市实验性示范性高中等)"""
|
||
d = self._bundle.get("SCHOOL_TYPES", {})
|
||
return d.get(type_zh, type_zh)
|
||
|
||
def district(self, name_zh: str) -> str:
|
||
"""区域名翻译(长宁区等)"""
|
||
d = self._bundle.get("DISTRICTS", {})
|
||
return d.get(name_zh, name_zh)
|
||
|
||
def date(self, dt) -> str:
|
||
"""日期格式化(按语言)"""
|
||
from datetime import datetime
|
||
if isinstance(dt, str):
|
||
return dt
|
||
if self.lang == "en":
|
||
return dt.strftime("%B %d, %Y")
|
||
return dt.strftime("%Y年%m月%d日")
|
||
|
||
|
||
def get_translator(lang: str = DEFAULT_LANG) -> Translator:
|
||
"""获取翻译器实例"""
|
||
return Translator(lang)
|
||
|
||
|
||
def get_bundle(lang: str = DEFAULT_LANG) -> Dict[str, Any]:
|
||
"""获取语言原始字典(供低层代码使用)"""
|
||
return _BUNDLES.get(lang, _BUNDLES[DEFAULT_LANG])
|
||
|
||
|
||
__all__ = ["Translator", "get_translator", "get_bundle", "DEFAULT_LANG"]
|