From 0f66b31769787b0544e7519457bd168114e456f1 Mon Sep 17 00:00:00 2001 From: raph666 Date: Tue, 21 Jul 2026 14:45:24 +0200 Subject: [PATCH] Fix entity translations --- CHANGELOG.md | 8 +++ README.md | 2 +- custom_components/arkteos/binary_sensor.py | 2 +- custom_components/arkteos/manifest.json | 2 +- custom_components/arkteos/sensor.py | 1 + custom_components/arkteos/strings.json | 3 + .../arkteos/translations/en.json | 65 +++++++++++++++++++ .../arkteos/translations/fr.json | 3 + tests/test_binary_sensor.py | 12 ++++ tests/test_sensor.py | 26 ++++++++ 10 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 custom_components/arkteos/translations/en.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1a552..74becf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.1.3] - 2026-07-21 + +### Fixed + +- Remplacement des noms génériques des entités par leurs noms fonctionnels. +- Ajout des clés de traduction pour tous les capteurs et le capteur de + connectivité. + ## [0.1.2] - 2026-07-21 ### Added diff --git a/README.md b/README.md index fd59972..822db65 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ni de Node-RED une fois la migration terminée. ## État du projet -- Version actuelle : `0.1.2`. +- Version actuelle : `0.1.3`. - Statut : expérimental. - Testée avec les captures d’une Arkteos Zuran 4. - Le protocole n’est pas officiellement documenté. diff --git a/custom_components/arkteos/binary_sensor.py b/custom_components/arkteos/binary_sensor.py index 6301dd0..2d67b6c 100644 --- a/custom_components/arkteos/binary_sensor.py +++ b/custom_components/arkteos/binary_sensor.py @@ -23,7 +23,7 @@ async def async_setup_entry(hass, entry, async_add_entities: AddEntitiesCallback class ArkteosConnectionBinarySensor(ArkteosEntity, BinarySensorEntity): """Expose la disponibilité du flux lu depuis le proxy.""" - _attr_translation_key = "connection" + _attr_translation_key = "connectivity" _attr_unique_id = "arkteos_zuran4_connection" _attr_device_class = BinarySensorDeviceClass.CONNECTIVITY _attr_device_info = DeviceInfo( diff --git a/custom_components/arkteos/manifest.json b/custom_components/arkteos/manifest.json index dd93a83..92d26dc 100644 --- a/custom_components/arkteos/manifest.json +++ b/custom_components/arkteos/manifest.json @@ -3,7 +3,7 @@ "name": "Arkteos", "config_flow": true, "iot_class": "local_push", - "version": "0.1.2", + "version": "0.1.3", "requirements": [], "documentation": "https://gitea.i-host.fr/raph666/home-assistant-arkteos", "issue_tracker": "https://gitea.i-host.fr/raph666/home-assistant-arkteos/issues", diff --git a/custom_components/arkteos/sensor.py b/custom_components/arkteos/sensor.py index 0f893e4..0e0cded 100644 --- a/custom_components/arkteos/sensor.py +++ b/custom_components/arkteos/sensor.py @@ -331,6 +331,7 @@ class ArkteosSensor(ArkteosEntity, SensorEntity): def __init__(self, client: ArkteosClient, description: ArkteosSensorDescription) -> None: super().__init__(client) self.entity_description = description + self._attr_translation_key = description.translation_key self._attr_unique_id = f"arkteos_zuran4_{description.key}" latest_data = self._latest_data() self._has_received_frame = latest_data is not None diff --git a/custom_components/arkteos/strings.json b/custom_components/arkteos/strings.json index 84e60c5..f72d5e1 100644 --- a/custom_components/arkteos/strings.json +++ b/custom_components/arkteos/strings.json @@ -35,6 +35,9 @@ "binary_sensor": { "connection": { "name": "PAC connectée" + }, + "connectivity": { + "name": "Connexion" } }, "sensor": { diff --git a/custom_components/arkteos/translations/en.json b/custom_components/arkteos/translations/en.json new file mode 100644 index 0000000..ce70b63 --- /dev/null +++ b/custom_components/arkteos/translations/en.json @@ -0,0 +1,65 @@ +{ + "title": "Arkteos", + "config": { + "step": { + "user": { + "title": "Configure Arkteos", + "description": "Enter the Arkteos TCP proxy details.", + "data": {"host": "Proxy host", "port": "Proxy port"} + }, + "reconfigure": { + "title": "Reconfigure Arkteos", + "description": "Change the proxy host or port.", + "data": {"host": "Proxy host", "port": "Proxy port"} + } + }, + "error": { + "cannot_connect": "Cannot connect to the proxy.", + "invalid_host": "The host is invalid.", + "invalid_port": "The port must be between 1 and 65535.", + "timeout": "No valid frame was received before timeout.", + "unknown": "Unexpected error." + }, + "abort": { + "already_configured": "This proxy is already configured.", + "reconfigure_successful": "Arkteos has been reconfigured." + } + }, + "entity": { + "binary_sensor": {"connectivity": {"name": "Connection"}}, + "sensor": { + "exterieur_temp": {"name": "Outdoor temperature"}, + "nb_degivrages": {"name": "Defrost count"}, + "temps_compresseur": {"name": "Compressor operating time"}, + "nb_cycles_compresseur": {"name": "Compressor cycle count"}, + "freq_comp_actuelle": {"name": "Current compressor frequency"}, + "freq_comp_cible": {"name": "Target compressor frequency"}, + "fan_speed_evaporator_1": {"name": "Refrigeration unit fan speed"}, + "dc_voltage": {"name": "Compressor DC voltage"}, + "statut_frigo_s": {"name": "Refrigeration status"}, + "statut_frigo": {"name": "Refrigeration status code"}, + "active_error_fri": {"name": "Active refrigeration error"}, + "puissance_inst_produite": {"name": "Instantaneous produced power"}, + "puissance_inst_consommee": {"name": "Instantaneous consumed power"}, + "temps_mise_sous_tension": {"name": "Power-on time"}, + "modele_pac_s": {"name": "Heat pump model"}, + "modele_pac": {"name": "Heat pump model code"}, + "primaire_temp_eau_aller_consigne": {"name": "Primary water supply setpoint"}, + "primaire_temp_eau_aller": {"name": "Primary water supply temperature"}, + "primaire_temp_eau_retour": {"name": "Primary water return temperature"}, + "primaire_debit_eau": {"name": "Primary water flow rate"}, + "primaire_pression": {"name": "Primary water pressure"}, + "primaire_circulateur_consigne": {"name": "Primary circulator"}, + "zone1_temp_interieur": {"name": "Zone 1 indoor temperature"}, + "zone1_consigne": {"name": "Zone 1 temperature setpoint"}, + "ecs_temp_eau_milieu": {"name": "DHW tank middle temperature"}, + "ecs_temp_eau_bas": {"name": "DHW tank bottom temperature"}, + "ecs_consigne": {"name": "DHW setpoint"}, + "nb_cycles_compresseur_reg": {"name": "Control compressor cycle count"}, + "statut_pac_s": {"name": "Heat pump status"}, + "statut_pac": {"name": "Heat pump status code"}, + "active_error_reg": {"name": "Active control error"}, + "signal_rf_sonde_1": {"name": "Zone 1 sensor RF signal"} + } + } +} diff --git a/custom_components/arkteos/translations/fr.json b/custom_components/arkteos/translations/fr.json index 84e60c5..f72d5e1 100644 --- a/custom_components/arkteos/translations/fr.json +++ b/custom_components/arkteos/translations/fr.json @@ -35,6 +35,9 @@ "binary_sensor": { "connection": { "name": "PAC connectée" + }, + "connectivity": { + "name": "Connexion" } }, "sensor": { diff --git a/tests/test_binary_sensor.py b/tests/test_binary_sensor.py index 9fc9873..9ac5be0 100644 --- a/tests/test_binary_sensor.py +++ b/tests/test_binary_sensor.py @@ -2,6 +2,8 @@ from __future__ import annotations +import json +from pathlib import Path from unittest.mock import Mock from custom_components.arkteos.binary_sensor import ArkteosConnectionBinarySensor @@ -28,6 +30,16 @@ def test_unique_id_is_stable() -> None: assert ArkteosConnectionBinarySensor(FakeClient()).unique_id == "arkteos_zuran4_connection" +def test_connectivity_translation_is_present_and_specific() -> None: + entity = ArkteosConnectionBinarySensor(FakeClient()) + french = json.loads( + (Path(__file__).parents[1] / "custom_components" / "arkteos" / "translations" / "fr.json").read_text() + ) + assert entity.has_entity_name + assert entity.translation_key == "connectivity" + assert french["entity"]["binary_sensor"]["connectivity"]["name"] == "Connexion" + + def test_device_info_is_correct() -> None: info = ArkteosConnectionBinarySensor(FakeClient()).device_info assert info["identifiers"] == {(DOMAIN, "arkteos_zuran4")} diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 00b703a..fd601ee 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -2,6 +2,7 @@ from __future__ import annotations +import json from pathlib import Path from unittest.mock import Mock @@ -89,6 +90,31 @@ def test_total_sensor_count_and_unique_ids() -> None: sensors = _sensors(FakeClient()) assert len(sensors) == 32 assert len({sensor.unique_id for sensor in sensors}) == len(sensors) + assert {sensor.unique_id for sensor in sensors} == { + f"arkteos_zuran4_{description.key}" for description in SENSOR_DESCRIPTIONS + } + + +def test_sensor_translation_keys_are_specific_and_translated() -> None: + translations_path = Path(__file__).parents[1] / "custom_components" / "arkteos" / "translations" + french_sensors = json.loads((translations_path / "fr.json").read_text())["entity"]["sensor"] + english_sensors = json.loads((translations_path / "en.json").read_text())["entity"]["sensor"] + translation_keys = [description.translation_key for description in SENSOR_DESCRIPTIONS] + + assert all(translation_keys) + assert len(translation_keys) == len(set(translation_keys)) + assert set(translation_keys) == set(french_sensors) == set(english_sensors) + assert all("name" in french_sensors[key] for key in translation_keys) + assert all("name" in english_sensors[key] for key in translation_keys) + assert not {"Temperature", "Power", "Frequency", "Duration", "Pressure", "Voltage", "Volume flow rate"} & { + english_sensors[key]["name"] for key in translation_keys + } + + +def test_entities_expose_their_description_translation_key() -> None: + sensors = _sensors(FakeClient()) + assert all(sensor.has_entity_name for sensor in sensors) + assert all(sensor.translation_key == sensor.entity_description.translation_key for sensor in sensors) def test_all_node_red_keys_are_described() -> None: