Skip to content

Commit a8d9aaa

Browse files
committed
Rework for internationalisation support.
1 parent 9fe7433 commit a8d9aaa

15 files changed

+273
-142
lines changed

custom_components/powersensor/config_flow.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import voluptuous as vol
77

88
from homeassistant import config_entries
9-
from homeassistant.config_entries import ConfigFlowResult
9+
from homeassistant.core import HomeAssistant
10+
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
1011
from homeassistant.helpers.dispatcher import async_dispatcher_send
1112
from homeassistant.helpers.selector import selector
1213
from homeassistant.helpers.service_info import zeroconf
14+
from homeassistant.helpers.translation import async_get_cached_translations
1315

1416
from .const import (
1517
CFG_DEVICES,
@@ -22,17 +24,28 @@
2224
ROLE_UPDATE_SIGNAL,
2325
ROLE_WATER,
2426
RT_DISPATCHER,
25-
SENSOR_NAME_FORMAT,
2627
)
2728

2829
_LOGGER = logging.getLogger(__name__)
2930

3031

32+
def get_translated_sensor_name(hass: HomeAssistant, config_entry: ConfigEntry, mac: str) -> str|None:
33+
"""Helper to neatly format the translated name, for user input."""
34+
translations = async_get_cached_translations(
35+
hass, hass.config.language, "device", config_entry.domain
36+
)
37+
format_string = translations.get(
38+
"component.powersensor.device.unknown_sensor.name",
39+
"Powersensor Sensor (ID: {id})"
40+
)
41+
return format_string.replace("{id}", mac)
42+
43+
3144
class PowersensorConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
3245
"""Handle a config flow."""
3346

3447
VERSION = 2
35-
MINOR_VERSION = 0
48+
MINOR_VERSION = 2
3649

