Skip to content

Commit 2ec9a49

Browse files
committed
Add translations for entity names
1 parent e1cb634 commit 2ec9a49

File tree

12 files changed

+1950
-90
lines changed

12 files changed

+1950
-90
lines changed

custom_components/xiaomi_gateway3/hass/entity.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,16 @@ def __init__(self, device: "XDevice", conv: "BaseConv"):
6969
via_device=via_device,
7070
)
7171
self._attr_has_entity_name = True
72-
self._attr_name = attr_human_name(conv.attr)
7372
self._attr_should_poll = False
7473
self._attr_unique_id = f"{device.uid}_{conv.attr}"
7574

7675
setup_entity_description(self, conv)
76+
if (
77+
not hasattr(self, "_attr_name")
78+
and not hasattr(self, "_attr_translation_key")
79+
and not self._default_to_device_class_name()
80+
): # unnamed
81+
self._attr_name = attr_human_name(conv.attr)
7782

7883
if entity_name := device.extra.get("entity_name"):
7984
if entity_name.endswith(conv.attr):

custom_components/xiaomi_gateway3/hass/entity_description.py

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from homeassistant.const import CONDUCTIVITY
3232

3333
from ..core.converters.base import BaseConv
34+
from ..core.converters.const import ENTITY_LAZY
3435

3536
# just to reduce the code
3637
CELSIUS = UnitOfTemperature.CELSIUS
@@ -51,6 +52,7 @@
5152
"statistics": "_attr_state_class",
5253
"units": "_attr_native_unit_of_measurement",
5354
"visible": "_attr_entity_registry_visible_default",
55+
"translation_key": "_attr_translation_key",
5456
}
5557

