Skip to main content

Raising exceptions with translations

· One min read

Logging exceptions with translation support

Translation support applies to HomeAssistantError and subclasses like ServiceValidationError. When a translation_domain and translation_key is set and the error message is added in strings.json, it is no longer needed to add the error message string for the local logging. Home Assistant will automatically fetch the English error message from the translation cache.

When raising HomeAssistantError or a subclass with translation support we should remove the log message from the argument list to enable it to be fetched from the translation cache.

For example:

async def async_select_index(hass: HomeAssistant, index: int) -> None:
"""Setup the config entry for my device."""
try:
check_index(index)
except ValueError as exc:
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="invalid_index",
translation_placeholders={
"index": index,
"expected": expected,
},
) from exc

The error message is placed in strings.json:

{
...
"exceptions": {
"invalid_index": {
"message": "An invalid index is selected, expected: {expected}, got: {index}"
}
}
}

Deprecating `async_run_job` and `async_add_job`

· One min read

async_run_job and async_add_job are deprecated and will be removed in Home Assistant 2025.4. This deprecation does not apply to the sync API add_job method, which is not planned to be removed.

Instead, it's more efficient to use one of the other job methods, as the method of calling the job does not ever have to be worked out:

If the callable is a coroutine function running from a config entry: entry.async_create_background_task, entry.async_create_task

If the callable is a coroutine function running from another place: hass.async_create_background_task, hass.async_create_task

If the callable should run in the executor: hass.async_add_executor_job

Climate entity auxiliary heater is deprecated

· One min read

As of Home Assistant Core 2024.4 we have deprecated the auxiliary heater functionality in ClimateEntity.

Integrations that are currently implementing the is_aux_heat property and the turn_aux_heat_on/turn_aux_heat_off methods need to remove these and alternatively implement other entities to accommodate the necessary functionality such as a SwitchEntity or in the case of a read-only property a BinarySensorEntity.

You can read more about this decision here.

Integrations import in the executor to avoid blocking the event loop

· One min read

Starting from Home Assistant 2024.4, all integrations are imported in the executor to avoid blocking the event loop while the code is imported and executed.

In the rare event that an integration creates loop-bound objects at import time, this may fail because there is no running loop in the executor.

Custom integrations needing more time to adjust their code to avoid creating such objects can opt-out and continue to have their code imported in the event loop, understanding that system stability will be impacted.

To opt-out of importing in the executor, an integration can add:

"import_executor": false to their manifest.json

Support for platform translations in separate files will be removed

· One min read

The method for integrations to provide translations for states of its entities under other integrations, for example to translate an integration's sensors was changed in November 2022, and support for the old method will be removed in Home Assistant Core 2024.5.0.

Once Home Assistant Core 2024.5.0 is released, integrations can no longer use custom device classes together with a strings.<platform name>.json file. Instead, entities must set the translation_key property on an entity and include that translation_key in the integration's strings.json.

The following example strings.json is for a Moon domain sensor entity with its translation_key property set to phase:

{
"entity": {
"sensor": {
"phase": {
"state": {
"new_moon": "New moon",
"first_quarter": "First quarter",
"full_moon": "Full moon",
"last_quarter": "Last quarter"
}
}
}
}
}

For more details, see the translation and entity documentation.

Introducing device name translations

· One min read

It's now possible to provide translations for device names, including support for static values to be used as placeholders.

An example sensor with a translated device name:

class TestEntity(SensorEntity):
"""Example entity."""

_attr_has_entity_name = True

def __init__(self) -> None:
"""Initialize example entity."""
self._attr_device_info = DeviceInfo(
translation_key="n_ch_power_strip",
translation_placeholders={"number_of_sockets": "2"},
)

The strings.json file would look like:

{
"device": {
"n_ch_power_strip": {
"name": "Power strip with {number_of_sockets} sockets"
}
}
}

The resulting device would be called Power strip with 2 sockets.

A warning is logged when a translation placeholder is expected but not provided by the device. When this happens on a system that is not on a stable version (dev, nightly, or beta), an error will be raised to be able to catch the mistakes quickly.

Please don't forget to be kind towards your translators, as they need to understand what kind of name or value will be passed in from the placeholder name ❤️.

Deprecate use of @bind_hass and hass.components

· 2 min read

As of Home Assistant 2024.3, we deprecate the use of the @bind_hass decorator and thus also the use of hass.components. Using hass.components will issue a warning in the logs. Authors of custom integrations are encouraged to update their code to prevent any issues before Home Assistant 2024.9.

Starting from Home Assistant 2024.9, the @bind_hass decorator and hass.components will be removed and will no longer work.

Use of @bind_hass decorator

Integrations that use the @bind_hass decorator should be updated to remove them and pass the hass object as first parameter to the function instead:

New example

from homeassistant.core import HomeAssistant
from homeassistant.components.persistent_notification import async_create

def create_notification(hass: HomeAssistant, message: str):
"""Create a notification."""
async_create(
hass,
message,
title='Important notification'
)

async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
create_notification(hass, "You're already using the latest version!")

Old example

from homeassistant.core import HomeAssistant
from homeassistant.loader import bind_hass
from homeassistant.components.persistent_notification import async_create

@bind_hass
def create_notification(hass: HomeAssistant, message: str):
"""Create a notification."""
async_create(
hass,
message,
title='Important notification'
)

async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
create_notification("You're already using the latest version!")

Use of hass.components

Integrations that use hass.components should be updated to import the functions and classes directly from the integration package and pass the hass object as first parameter. Remember to include the imported components under dependencies in your manifest.json.

New example

from homeassistant.core import HomeAssistant
from homeassistant.components.persistent_notification import async_create

async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
async_create(
hass,
"You're already using the latest version!",
title='Important notification'
)

Old example

from homeassistant.core import HomeAssistant

async def async_setup(hass: HomeAssistant, config):
"""Set up the component."""
hass.components.persistent_notification.async_create(
"You're already using the latest version!",
title='Important notification'
)

New single instance only manifest option

· One min read

In Home Assistant 2024.3, we introduced a new single_config_entry option for the integration manifest file. This option allows you to set that your integration supports only one config entry.

Home Assistant will take care and prevent the initialization of a config flow if there is already a config entry for the integration. This way you won't have to implement any check in the config flow.

Integrations that have this option not set in their manifest and do the check in the config flow should replace it with the new option.

New Climate entity toggle method

· One min read

As of Home Assistant Core 2024.3 we have added a new toggle method to ClimateEntity and users can now call climate.toggle in their service calls.

Integrations that support turn_on and turn_off implicitly also support the toggle method.

Read more about the toggle method in our documentation

Example (default implementation):

async def async_toggle(self) -> None:
"""Toggle the entity."""
if self.hvac_mode == HVACMode.OFF:
await self.async_turn_on()
else:
await self.async_turn_off()

Altering config entries

· One min read

Starting from Home Assistant 2024.3, modifications to a ConfigEntry should use hass.config_entries.async_update_entry. Directly setting attributes on the ConfigEntry object is deprecated and will start to fail in version 2024.9 and later. There is no deprecation period for directly setting unique_id on the ConfigEntry as doing so will corrupt the internal state, and doing so will start to fail immediately.

The following attributes must now be set via hass.config_entries.async_update_entry:

  • data
  • minor_version
  • options
  • pref_disable_new_entities
  • pref_disable_polling
  • title
  • unique_id
  • version

Tests must ensure that MockConfigEntry objects are added to Home Assistant via entry.add_to_hass(hass) before calling hass.config_entries.async_update_entry.