3750
def __init__(self) -> None:
3851
"""Initialize the config flow."""
@@ -49,9 +62,9 @@ async def async_step_reconfigure(
4962
if dispatcher is None:
5063
return self.async_abort(reason="cannot_reconfigure")
5164

52-
mac2name = {mac: SENSOR_NAME_FORMAT % mac for mac in dispatcher.sensors}
65+
mac2name = {mac: get_translated_sensor_name(self.hass, entry, mac) for mac in dispatcher.sensors}
5366

54-
unknown = "<unknown>"
67+
unknown = "unknown"
5568
if user_input is not None:
5669
name2mac = {name: mac for mac, name in mac2name.items()}
5770
for name, role in user_input.items():

custom_components/powersensor/const.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
ZEROCONF_REMOVE_PLUG_SIGNAL = f"{DOMAIN}_zeroconf_remove_plug"
1717
ZEROCONF_UPDATE_PLUG_SIGNAL = f"{DOMAIN}_zeroconf_update_plug"
1818

19-
# Formatting, would've liked to have been able to have this translatable
20-
SENSOR_NAME_FORMAT = "Powersensor Sensor (ID: %s)"
21-
2219
# Config entry keys
2320
CFG_DEVICES = "devices"
2421
CFG_ROLES = "roles"

custom_components/powersensor/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"iot_class": "local_push",
1313
"issue_tracker": "https://github.com/DiUS/homeassistant-powersensor/issues",
1414
"requirements": [
15-
"powersensor-local==2.1.0"
15+
"powersensor-local==2.1.1"
1616
],
1717
"single_config_entry": true,
1818
"version": "1.0.1",

custom_components/powersensor/powersensor_message_dispatcher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ async def _plug_added(self, info):
349349
else:
350350
await self.enqueue_plug_for_adding(network_info)
351351

352-
async def _plug_updated(self, info):
352+
async def _plug_updated(self, info) -> None:
353353
_LOGGER.debug("Request to update plug received: %s", info)
354354
mac = info["properties"][b"id"].decode("utf-8")
355355
await self.cancel_any_pending_removal(mac, "request to update plug")

custom_components/powersensor/sensor/__init__.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ async def async_setup_entry(
6363
entry.runtime_data[RT_VHH_SOLAR_ADDED] = False
6464

6565
plug_role = ROLE_APPLIANCE
66+
entry_id = entry.entry_id
6667

6768
def with_solar():
6869
"""Checks whether any known sensor has the solar role."""
@@ -110,19 +111,19 @@ async def handle_discovered_sensor(sensor_mac: str, sensor_role: str):
110111
"""Registers sensor entities, signals sensor added plus VHH update if needed."""
111112
new_sensors = [
112113
PowersensorSensorEntity(
113-
hass, sensor_mac, sensor_role, SensorMeasurements.BATTERY
114+
hass, entry_id, sensor_mac, sensor_role, SensorMeasurements.BATTERY
114115
),
115116
PowersensorSensorEntity(
116-
hass, sensor_mac, sensor_role, SensorMeasurements.WATTS
117+
hass, entry_id, sensor_mac, sensor_role, SensorMeasurements.WATTS
117118
),
118119
PowersensorSensorEntity(
119-
hass, sensor_mac, sensor_role, SensorMeasurements.SUMMATION_ENERGY
120+
hass, entry_id, sensor_mac, sensor_role, SensorMeasurements.SUMMATION_ENERGY
120121
),
121122
PowersensorSensorEntity(
122-
hass, sensor_mac, sensor_role, SensorMeasurements.ROLE
123+
hass, entry_id, sensor_mac, sensor_role, SensorMeasurements.ROLE
123124
),
124125
PowersensorSensorEntity(
125-
hass, sensor_mac, sensor_role, SensorMeasurements.RSSI
126+
hass, entry_id, sensor_mac, sensor_role, SensorMeasurements.RSSI
126127
),
127128
]
128129
async_add_entities(new_sensors, True)
@@ -142,25 +143,25 @@ async def create_plug(plug_mac_address: str, new_plug_role: str):
142143
"""Registers sensor entities."""
143144
this_plug_sensors = [
144145
PowersensorPlugEntity(
145-
hass, plug_mac_address, new_plug_role, PlugMeasurements.WATTS
146+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.WATTS
146147
),
147148
PowersensorPlugEntity(
148-
hass, plug_mac_address, new_plug_role, PlugMeasurements.VOLTAGE
149+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.VOLTAGE
149150
),
150151
PowersensorPlugEntity(
151-
hass, plug_mac_address, new_plug_role, PlugMeasurements.APPARENT_CURRENT
152+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.APPARENT_CURRENT
152153
),
153154
PowersensorPlugEntity(
154-
hass, plug_mac_address, new_plug_role, PlugMeasurements.ACTIVE_CURRENT
155+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.ACTIVE_CURRENT
155156
),
156157
PowersensorPlugEntity(
157-
hass, plug_mac_address, new_plug_role, PlugMeasurements.REACTIVE_CURRENT
158+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.REACTIVE_CURRENT
158159
),
159160
PowersensorPlugEntity(
160-
hass, plug_mac_address, new_plug_role, PlugMeasurements.SUMMATION_ENERGY
161+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.SUMMATION_ENERGY
161162
),
162163
PowersensorPlugEntity(
163-
hass, plug_mac_address, new_plug_role, PlugMeasurements.ROLE
164+
hass, entry_id, plug_mac_address, new_plug_role, PlugMeasurements.ROLE
164165
),
165166
]
166167

custom_components/powersensor/sensor/powersensor_entity.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ class PowersensorSensorEntityDescription(SensorEntityDescription):
3535
class PowersensorEntity(SensorEntity, Generic[MeasurementType]):
3636
"""Base class for all Powersensor entities."""
3737

38+
_attr_has_entity_name = True
39+
_attr_should_poll = False
40+
3841
def __init__(
3942
self,
4043
hass: HomeAssistant,
44+
config_entry_id: str,
4145
mac: str,
4246
role: str,
4347
input_config: dict[MeasurementType, PowersensorSensorEntityDescription],
@@ -48,8 +52,8 @@ def __init__(
4852
self._role = role
4953
self._has_recently_received_update_message = False
5054
self._attr_native_value = 0.0
51-
self._attr_should_poll = False
5255
self._hass = hass
56+
self._config_entry_id = config_entry_id
5357
self._mac = mac
5458
self._model = "PowersensorDevice"
5559
self._device_name = f"Powersensor Device (ID: {self._mac})"
@@ -63,17 +67,11 @@ def __init__(
6367
self.entity_description = config
6468

6569
self._attr_unique_id = f"{mac}_{measurement_type.name}"
66-
self._attr_device_info = self.device_info
6770

6871
self._signal = DATA_UPDATE_SIGNAL_FMT_MAC_EVENT % (mac, config.event)
6972
self._message_key = config.message_key
7073
self._message_callback = config.conversion_function
7174

72-
@property
73-
def device_info(self) -> DeviceInfo:
74-
"""Abstract property to for returning DeviceInfo."""
75-
raise NotImplementedError
76-
7775
@property
7876
def available(self) -> bool:
7977
"""Does data exist for this sensor type."""
@@ -119,18 +117,25 @@ def _handle_role_update(self, mac: str, role: str):
119117
return
120118

121119
self._role = role
122-
name_updated = self._rename_based_on_role()
120+
was_updated = self._rename_based_on_role()
123121

124-
if name_updated:
122+
if was_updated:
125123
device_registry = dr.async_get(self._hass)
126124
device = device_registry.async_get_device(identifiers={(DOMAIN, self._mac)})
127-
128-
if device and device.name != self._device_name:
129-
# Update the device name
130-
device_registry.async_update_device(device.id, name=self._device_name)
131-
132-
entity_registry = er.async_get(self._hass)
133-
entity_registry.async_update_entity(self.entity_id, name=self._attr_name)
125+
info = self.device_info
126+
if device is not None and info is not None:
127+
# The device registry provides no way of just updating the
128+
# translation_key via dr.async_update_device(), only the
129+
# name. The only way to properly apply the translation to
130+
# the name is through async_get_or_create(), which also
131+
# does apply the update, but requires knowing the config
132+
# entry id. Hoops and roundabouts.
133+
device_registry.async_get_or_create(
134+
config_entry_id = self._config_entry_id,
135+
identifiers = device.identifiers,
136+
translation_key = info["translation_key"],
137+
translation_placeholders = { "id": self._mac },
138+
)
134139

135140
self.async_write_ha_state()
136141

custom_components/powersensor/sensor/powersensor_household_entity.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,14 @@ def fmt_ws_to_kwh(f):
6666
class PowersensorHouseholdEntity(SensorEntity):
6767
"""Powersensor Virtual Household entity."""
6868

69-
should_poll = False
70-
_attr_has_entity_name = True
7169
_attr_available = True
70+
_attr_has_entity_name = True
71+
_attr_should_poll = False
7272

7373
_ENTITY_CONFIGS = {
7474
HouseholdMeasurements.POWER_HOME_USE: PowersensorVirtualHouseholdSensorEntityDescription(
7575
key="Power - Home use",
76+
translation_key="power_home_use",
7677
device_class=SensorDeviceClass.POWER,
7778
native_unit_of_measurement=UnitOfPower.WATT,
7879
state_class=SensorStateClass.MEASUREMENT,
@@ -82,6 +83,7 @@ class PowersensorHouseholdEntity(SensorEntity):
8283
),
8384
HouseholdMeasurements.POWER_FROM_GRID: PowersensorVirtualHouseholdSensorEntityDescription(
8485
key="Power - From grid",
86+
translation_key="power_from_grid",
8587
device_class=SensorDeviceClass.POWER,
8688
native_unit_of_measurement=UnitOfPower.WATT,
8789
state_class=SensorStateClass.MEASUREMENT,
@@ -91,6 +93,7 @@ class PowersensorHouseholdEntity(SensorEntity):
9193
),
9294
HouseholdMeasurements.POWER_TO_GRID: PowersensorVirtualHouseholdSensorEntityDescription(
9395
key="Power - To grid",
96+
translation_key="power_to_grid",
9497
device_class=SensorDeviceClass.POWER,
9598
native_unit_of_measurement=UnitOfPower.WATT,
9699
state_class=SensorStateClass.MEASUREMENT,
@@ -100,6 +103,7 @@ class PowersensorHouseholdEntity(SensorEntity):
100103
),
101104
HouseholdMeasurements.POWER_SOLAR_GENERATION: PowersensorVirtualHouseholdSensorEntityDescription(
102105
key="Power - Solar generation",
106+
translation_key="power_solar_generation",
103107
device_class=SensorDeviceClass.POWER,
104108
native_unit_of_measurement=UnitOfPower.WATT,
105109
state_class=SensorStateClass.MEASUREMENT,
@@ -109,6 +113,7 @@ class PowersensorHouseholdEntity(SensorEntity):
109113
),
110114
HouseholdMeasurements.ENERGY_HOME_USE: PowersensorVirtualHouseholdSensorEntityDescription(
111115
key="Energy - Home usage",
116+
translation_key="energy_home_use",
112117
device_class=SensorDeviceClass.ENERGY,
113118
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
114119
state_class=SensorStateClass.TOTAL_INCREASING,
@@ -118,6 +123,7 @@ class PowersensorHouseholdEntity(SensorEntity):
118123
),
119124
HouseholdMeasurements.ENERGY_FROM_GRID: PowersensorVirtualHouseholdSensorEntityDescription(
120125
key="Energy - From grid",
126+
translation_key="energy_from_grid",
121127
device_class=SensorDeviceClass.ENERGY,
122128
state_class=SensorStateClass.TOTAL_INCREASING,
123129
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
@@ -127,6 +133,7 @@ class PowersensorHouseholdEntity(SensorEntity):
127133
),
128134
HouseholdMeasurements.ENERGY_TO_GRID: PowersensorVirtualHouseholdSensorEntityDescription(
129135
key="Energy - To grid",
136+
translation_key="energy_to_grid",
130137
device_class=SensorDeviceClass.ENERGY,
131138
state_class=SensorStateClass.TOTAL_INCREASING,
132139
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
@@ -136,6 +143,7 @@ class PowersensorHouseholdEntity(SensorEntity):
136143
),
137144
HouseholdMeasurements.ENERGY_SOLAR_GENERATION: PowersensorVirtualHouseholdSensorEntityDescription(
138145
key="Energy - Solar generation",
146+
translation_key="energy_solar_generation",
139147
device_class=SensorDeviceClass.ENERGY,
140148
state_class=SensorStateClass.TOTAL_INCREASING,
141149
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
@@ -150,10 +158,8 @@ def __init__(
150158
) -> None:
151159
"""Initialize the entity."""
152160
self._vhh = vhh
153-
self._attr_should_poll = False
154161
self._config = self._ENTITY_CONFIGS[measurement_type]
155162

156-
self._attr_name = self._config.key
157163
self._attr_unique_id = f"vhh_{self._config.event}"
158164

159165
self.entity_description = self._config
@@ -165,7 +171,7 @@ def device_info(self) -> DeviceInfo:
165171
"identifiers": {(DOMAIN, "vhh")},
166172
"manufacturer": "Powersensor",
167173
"model": "Virtual",
168-
"name": "Powersensor Household View 🏠",
174+
"translation_key": "virtual_household_view",
169175
}
170176

171177
async def async_added_to_hass(self):

0 commit comments

Comments
 (0)