5658
# description with class should be used with "domain.attr"
@@ -63,73 +65,83 @@
6365
"sensor.illuminance": {"class": SENSOR.ILLUMINANCE, "units": LIGHT_LUX},
6466
"sensor.humidity": {"class": SENSOR.HUMIDITY, "units": PERCENTAGE},
6567
"sensor.moisture": {"class": SENSOR.MOISTURE, "units": PERCENTAGE},
66-
"sensor.power": {"class": SENSOR.POWER, "units": UnitOfPower.WATT},
68+
"sensor.power": {"class": SENSOR.POWER, "units": UnitOfPower.WATT, "translation_key": "power"},
6769
"sensor.pressure": {"class": SENSOR.PRESSURE, "units": UnitOfPressure.HPA},
6870
"sensor.temperature": {"class": SENSOR.TEMPERATURE, "units": CELSIUS},
6971
"sensor.voltage": {"class": SENSOR.VOLTAGE, "units": UnitOfElectricPotential.VOLT},
7072
##
7173
# binary sensors with device class
72-
"binary_sensor.contact": {"class": BinarySensorDeviceClass.DOOR},
73-
"binary_sensor.latch": {"class": BinarySensorDeviceClass.LOCK},
74+
"binary_sensor.contact": {"class": BinarySensorDeviceClass.DOOR, "translation_key": "contact"},
75+
"binary_sensor.latch": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "latch"},
7476
"binary_sensor.moisture": {"class": BinarySensorDeviceClass.MOISTURE},
7577
"binary_sensor.plug_detection": {"class": BinarySensorDeviceClass.PLUG},
76-
"binary_sensor.pressure": {"class": BinarySensorDeviceClass.VIBRATION},
77-
"binary_sensor.reverse": {"class": BinarySensorDeviceClass.LOCK},
78-
"binary_sensor.square": {"class": BinarySensorDeviceClass.LOCK},
78+
"binary_sensor.pressure": {"class": BinarySensorDeviceClass.VIBRATION, "translation_key": "pressure"},
79+
"binary_sensor.reverse": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "reverse"},
80+
"binary_sensor.square": {"class": BinarySensorDeviceClass.LOCK, "translation_key": "square"},
7981
"binary_sensor.water_leak": {"class": BinarySensorDeviceClass.MOISTURE},
8082
##
8183
# sensors without device class
82-
"action": {"icon": "mdi:bell"},
83-
"conductivity": {"icon": "mdi:flower", "units": CONDUCTIVITY},
84-
"formaldehyde": {"units": CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER},
85-
"gas_density": {"icon": "mdi:google-circles-communities", "units": "% LEL"},
86-
"rssi": {"units": SIGNAL_STRENGTH_DECIBELS_MILLIWATT},
87-
"smoke_density": {"icon": "mdi:google-circles-communities", "units": "% obs/ft"},
88-
"supply": {"icon": "mdi:gauge", "units": PERCENTAGE},
89-
"tvoc": {"icon": "mdi:cloud", "units": CONCENTRATION_PARTS_PER_BILLION},
90-
"eco_two": {"name": "eCO2", "icon": "mdi:molecule-co2", "units": CONCENTRATION_PARTS_PER_MILLION},
84+
"action": {"icon": "mdi:bell", "translation_key": "action"},
85+
"conductivity": {"icon": "mdi:flower", "units": CONDUCTIVITY, "translation_key": "conductivity"},
86+
"formaldehyde": {"units": CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER, "translation_key": "formaldehyde"},
87+
"gas_density": {"icon": "mdi:google-circles-communities", "units": "% LEL", "translation_key": "gas_density"},
88+
"rssi": {"units": SIGNAL_STRENGTH_DECIBELS_MILLIWATT, "translation_key": "rssi"},
89+
"smoke_density": {"icon": "mdi:google-circles-communities", "units": "% obs/ft", "translation_key": "smoke_density"},
90+
"supply": {"icon": "mdi:gauge", "units": PERCENTAGE, "translation_key": "supply"},
91+
"tvoc": {"icon": "mdi:cloud", "units": CONCENTRATION_PARTS_PER_BILLION, "translation_key": "tvoc"},
92+
"eco_two": {"icon": "mdi:molecule-co2", "units": CONCENTRATION_PARTS_PER_MILLION, "translation_key": "e_co2"},
9193
##
9294
# stats sensors
9395
"binary_sensor.gateway": {
9496
"class": BinarySensorDeviceClass.CONNECTIVITY,
9597
"icon": "mdi:router-wireless",
98+
"translation_key": "gateway",
9699
},
97100
"binary_sensor.ble": {
98101
"class": BinarySensorDeviceClass.CONNECTIVITY,
99102
"category": DIAGNOSTIC,
100103
"icon": "mdi:bluetooth",
104+
"translation_key": "ble",
101105
},
102106
"binary_sensor.mesh": {
103107
"class": BinarySensorDeviceClass.CONNECTIVITY,
104108
"category": DIAGNOSTIC,
105109
"icon": "mdi:bluetooth",
110+
"translation_key": "mesh",
106111
},
107112
"binary_sensor.zigbee": {
108113
"class": BinarySensorDeviceClass.CONNECTIVITY,
109114
"category": DIAGNOSTIC,
110115
"icon": "mdi:zigbee",
116+
"translation_key": "zigbee",
111117
},
112118
"sensor.ble": {
113119
"class": SENSOR.TIMESTAMP,
114120
"category": DIAGNOSTIC,
115121
"icon": "mdi:bluetooth",
122+
"translation_key": "ble",
116123
},
117124
"sensor.mesh": {
118125
"class": SENSOR.TIMESTAMP,
119126
"category": DIAGNOSTIC,
120127
"icon": "mdi:bluetooth",
128+
"translation_key": "mesh",
121129
},
122130
"sensor.zigbee": {
123131
"class": SENSOR.TIMESTAMP,
124132
"category": DIAGNOSTIC,
125133
"icon": "mdi:zigbee",
134+
"translation_key": "zigbee",
126135
},
127136
##
128137
# main controls
129-
"alarm_trigger": {"icon": "mdi:alarm-bell"},
130-
"fan": {"icon": "mdi:fan"},
131-
"outlet": {"icon": "mdi:power-socket-us"},
132-
"plug": {"icon": "mdi:power-plug"},
138+
"alarm_trigger": {"icon": "mdi:alarm-bell", "translation_key": "alarm_trigger"},
139+
"fan": {"icon": "mdi:fan", "translation_key": "fan"},
140+
"light.light": {"name": None},
141+
"switch.channel": {"class": SwitchDeviceClass.SWITCH, "translation_key": "channel"},
142+
"switch.outlet": {"class": SwitchDeviceClass.OUTLET, "icon": "mdi:power-socket-us", "translation_key": "outlet"},
143+
"switch.plug": {"class": SwitchDeviceClass.OUTLET, "icon": "mdi:power-plug", "translation_key": "plug"},
144+
"switch.switch": {"class": SwitchDeviceClass.SWITCH, "translation_key": "switch"},
133145
"usb": {"icon": "mdi:usb-port"},
134146
##
135147
# batteries and energy sensors
@@ -143,11 +155,13 @@
143155
"units": PERCENTAGE,
144156
"category": DIAGNOSTIC,
145157
"enabled": False,
158+
"translation_key": "battery_original",
146159
},
147160
"sensor.battery_voltage": {
148161
"class": SENSOR.VOLTAGE,
149162
"units": UnitOfElectricPotential.MILLIVOLT,
150163
"category": DIAGNOSTIC,
164+
"translation_key": "battery_voltage",
151165
},
152166
"binary_sensor.battery_charging": {
153167
"class": BinarySensorDeviceClass.BATTERY_CHARGING,
@@ -163,43 +177,46 @@
163177
"class": SENSOR.ENERGY,
164178
"statistics": SensorStateClass.TOTAL,
165179
"units": UnitOfEnergy.KILO_WATT_HOUR,
180+
"translation_key": "power_consumption",
166181
},
167182
##
168183
# CONFIG controls
169-
"backlight": {"category": CONFIG, "enabled": False},
170-
"blind_time": {"category": CONFIG, "enabled": False},
171-
"charge_protect": {"category": CONFIG, "enabled": False},
172-
"child_lock": {"category": CONFIG, "enabled": False, "icon": "mdi:baby-carriage"},
173-
"display_unit": {"category": CONFIG, "enabled": False},
174-
"flex_switch": {"category": CONFIG, "enabled": False},
175-
"led": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off"},
176-
"led_reverse": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off"},
177-
"mode": {"category": CONFIG, "enabled": False, "icon": "mdi:cog"},
178-
"motor_reverse": {"category": CONFIG, "enabled": False},
179-
"motor_speed": {"category": CONFIG, "enabled": False},
180-
"power_off_memory": {"category": CONFIG, "enabled": False},
181-
"power_on_state": {"category": CONFIG, "enabled": False},
182-
"sensitivity": {"category": CONFIG, "enabled": False},
183-
"wireless": {"category": CONFIG, "enabled": False},
184+
"backlight": {"category": CONFIG, "enabled": False, "translation_key": "backlight"},
185+
"blind_time": {"category": CONFIG, "enabled": False, "translation_key": "blind_time"},
186+
"charge_protect": {"category": CONFIG, "enabled": False, "translation_key": "charge_protect"},
187+
"child_lock": {"category": CONFIG, "enabled": False, "icon": "mdi:baby-carriage", "translation_key": "child_lock"},
188+
"display_unit": {"category": CONFIG, "enabled": False, "translation_key": "display_unit"},
189+
"flex_switch": {"category": CONFIG, "enabled": False, "translation_key": "flex_switch"},
190+
"led": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off", "translation_key": "led"},
191+
"led_reverse": {"category": CONFIG, "enabled": False, "icon": "mdi:led-off", "translation_key": "led_reverse"},
192+
"mode": {"category": CONFIG, "enabled": False, "icon": "mdi:cog", "translation_key": "mode"},
193+
"motor_reverse": {"category": CONFIG, "enabled": False, "translation_key": "motor_reverse"},
194+
"motor_speed": {"category": CONFIG, "enabled": False, "translation_key": "motor_speed"},
195+
"power_off_memory": {"category": CONFIG, "enabled": False, "translation_key": "power_off_memory"},
196+
"power_on_state": {"category": CONFIG, "enabled": False, "translation_key": "power_on_state"},
197+
"sensitivity": {"category": CONFIG, "enabled": False, "translation_key": "sensitivity"},
198+
"wireless": {"category": CONFIG, "enabled": False, "translation_key": "wireless"},
184199
##
185200
# DIAGNOSTIC controls
186-
"command": {"category": DIAGNOSTIC, "icon": "mdi:apple-keyboard-command"},
187-
"data": {"category": DIAGNOSTIC, "icon": "mdi:information-box"},
201+
"command": {"category": DIAGNOSTIC, "icon": "mdi:apple-keyboard-command", "translation_key": "command"},
202+
"data": {"category": DIAGNOSTIC, "icon": "mdi:information-box", "translation_key": "data"},
188203
##
189204
# CONFIG and DIAGNOSTIC sensors
190205
"sensor.chip_temperature": {
191206
"class": SENSOR.TEMPERATURE,
192207
"units": UnitOfTemperature.CELSIUS,
193208
"category": DIAGNOSTIC,
194209
"enabled": False,
210+
"translation_key": "chip_temperature",
195211
},
196-
"fault": {"category": DIAGNOSTIC},
212+
"fault": {"category": DIAGNOSTIC, "translation_key": "fault"},
197213
"sensor.idle_time": {
198214
"class": SENSOR.DURATION,
199215
"icon": "mdi:timer",
200216
"units": UnitOfTime.SECONDS,
201217
"category": DIAGNOSTIC,
202218
"enabled": False,
219+
"translation_key": "idle_time",
203220
},
204221
}
205222

