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>
This commit is contained in:
@@ -9,26 +9,23 @@ are (DECISIONS/UX-13-one-layout-table.md).
|
||||
"""
|
||||
|
||||
import copy
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
from . import uilayout as L
|
||||
from . import uitext
|
||||
from . import uimodel as U
|
||||
from .configui import help_of, label_of, problems_by_field, split_group
|
||||
from .validate import power_request_entities
|
||||
|
||||
UI_TEXT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui_text",
|
||||
"en.json")
|
||||
# A choice the page cannot make, only keep: odd tariff windows (P5 editor).
|
||||
ONLY_IF_HELD = ("custom",)
|
||||
# A choice the page cannot make, only keep. None since P5's period editor.
|
||||
ONLY_IF_HELD = ()
|
||||
_TIERS = ("bad", "warn", "info")
|
||||
|
||||
|
||||
def ui_text() -> dict:
|
||||
with io.open(UI_TEXT, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
def ui_text(lang="en") -> dict:
|
||||
"""The page words in `lang`, English where Dutch has no key (P5)."""
|
||||
return copy.deepcopy(uitext.words(lang))
|
||||
|
||||
|
||||
def _roster():
|
||||
@@ -122,6 +119,10 @@ def _field(fld, schema_ui, translations, lang, T):
|
||||
if hints:
|
||||
out["hints"] = {v: e.get("description", "")
|
||||
for v, e in hints.items()}
|
||||
if fld.control == L.PERIOD_LIST:
|
||||
# P5: the day choices of one time window, in the editor's order.
|
||||
names = T["choices"]["period_days"]
|
||||
out["days"] = [[d, names.get(d, d)] for d in U.PERIOD_DAYS]
|
||||
if fld.mirror:
|
||||
out["mirror"] = fld.mirror
|
||||
if fld.fills:
|
||||
@@ -145,7 +146,7 @@ def _field(fld, schema_ui, translations, lang, T):
|
||||
def layout(schema_ui, translations, lang="en") -> dict:
|
||||
"""Every group, part and field of the Installer view, as the page draws
|
||||
it. Built from the table only: a field the table places is on the page."""
|
||||
T = ui_text()
|
||||
T = ui_text(lang)
|
||||
groups = []
|
||||
for g in L.GROUPS:
|
||||
parts = []
|
||||
@@ -220,14 +221,19 @@ def _settle(out: dict, stored: dict | None) -> dict:
|
||||
| {k: v for k, v in out.items() if k not in stored})
|
||||
|
||||
|
||||
def derive_message(err: U.DeriveError) -> dict:
|
||||
words = ui_text()["settings"]["derive"]
|
||||
def derive_message(err: U.DeriveError, lang="en") -> dict:
|
||||
T = uitext.words(lang)
|
||||
words = T["settings"]["derive"]
|
||||
text = words.get(err.code, words["unknown"])["description"]
|
||||
args = dict(getattr(err, "values", None) or {})
|
||||
# A time window's day is shown by name (P5 period editor).
|
||||
if "day" in args:
|
||||
args["day"] = T["choices"]["period_days"].get(args["day"], args["day"])
|
||||
return {"field": err.field or None, "card": None, "tier": "bad",
|
||||
"text": text}
|
||||
"text": uitext.say(text, **args)}
|
||||
|
||||
|
||||
def derive_messages(errors, problems, notes, model, keys):
|
||||
def derive_messages(errors, problems, notes, model, keys, lang="en"):
|
||||
"""The page's messages when part of the model could not become options:
|
||||
each conversion's own sentence beside its field, then the checks of the
|
||||
rest. A refusal or note about a key the failed conversion writes is left
|
||||
@@ -238,7 +244,7 @@ def derive_messages(errors, problems, notes, model, keys):
|
||||
for t in texts] + list(unanchored)
|
||||
kept = [p for p in problems if p in kept]
|
||||
notes = [n for n in notes if not set(n.keys or ()) & failed]
|
||||
return ([derive_message(err) for err in errors]
|
||||
return ([derive_message(err, lang) for err in errors]
|
||||
+ anchors(kept, notes, model, keys))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user