diff --git a/custom_components/birthdays/__init__.py b/custom_components/birthdays/__init__.py index 23fe187..7948f73 100644 --- a/custom_components/birthdays/__init__.py +++ b/custom_components/birthdays/__init__.py @@ -1,4 +1,5 @@ import asyncio +from dataclasses import dataclass import logging import voluptuous as vol @@ -8,6 +9,7 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.event import async_call_later from homeassistant.helpers.template import Template, is_template_string, render_complex +from homeassistant.helpers.translation import async_get_translations from homeassistant.util import dt as dt_util, slugify _LOGGER = logging.getLogger(__name__) @@ -54,11 +56,18 @@ ), extra=vol.ALLOW_EXTRA) +@dataclass +class Translation: + single_day_unit: str + multiple_days_unit: str + + async def async_setup(hass, config): devices = [] is_new_config = isinstance(config[DOMAIN], dict) and config[DOMAIN].get(CONF_BIRTHDAYS) is not None birthdays = config[DOMAIN][CONF_BIRTHDAYS] if is_new_config else config[DOMAIN] + translation = await _get_translation(hass) for birthday_data in birthdays: unique_id = birthday_data.get(CONF_UNIQUE_ID) @@ -69,13 +78,16 @@ async def async_setup(hass, config): if is_new_config: global_config = config[DOMAIN][CONF_GLOBAL_CONFIG] # Empty dict or has attributes global_attributes = global_config.get(CONF_ATTRIBUTES) or {} - attributes = dict(global_attributes, **attributes) # Add global_attributes but let local attributes be on top + attributes = dict(global_attributes, + **attributes) # Add global_attributes but let local attributes be on top - devices.append(BirthdayEntity(unique_id, name, date_of_birth, icon, attributes, hass)) + devices.append(BirthdayEntity(unique_id, name, date_of_birth, icon, attributes, translation, hass)) + # Set up component component = EntityComponent(_LOGGER, DOMAIN, hass) await component.async_add_entities(devices) + # Update state tasks = [asyncio.create_task(device.update_data()) for device in devices] await asyncio.wait(tasks) @@ -84,9 +96,25 @@ async def async_setup(hass, config): return True +async def _get_translation(hass) -> Translation: + """Fetch the translated units of measurement and update each sensor.""" + category = "config" + translations = await async_get_translations(hass, + language=hass.config.language, + category=category, + integrations=[DOMAIN]) + + base_key = f'component.{DOMAIN}.{category}.unit_of_measurement' + + single_day_unit = translations.get(f'{base_key}.single_day', 'day') + multiple_days_unit = translations.get(f'{base_key}.multiple_days', 'days') + + return Translation(single_day_unit=single_day_unit, multiple_days_unit=multiple_days_unit) + + class BirthdayEntity(Entity): - def __init__(self, unique_id, name, date_of_birth, icon, attributes, hass): + def __init__(self, unique_id, name, date_of_birth, icon, attributes, translation, hass): self._name = name if unique_id is not None: @@ -112,6 +140,8 @@ def __init__(self, unique_id, name, date_of_birth, icon, attributes, hass): else: self._extra_state_attributes[k] = v + self._translation: Translation = translation + @property def name(self): return self._name @@ -147,13 +177,16 @@ def date_of_birth(self): @property def unit_of_measurement(self): - return 'days' + return self._translation.single_day_unit \ + if self._state is not None and self._state == 1 \ + else self._translation.multiple_days_unit @property def hidden(self): return self._state is None - def _get_seconds_until_midnight(self): + @staticmethod + def _get_seconds_until_midnight(): one_day_in_seconds = 24 * 60 * 60 now = dt_util.now() diff --git a/custom_components/birthdays/manifest.json b/custom_components/birthdays/manifest.json index 7449d19..648a2d3 100644 --- a/custom_components/birthdays/manifest.json +++ b/custom_components/birthdays/manifest.json @@ -5,5 +5,5 @@ "dependencies": [], "codeowners": ["@Miicroo"], "requirements": [], - "version": "1.0.0" + "version": "1.2.0" } diff --git a/custom_components/birthdays/translations/en.json b/custom_components/birthdays/translations/en.json new file mode 100644 index 0000000..67fb2b4 --- /dev/null +++ b/custom_components/birthdays/translations/en.json @@ -0,0 +1,8 @@ +{ + "config": { + "unit_of_measurement": { + "single_day": "day", + "multiple_days": "days" + } + } +} \ No newline at end of file diff --git a/custom_components/birthdays/translations/nl.json b/custom_components/birthdays/translations/nl.json new file mode 100644 index 0000000..96a222f --- /dev/null +++ b/custom_components/birthdays/translations/nl.json @@ -0,0 +1,8 @@ +{ + "config": { + "unit_of_measurement": { + "single_day": "dag", + "multiple_days": "dagen" + } + } +} \ No newline at end of file diff --git a/custom_components/birthdays/translations/sv.json b/custom_components/birthdays/translations/sv.json new file mode 100644 index 0000000..1b55e30 --- /dev/null +++ b/custom_components/birthdays/translations/sv.json @@ -0,0 +1,8 @@ +{ + "config": { + "unit_of_measurement": { + "single_day": "dag", + "multiple_days": "dagar" + } + } +} \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 1d99892..f15a4ec 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,24 @@ """pytest fixtures.""" +from unittest.mock import patch + import pytest +from custom_components.birthdays import Translation + @pytest.fixture(autouse=True) def auto_enable_custom_integrations(enable_custom_integrations): """Enable custom integrations defined in the test dir.""" yield + + +@pytest.fixture(autouse=True) +def mock_translations(): + """Mock translations globally.""" + translation = Translation(single_day_unit="day", multiple_days_unit="days") + with patch( + "custom_components.birthdays._get_translation", + return_value=translation, + autospec=True, + ) as m: + yield m