Files
goodwe-addon/goodwe_controller/app/uitext.py
T
Claude dev agent 667b8e9145
checks / unit (pull_request) Successful in 10m45s
infra-pin / fresh (pull_request) Successful in 1s
UX-13 P5: Dutch text, STYLE check, DOCS screenshots, period editor
- app/ui_text/nl.json and app/uitext.py: every page word in Dutch, English
  fallback per key; the page picks by browser language. Home's sentences
  move into ui_text `home_words`, so /status?lang=nl builds them in Dutch.
- test_ui_text.py: EN/NL key and placeholder parity, STYLE limits, jargon
  lists for both languages, no inline details, untranslated Dutch caught.
  Shared rules moved unchanged to tools/style_rules.py.
- tools/ux13_screenshots.sh/.py: DOCS screenshots from the demo fixtures in
  headless Chromium; docs/img/ux13/. Battery modes (P3): no screenshot.
- "Other time windows": a list editor (ui.periods) that builds
  static_profile and names bad times, empty prices, overlaps and gaps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:33:32 +02:00

52 lines
1.6 KiB
Python

"""UX-13 P5: the page's words, app/ui_text/<lang>.json, in English or Dutch.
One file per language with the same keys. A key missing from a language falls
back to English, key by key, the way the Supervisor's translations do.
test_ui_text.py holds both files to STYLE.md and to each other.
"""
import copy
import io
import json
import os
DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui_text")
LANGS = ("en", "nl")
_CACHE: dict = {}
def lang_of(value) -> str:
""""nl", "nl-BE" or "nl_NL" -> "nl"; anything else -> "en"."""
head = str(value or "").strip().lower().replace("_", "-").split("-")[0]
return head if head in LANGS else "en"
def raw(lang: str) -> dict:
"""One language file as written, without the English fallback."""
if lang not in _CACHE:
with io.open(os.path.join(DIR, f"{lang}.json"), encoding="utf-8") as f:
_CACHE[lang] = json.load(f)
return _CACHE[lang]
def _merge(base, over):
if not (isinstance(base, dict) and isinstance(over, dict)):
return copy.deepcopy(over)
out = copy.deepcopy(base)
for k, v in over.items():
out[k] = _merge(base.get(k), v) if k in base else copy.deepcopy(v)
return out
def words(lang="en") -> dict:
"""Every word in `lang`, English where a key is missing."""
lang = lang_of(lang)
return raw("en") if lang == "en" else _merge(raw("en"), raw(lang))
def say(template: str, **values) -> str:
"""Fill `{name}` placeholders, as settings.js `say()` does."""
for k, v in values.items():
template = template.replace("{" + k + "}", str(v))
return template