UX-46 review: Dutch wording fixes on the NL rows and notes
checks / unit (pull_request) Successful in 45m44s
infra-pin / fresh (pull_request) Successful in 1s

Text only. "stroom te opnemen" -> "stroom op te nemen"; Developer Tools is
"Ontwikkelhulpmiddelen" in HA and ui_text; the green stuck-meter row no longer
starts "Vastgelopen meter:"; maintenance banner names the phase in Dutch;
double "dan" in the device note; plainer peak reserve, peak guard, refused
commands and missing-entity wording. Two stale comments now say the banner
and Home bodies follow the page's language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
glenn schrooyen
2026-10-22 04:56:30 +02:00
co-authored by Claude Opus 5.5
parent c1809b4ca9
commit ae0ef4296b
5 changed files with 31 additions and 27 deletions
+3 -3
View File
@@ -1075,9 +1075,9 @@ def _kwh(v) -> str:
return _dec(f"{float(v):.1f}") + " kWh" return _dec(f"{float(v):.1f}") + " kWh"
# Row id -> the title on Home. The row's own sentence is the body, and it stays # Row id -> the title on Home. The row's own sentence is the body, in the
# in English (app/messages.py). Five titles are the notification's own title, # page's language (UX-46, `messages.pick`). Five titles are the notification's
# which test_ui_text.py checks. # own title, which test_ui_text.py checks.
_EN = uitext.words("en")["home_words"] _EN = uitext.words("en")["home_words"]
ATTN_TITLES = {(None if k == "none" else k): v for k, v in _EN["attn"].items()} ATTN_TITLES = {(None if k == "none" else k): v for k, v in _EN["attn"].items()}
ATTN_FROM_MESSAGES = { ATTN_FROM_MESSAGES = {
+2 -2
View File
@@ -7598,8 +7598,8 @@ class Controller:
held = level == "bad" and not running_alarm held = level == "bad" and not running_alarm
# UX-46. The rows were built in English with their Dutch beside them # UX-46. The rows were built in English with their Dutch beside them
# (`messages.Bi`); the page's language is chosen once, here, for the # (`messages.Bi`); the page's language is chosen once, here, for the
# Home sentences, the checks list and the rows that carry one. The # Home sentences, the checks list, the rows that carry one and the
# banner above stays English: it is the plain fallback. # banner. A plain str (no Dutch twin) stays as it is.
checks = [dict(c, text=messages.pick(c["text"], lang)) for c in checks] checks = [dict(c, text=messages.pick(c["text"], lang)) for c in checks]
rows = [(k, messages.pick(v, lang)) for k, v in rows] rows = [(k, messages.pick(v, lang)) for k, v in rows]
banner = messages.pick(banner, lang) banner = messages.pick(banner, lang)
+22 -18
View File
@@ -466,7 +466,7 @@ def row_maint_waits(until_text: str) -> str:
NOT_READY = "Not ready" NOT_READY = "Not ready"
BANNER_RUNNING = ("Running — holding grid at zero", BANNER_RUNNING = ("Running — holding grid at zero",
"Actief — het net blijft op nul") "Actief — houdt het net op nul")
DOCS_STATUS = "Status page" DOCS_STATUS = "Status page"
@@ -566,7 +566,9 @@ def banner_not_delivering(units) -> str:
def banner_maintenance(phase: str, unit: str = "") -> str: def banner_maintenance(phase: str, unit: str = "") -> str:
where = f" ({unit})" if unit else "" where = f" ({unit})" if unit else ""
return Bi(f"Maintenance: {phase}{where}", f"Onderhoud: {phase}{where}") fase = {"drain": "leegmaken", "charge": "opladen", "hold": "vol houden"}
return Bi(f"Maintenance: {phase}{where}",
f"Onderhoud: {fase.get(phase, phase)}{where}")
def banner_running() -> str: def banner_running() -> str:
@@ -588,7 +590,7 @@ def banner_setup_only() -> str:
def row_setup_only() -> str: def row_setup_only() -> str:
return Bi("No inverter is named yet, so finish Setup and restart the " return Bi("No inverter is named yet, so finish Setup and restart the "
"add-on.", "add-on.",
"Er is nog geen omvormer benoemd, dus rond de installatie af " "Er is nog geen omvormer opgegeven, dus rond de installatie af "
"en herstart de add-on.") "en herstart de add-on.")
@@ -700,9 +702,9 @@ def row_freeze_on(hold_s, rail_w, own_limit: bool) -> str:
return Bi(f"Stuck-meter check: alerts after {duration(hold_s)} unchanged " return Bi(f"Stuck-meter check: alerts after {duration(hold_s)} unchanged "
f"above {watts(rail_w)}" f"above {watts(rail_w)}"
+ (", the inverter's own limit" if own_limit else ""), + (", the inverter's own limit" if own_limit else ""),
f"Vastgelopen meter: alarm na {duur(hold_s)} gelijk boven " f"Controle op vastgelopen meter: alarm na {duur(hold_s)} "
f"{watts(rail_w)}" f"ongewijzigd boven {watts(rail_w)}"
+ (", limiet van de omvormer" if own_limit else "")) + (", omvormerlimiet" if own_limit else ""))
# Rows: the peak guard. # Rows: the peak guard.
@@ -734,14 +736,15 @@ def row_peak_reserve(ceiling_w, *, soc_unread: bool, floor_unknown: bool,
f"limit alone. Home use still draws it lower, to the " f"limit alone. Home use still draws it lower, to the "
f"cut-out level.", f"cut-out level.",
f"{why_nl}. De andere kunnen de piekgrens van " f"{why_nl}. De andere kunnen de piekgrens van "
f"{watts(ceiling_w)} niet alleen houden. Het huis trekt de " f"{watts(ceiling_w)} niet alleen houden. Het verbruik in "
f"batterij nog leger, tot het uitschakelniveau.") f"huis trekt de batterij verder leeg, tot het "
f"uitschakelniveau.")
return Bi(f"{why}, so the {watts(ceiling_w)} peak limit will be passed. " return Bi(f"{why}, so the {watts(ceiling_w)} peak limit will be passed. "
f"Home use still draws the battery below it, down to the " f"Home use still draws the battery below it, down to the "
f"cut-out level.", f"cut-out level.",
f"{why_nl}, dus de piekgrens van {watts(ceiling_w)} wordt " f"{why_nl}, dus de piekgrens van {watts(ceiling_w)} wordt "
f"overschreden. Het huis trekt de batterij nog leger, tot het " f"overschreden. Het verbruik in huis trekt de batterij verder "
f"uitschakelniveau.") f"leeg, tot het uitschakelniveau.")
def row_peak_guard_off() -> str: def row_peak_guard_off() -> str:
@@ -788,7 +791,7 @@ def row_sensor_unusable(label, unit=None) -> str:
f"Developer Tools before replacing it.", f"Developer Tools before replacing it.",
f"{LABEL_NL.get(label, label)}{voor(unit)}: geen bruikbare " f"{LABEL_NL.get(label, label)}{voor(unit)}: geen bruikbare "
f"meting. De entiteit ontbreekt misschien, of de meting is te " f"meting. De entiteit ontbreekt misschien, of de meting is te "
f"oud. Controleer ze in Ontwikkelaarstools voor u ze vervangt.") f"oud. Controleer ze in Ontwikkelhulpmiddelen voor u ze vervangt.")
def setpoint_label(unit=None, lang="en") -> str: def setpoint_label(unit=None, lang="en") -> str:
@@ -829,7 +832,7 @@ def row_not_controllable(name, held_s, limit_s) -> str:
f"{seconds(held_s)}, so control leaves it out.", f"{seconds(held_s)}, so control leaves it out.",
f"{name} kan niet worden geregeld. Hij weigerde elke opdracht " f"{name} kan niet worden geregeld. Hij weigerde elke opdracht "
f"gedurende {seconden(held_s)}, dus de regeling laat hem " f"gedurende {seconden(held_s)}, dus de regeling laat hem "
f"buiten beschouwing.") f"weg.")
def row_commands_refused(name, held_s, limit_s) -> str: def row_commands_refused(name, held_s, limit_s) -> str:
@@ -837,7 +840,7 @@ def row_commands_refused(name, held_s, limit_s) -> str:
return Bi(f"{name}: commands refused for {seconds(held_s)}, left out of " return Bi(f"{name}: commands refused for {seconds(held_s)}, left out of "
f"control after {seconds(limit_s)}", f"control after {seconds(limit_s)}",
f"{name}: opdrachten geweigerd gedurende {seconden(held_s)}, " f"{name}: opdrachten geweigerd gedurende {seconden(held_s)}, "
f"na {seconden(limit_s)} buiten de regeling gelaten") f"de regeling laat hem weg na {seconden(limit_s)}")
def row_control(lo_w, hi_w, unit=None) -> str: def row_control(lo_w, hi_w, unit=None) -> str:
@@ -1029,7 +1032,7 @@ def row_peak_forecast_unit(unit) -> str:
def row_peak_guard_waiting() -> str: def row_peak_guard_waiting() -> str:
return Bi("Peak guard: no decision yet, control has not run", return Bi("Peak guard: no decision yet, control has not run",
"Piekbewaking: nog geen besluit, de regeling is niet uitgevoerd") "Piekbewaking: nog geen besluit, de regeling liep nog niet")
def row_no_estop() -> str: def row_no_estop() -> str:
@@ -1175,12 +1178,12 @@ def row_peak_guard_idle(projected_w, limit_w, month_peak: bool) -> str:
else f"de piekgrens van {watts(limit_w)}") else f"de piekgrens van {watts(limit_w)}")
return Bi(f"Peak guard: idle, heading for {watts(projected_w)}, under " return Bi(f"Peak guard: idle, heading for {watts(projected_w)}, under "
f"{limit}", f"{limit}",
f"Piekbewaking: rust, op weg naar {watts(projected_w)}, onder " f"Piekbewaking: in rust, richting {watts(projected_w)}, onder "
f"{grens}") f"{grens}")
def row_peak_guard_quiet() -> str: def row_peak_guard_quiet() -> str:
return Bi("Peak guard: idle", "Piekbewaking: rust") return Bi("Peak guard: idle", "Piekbewaking: in rust")
BLIND_WORDS = { BLIND_WORDS = {
@@ -1219,7 +1222,7 @@ def row_peak_guard_on(floor_w, limit_w, *, shadow: bool = False) -> str:
f"{watts(limit_w)} te blijven") f"{watts(limit_w)} te blijven")
return Bi(f"Peak guard: asks the battery for {watts(floor_w)} to stay " return Bi(f"Peak guard: asks the battery for {watts(floor_w)} to stay "
f"under {watts(limit_w)}", f"under {watts(limit_w)}",
f"Piekbewaking: vraagt {watts(floor_w)} van de batterij om " f"Piekbewaking: vraagt de batterij {watts(floor_w)} om "
f"onder {watts(limit_w)} te blijven") f"onder {watts(limit_w)} te blijven")
@@ -1236,12 +1239,13 @@ def row_battery_refuses(unit, sign, probing) -> str:
"""SAFETY-73. One inverter's battery refuses, the others take its share.""" """SAFETY-73. One inverter's battery refuses, the others take its share."""
way = "give" if sign > 0 else "take" way = "give" if sign > 0 else "take"
weg = "leveren" if sign > 0 else "opnemen" weg = "leveren" if sign > 0 else "opnemen"
weigert = "te leveren" if sign > 0 else "op te nemen"
if probing: if probing:
return Bi(f"{unit}: testing if the battery will {way} power again", return Bi(f"{unit}: testing if the battery will {way} power again",
f"{unit}: test of de batterij weer stroom wil {weg}") f"{unit}: test of de batterij weer stroom wil {weg}")
return Bi(f"{unit}: the battery refuses to {way} power, the others take " return Bi(f"{unit}: the battery refuses to {way} power, the others take "
f"over", f"over",
f"{unit}: de batterij weigert stroom te {weg}, de andere " f"{unit}: de batterij weigert stroom {weigert}, de andere "
f"nemen over") f"nemen over")
+3 -3
View File
@@ -1865,8 +1865,8 @@ def _entity_notes(notes, opts: dict, entities: dict, bad=()) -> None:
_advise(notes, "bad" if key in bad else "warn", (key,), _advise(notes, "bad" if key in bad else "warn", (key,),
f"Home Assistant has no entity {entity}, which " f"Home Assistant has no entity {entity}, which "
f"{S(key, where)} names.", f"{S(key, where)} names.",
nl=f"Home Assistant heeft geen entiteit {entity}, terwijl " nl=f"Home Assistant kent {entity} niet, maar "
f"{SN(key, where)} die noemt.") f"{SN(key, where)} verwijst ernaar.")
continue continue
unit = str(row.get("unit") or "") unit = str(row.get("unit") or "")
if key in WATT_ENTITY_KEYS and unit in pv.WATTS_PER and unit != "W": if key in WATT_ENTITY_KEYS and unit in pv.WATTS_PER and unit != "W":
@@ -1885,7 +1885,7 @@ def _entity_notes(notes, opts: dict, entities: dict, bad=()) -> None:
_advise(notes, "warn", (key,), _advise(notes, "warn", (key,),
f"{entity} does not read in kWh, so pick a solar " f"{entity} does not read in kWh, so pick a solar "
"forecast sensor in kWh.", "forecast sensor in kWh.",
nl=f"{entity} meldt niet in kWh, dus kies een sensor voor " nl=f"{entity} meet niet in kWh, dus kies een sensor voor "
"de zonneprognose in kWh.") "de zonneprognose in kWh.")
today = solarfc.entities(opts) today = solarfc.entities(opts)
tomorrow = solarfc.entities(opts, tomorrow=True) tomorrow = solarfc.entities(opts, tomorrow=True)
+1 -1
View File
@@ -107,7 +107,7 @@ DEVICE_NOTE = (
"at start. If they fail later, the add-on will not start then.") "at start. If they fail later, the add-on will not start then.")
DEVICE_NOTE_NL = ( DEVICE_NOTE_NL = (
"%s meldde geen vermogensbereik, dus twee controles zijn overgeslagen, " "%s meldde geen vermogensbereik, dus twee controles zijn overgeslagen, "
"hier en bij het starten. Falen ze later, dan start de add-on dan niet.") "hier en bij het starten. Falen ze later, dan start de add-on niet.")
def build_app(controller, selfcfg=None) -> web.Application: def build_app(controller, selfcfg=None) -> web.Application: