feat: add translations and improve config flow UX

- translations/en.json: runtime translation file HA loads (strings.json
  is tooling-only); includes data_description hints for host, cert, key

- config_flow.py: cert_pem and key_pem rendered as multiline text areas
  via TextSelector so users can paste full PEM blocks; host stays single-line

- strings.json: expanded error messages and data_description to match

- entity.py: entities with name=None (pattern-cap doors, temps, icemmakers)
  now derive a human-readable title from their state key instead of
  displaying blank ("door_cooler_open1" → "Door Cooler Open 1")
This commit is contained in:
Marc Billow committed 2026-06-30 16:34:39 -05:00
1 parent 8d43d54952
commit b372bca377
4 files changed
+60 -8

No files matched your search

+12 -4
View File
@@ -9,9 +9,17 @@ from typing import Any
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.selector import (
TextSelector,
TextSelectorConfig,
TextSelectorType,
)
from .const import DOMAIN, CONF_HOST, CONF_PORT, CONF_CERT_PEM, CONF_KEY_PEM, PROBE_PORTS
_TEXT = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT))
_MULTILINE = TextSelector(TextSelectorConfig(type=TextSelectorType.TEXT, multiline=True))
_LOGGER = logging.getLogger(__name__)
@@ -151,13 +159,13 @@ class LocalThingsConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
)
if has_creds:
schema = vol.Schema({vol.Required(CONF_HOST): str})
schema = vol.Schema({vol.Required(CONF_HOST): _TEXT})
reuse_note = "Certificate and key will be reused from the existing device."
else:
schema = vol.Schema({
vol.Required(CONF_HOST): str,
vol.Required(CONF_CERT_PEM): str,
vol.Required(CONF_KEY_PEM): str,
vol.Required(CONF_HOST): _TEXT,
vol.Required(CONF_CERT_PEM): _MULTILINE,
vol.Required(CONF_KEY_PEM): _MULTILINE,
})
reuse_note = ""
+13 -1
View File
@@ -1,6 +1,8 @@
"""Base entity for Local Things."""
from __future__ import annotations
import re
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.device_registry import DeviceInfo
@@ -11,6 +13,16 @@ from .const import DOMAIN
from .coordinator import LocalThingsCoordinator
def _derive_name(state_key: str) -> str:
"""Turn a snake_case state key into a title-cased display name.
Strips a trailing instance number of 0 (singleton), promotes any other
instance number with a space: "door_cooler_open1" → "Door Cooler Open 1".
"""
name = re.sub(r'(\d+)$', lambda m: f' {m.group()}' if int(m.group()) > 0 else '', state_key)
return name.replace('_', ' ').title().strip()
class LocalThingsEntity(CoordinatorEntity[LocalThingsCoordinator]):
"""Base class for all Local Things entities."""
@@ -21,7 +33,7 @@ class LocalThingsEntity(CoordinatorEntity[LocalThingsCoordinator]):
self._bound = bound
self._state_key = _key(bound)
self._attr_unique_id = f"{DOMAIN}_{coordinator.device_serial}_{self._state_key}"
self._attr_name = bound.desc.name
self._attr_name = bound.desc.name if bound.desc.name is not None else _derive_name(self._state_key)
self._attr_icon = bound.desc.icon
self._attr_entity_category = bound.desc.entity_category
self._attr_entity_registry_enabled_default = bound.desc.enabled_default
+8 -3
View File
@@ -3,17 +3,22 @@
"step": {
"user": {
"title": "Add Samsung Appliance",
"description": "Enter the IP address of your Samsung appliance. {reuse_note}",
"description": "Enter the IP address of your Samsung appliance on the local network. {reuse_note}",
"data": {
"host": "IP Address",
"cert_pem": "Certificate (PEM)",
"key_pem": "Private Key (PEM)"
},
"data_description": {
"host": "Local IP address of your Samsung appliance (e.g. 192.168.1.50).",
"cert_pem": "The PEM-encoded client certificate used to authenticate with the appliance. Paste the full contents including the BEGIN/END CERTIFICATE header and footer.",
"key_pem": "The PEM-encoded private key matching the certificate above. Paste the full contents including the BEGIN/END PRIVATE KEY header and footer."
}
}
},
"error": {
"cannot_connect": "Cannot connect to the device. Check the IP address and credentials.",
"unknown": "Unexpected error."
"cannot_connect": "Cannot connect to the device. Verify the IP address is reachable and the certificate and key are correct.",
"unknown": "Unexpected error. Check the Home Assistant logs for details."
},
"abort": {
"already_configured": "This device is already configured."
@@ -0,0 +1,27 @@
{
"config": {
"step": {
"user": {
"title": "Add Samsung Appliance",
"description": "Enter the IP address of your Samsung appliance on the local network. {reuse_note}",
"data": {
"host": "IP Address",
"cert_pem": "Certificate (PEM)",
"key_pem": "Private Key (PEM)"
},
"data_description": {
"host": "Local IP address of your Samsung appliance (e.g. 192.168.1.50).",
"cert_pem": "The PEM-encoded client certificate used to authenticate with the appliance. Paste the full contents including the BEGIN/END CERTIFICATE header and footer.",
"key_pem": "The PEM-encoded private key matching the certificate above. Paste the full contents including the BEGIN/END PRIVATE KEY header and footer."
}
}
},
"error": {
"cannot_connect": "Cannot connect to the device. Verify the IP address is reachable and the certificate and key are correct.",
"unknown": "Unexpected error. Check the Home Assistant logs for details."
},
"abort": {
"already_configured": "This device is already configured."
}
}
}