growatt_server: use human-readable labels in exception messages#166024
growatt_server: use human-readable labels in exception messages#166024johanzander wants to merge 12 commits intohome-assistant:devfrom
Conversation
HA renamed "services" to "actions" in the UI. Update the remaining exception message in strings.json that still used the old term. Fixes review comment by @NoRi2909 on home-assistant#165927. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the Growatt Server integration’s exception translation string to use Home Assistant’s current “actions” terminology instead of the deprecated “services” wording.
Changes:
- Updates the
device_not_configuredexception message instrings.jsonfrom “services” to “actions”.
…able labels in exception messages Use proper English in translated exception messages instead of internal Python parameter names. Charge power, discharge power, SOC limits and time-format errors now show user-friendly labels (e.g. "Charge power", "Period 1 start") rather than snake_case identifiers. Update tests to match the new field_name values. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ld wording - Use third-person singular for all action descriptions (Reads/Writes/Updates) - Fix write_ac_charge_times and write_ac_discharge_times device_id field description from "to read from" to "to write to" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Improves readability and provides a hint to translators that these are field names, not generic text. Dynamic placeholders are left unquoted as ICU message format does not allow placeholders inside single quotes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rge_times The name field "Device" is shared with read actions so it can be referenced rather than duplicated as a literal string. Both write actions point directly to read_ac_charge_times for the name to avoid chained references (Lokalise only supports one level of indirection). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All four SPH actions (read/write AC charge/discharge times) now reference the neutral "The Growatt device to perform the action on." from read_time_segments instead of action-specific "to read from"/"to write to" wording. All references point directly to read_time_segments to avoid chained references (Lokalise only supports one level of indirection). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
…t errors
Replaces the single invalid_time_format key (which embedded a hardcoded
English field name as a placeholder) with four separate translatable keys:
invalid_time_format_start_time, invalid_time_format_end_time,
invalid_time_format_period_start, invalid_time_format_period_end.
This ensures non-English translations do not have English words embedded
in otherwise-translated error messages. Period keys use a {period}
numeric placeholder which requires no translation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| return datetime.strptime(f"{parts[0]}:{parts[1]}", "%H:%M").time() | ||
| except (ValueError, IndexError) as err: |
There was a problem hiding this comment.
_parse_time_str claims to accept HH:MM:SS, and the new validation errors/messages also allow that format, but the implementation discards the seconds component by parsing only parts[0]:parts[1]. This will silently turn e.g. 11:00:30 into 11:00. Consider either parsing the full string when 3 components are provided (and validating seconds), or tightening the accepted/advertised format to HH:MM only.
| return datetime.strptime(f"{parts[0]}:{parts[1]}", "%H:%M").time() | |
| except (ValueError, IndexError) as err: | |
| if len(parts) == 2: | |
| # Format HH:MM | |
| return datetime.strptime(time_str, "%H:%M").time() | |
| # Format HH:MM:SS | |
| return datetime.strptime(time_str, "%H:%M:%S").time() | |
| except ValueError as err: |
| end = _parse_time_str( | ||
| call.data.get(f"period_{i}_end", cached["end_time"]), | ||
| f"period_{i}_end", | ||
| "invalid_time_format_period_end", | ||
| {"period": str(i)}, | ||
| ) |
There was a problem hiding this comment.
New translation key path for invalid period end time (invalid_time_format_period_end with {period} placeholder) is introduced here, but the existing tests only assert the start error path. Adding a test that supplies an invalid period_1_end (and ideally one for write_ac_discharge_times too) would prevent future regressions in the raised translation key/placeholders.
Co-authored-by: Norbert Rittel <norbert@rittel.de>
| "invalid_time_format_period_end": { | ||
| "message": "'Period {period} end' must be in HH:MM or HH:MM:SS format." | ||
| }, | ||
| "invalid_time_format_period_start": { | ||
| "message": "'Period {period} start' must be in HH:MM or HH:MM:SS format." |
There was a problem hiding this comment.
strings.json is currently invalid JSON in this hunk: the invalid_time_format_period_start entry is missing its closing } (and comma), and another key starts immediately after it. This will break translation loading/build; please fix the structure so each exception key is a valid, properly closed JSON object.
| "invalid_time_format_period_end": { | |
| "message": "'Period {period} end' must be in HH:MM or HH:MM:SS format." | |
| }, | |
| "invalid_time_format_period_start": { | |
| "message": "'Period {period} start' must be in HH:MM or HH:MM:SS format." | |
| }, |
There was a problem hiding this comment.
Github somehow messed this up when I just added the two single quotes on each line.
| "invalid_time_format_period_end": { | ||
| "message": "'Period {period} end' must be in HH:MM or HH:MM:SS format." | ||
| }, | ||
| "invalid_time_format_period_start": { | ||
| "message": "'Period {period} start' must be in HH:MM or HH:MM:SS format." |
There was a problem hiding this comment.
There are duplicate exception keys (invalid_time_format_period_start / invalid_time_format_period_end) defined twice here. Also, one of the duplicates wraps the {period} placeholder inside single quotes ('Period {period} …'), which ICU message formatting treats as escaped text (the placeholder may not be substituted). Keep only one definition per key and ensure placeholders are not inside quoted segments.
| "invalid_time_format_period_end": { | |
| "message": "'Period {period} end' must be in HH:MM or HH:MM:SS format." | |
| }, | |
| "invalid_time_format_period_start": { | |
| "message": "'Period {period} start' must be in HH:MM or HH:MM:SS format." | |
| }, |
There was a problem hiding this comment.
Using two single quotes in those four places should fix that issue.
joostlek
left a comment
There was a problem hiding this comment.
The PR template isn't there and CI is failing, can you take a look?
The GitHub UI suggestion added quoted period field names without removing
the originals or closing their braces, resulting in duplicate keys and
invalid JSON. Keep only the quoted versions: 'Period {period} end' and
'Period {period} start', consistent with other field name messages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dd end time test - Fix _parse_time_str to actually parse seconds when HH:MM:SS format is provided, instead of silently discarding them - Add test for invalid period end time (invalid_time_format_period_end) to complement the existing period start time test Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…SS and add end time test" This reverts commit faa14ff.
|
This should hopefully fix the PR template issue: #166069 |
Proposed change
Follow-up to #165314, fixing wording issues in
strings.jsonfor the Growatt Server integration.device_not_configuredexception message incorrectly said "services" — Home Assistant renamed these to "actions".charge_power must be between 0 and 100). Replaced with proper English labels wrapped in single quotes ('Charge power','Charge stop SOC','Discharge power','Discharge stop SOC','Segment ID','Start time','End time','Period N start','Period N end').Reads…,Writes…,Updates…to match HA standards.device_idfield description for all SPH actions: All four SPH actions now reference the neutral description fromread_time_segmentsinstead of action-specific wording.Type of change
Additional information
Checklist
ruff format homeassistant tests)