| 12345678910111213141516171819202122232425262728293031323334353637 |
- # -*- coding: utf-8 -*-
- """显示层术语映射 (app_frontEnd/configs/terms/display_map.yaml): 内部说法 → 现场说法。
- **只在渲染边界用**, 不改数据、不改任何比较/匹配逻辑 (那些内部词就在 handoff/本体数据里, 改数据会断匹配)。
- 用法: from src.windscada.terms import humanize; humanize('发电机(引用同族, 见族主台)') → '发电机(无本台独立证据, 参照同型机组)'
- 前端同源: `pairs()` 出的表经语言包 `__display_zh` 注入 app.js 的 displayText。
- """
- from __future__ import annotations
- try:
- from app_common.app_common_guanlan.api import install_root as _install_root
- except ImportError: # 极端兜底(包结构异常时按位置上跳)
- from pathlib import Path as _P
- def _install_root(_f): return _P(_f).resolve().parents[3]
- import functools, pathlib, sys
- ROOT = _install_root(__file__)
- sys.path.insert(0, str(ROOT))
- from src import paths as P # 配置唯一取用口
- MAP_FILE = P.config("terms", "display_map.yaml") # 配置唯一取用口 (src/paths.py)
- @functools.lru_cache(maxsize=1)
- def pairs() -> tuple[tuple[str, str], ...]:
- """(内部词, 现场词) 按内部词长度降序 —— 长词先替, 否则 '引用同族, 见族主台' 会被 '引用同族' 先吃掉半句."""
- if not MAP_FILE.exists(): return ()
- import yaml
- d = yaml.safe_load(MAP_FILE.read_text(encoding="utf-8")) or {}
- ps = [(str(i["from"]), str(i["to"])) for i in (d.get("items") or []) if i.get("from")]
- return tuple(sorted(ps, key=lambda kv: -len(kv[0])))
- def humanize(s):
- """把内部词换成现场说法; 非字符串原样返回 (调用点可以无脑包)."""
- if not isinstance(s, str) or not s: return s
- for a, b in pairs():
- if a in s: s = s.replace(a, b)
- return s
|