DazedTL/util/skills/contexts.py

63 lines
2.1 KiB
Python

"""Load per-call translation history templates from data/translation_contexts.json."""
from __future__ import annotations
import json
import os
from typing import Any
from util.paths import TRANSLATION_CONTEXTS_PATH
_cache: dict[str, Any] | None = None
_cache_mtime: float | None = None
def _load() -> dict[str, Any]:
global _cache, _cache_mtime
path = TRANSLATION_CONTEXTS_PATH
if not path.is_file():
raise FileNotFoundError(f"Translation contexts file missing: {path}")
mtime = path.stat().st_mtime
if _cache is not None and _cache_mtime == mtime:
return _cache
data = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(data, dict):
raise ValueError(f"translation_contexts.json must be an object: {path}")
_cache = data
_cache_mtime = mtime
return data
def ctx(path: str, *, language: str | None = None, **kwargs: Any) -> str:
"""Return a formatted history string for ``section.key``.
``{language}`` defaults to the ``language`` env / argument (capitalized).
Extra kwargs fill other ``{placeholders}`` (e.g. ``context``).
"""
if not path or "." not in path:
raise KeyError(f"Context path must be 'section.key', got {path!r}")
section_name, key = path.split(".", 1)
data = _load()
section = data.get(section_name)
if not isinstance(section, dict):
raise KeyError(f"Unknown translation context section: {section_name!r}")
template = section.get(key)
if not isinstance(template, str) or not template.strip():
raise KeyError(f"Unknown translation context key: {path!r}")
lang = language or os.getenv("language", "English")
lang = str(lang).capitalize()
values = {"language": lang, **kwargs}
try:
return template.format(**values)
except KeyError as exc:
raise KeyError(
f"Missing placeholder {exc.args[0]!r} for context {path!r}"
) from exc
def reload_contexts() -> None:
"""Clear the in-memory cache so the next ctx() re-reads from disk."""
global _cache, _cache_mtime
_cache = None
_cache_mtime = None