@@ -215,6 +232,7 @@
215232
def setup_entity_description(entity: Entity, conv: BaseConv) -> bool:
216233
# 1. auto match entity description based on converter domain and attr name
217234
key = conv.attr.rstrip("_01234567890") # remove tail _1, _2, _3
235+
tail_index = conv.attr[len(key)+1:] # get tail 1, 2, 3
218236
domain_key = f"{conv.domain}.{key}"
219237
desc = ENTITY_DESCRIPTIONS.get(domain_key) or ENTITY_DESCRIPTIONS.get(key)
220238

@@ -223,21 +241,24 @@ def setup_entity_description(entity: Entity, conv: BaseConv) -> bool:
223241
desc = desc | conv.entity if desc else conv.entity
224242

225243
# 3. auto match only device_class based on converter domain
226-
if not desc:
244+
if not desc or desc == ENTITY_LAZY:
227245
if domain_class := DOMAIN_CLASSES.get(conv.domain):
228246
if key in iter(domain_class):
229247
entity._attr_device_class = domain_class(key)
230248
return True
231249
return False
232250

233251
for k, v in desc.items():
234-
if k == "lazy" or v is None:
252+
if k == "lazy" or (v is None and k != "name"):
235253
continue
236254
if k == "category" and type(v) is str:
237255
v = EntityCategory(v)
238256
elif k == "class" and type(v) is str:
239257
if domain_class := DOMAIN_CLASSES.get(conv.domain):
240258
v = domain_class(v)
259+
elif k == "translation_key" and tail_index:
260+
v = f"{v}_n"
261+
setattr(entity, "_attr_translation_placeholders", {"n": tail_index})
241262
setattr(entity, ENTITY_KEYS.get(k) or k, v)
242263

243264
# sensor with unit_of_measurement and without state_class will be MEASUREMENT

custom_components/xiaomi_gateway3/select.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class XCommandSelect(XEntity, SelectEntity):
5757
def on_init(self):
5858
self._attr_current_option = CMD_NONE
5959
self._attr_options = [CMD_NONE, CMD_INFO]
60-
self._attr_translation_key = self.attr
6160

6261
# noinspection PyTypeChecker
6362
self.gw = self.device.gateways[0]
@@ -176,7 +175,6 @@ class XDataSelect(XEntity, SelectEntity):
176175
def on_init(self):
177176
self._attr_current_option = None
178177
self._attr_options = []
179-
self._attr_translation_key = self.attr
180178

181179
self.listen_attrs = {
182180
"data",

0 commit comments

Comments
 (0)