Add translation support to Config Entry errors (#106305)
* Config Entry error translation * split key and placeholders * Fix config entries tests * translation optional * Modspull/114371/head
parent
aa9d58df67
commit
fc4d960d17
|
@ -243,7 +243,14 @@ class OperationNotAllowed(ConfigError):
|
|||
|
||||
UpdateListenerType = Callable[[HomeAssistant, "ConfigEntry"], Coroutine[Any, Any, None]]
|
||||
|
||||
FROZEN_CONFIG_ENTRY_ATTRS = {"entry_id", "domain", "state", "reason"}
|
||||
FROZEN_CONFIG_ENTRY_ATTRS = {
|
||||
"entry_id",
|
||||
"domain",
|
||||
"state",
|
||||
"reason",
|
||||
"error_reason_translation_key",
|
||||
"error_reason_translation_placeholders",
|
||||
}
|
||||
UPDATE_ENTRY_CONFIG_ENTRY_ATTRS = {
|
||||
"unique_id",
|
||||
"title",
|
||||
|
@ -274,6 +281,8 @@ class ConfigEntry:
|
|||
unique_id: str | None
|
||||
state: ConfigEntryState
|
||||
reason: str | None
|
||||
error_reason_translation_key: str | None
|
||||
error_reason_translation_placeholders: dict[str, Any] | None
|
||||
pref_disable_new_entities: bool
|
||||
pref_disable_polling: bool
|
||||
version: int
|
||||
|
@ -369,6 +378,8 @@ class ConfigEntry:
|
|||
|
||||
# Reason why config entry is in a failed state
|
||||
_setter(self, "reason", None)
|
||||
_setter(self, "error_reason_translation_key", None)
|
||||
_setter(self, "error_reason_translation_placeholders", None)
|
||||
|
||||
# Function to cancel a scheduled retry
|
||||
self._async_cancel_retry_setup: Callable[[], Any] | None = None
|
||||
|
@ -472,6 +483,8 @@ class ConfigEntry:
|
|||
"pref_disable_polling": self.pref_disable_polling,
|
||||
"disabled_by": self.disabled_by,
|
||||
"reason": self.reason,
|
||||
"error_reason_translation_key": self.error_reason_translation_key,
|
||||
"error_reason_translation_placeholders": self.error_reason_translation_placeholders,
|
||||
}
|
||||
return json_fragment(json_bytes(json_repr))
|
||||
|
||||
|
@ -543,6 +556,8 @@ class ConfigEntry:
|
|||
setup_phase = SetupPhases.CONFIG_ENTRY_PLATFORM_SETUP
|
||||
|
||||
error_reason = None
|
||||
error_reason_translation_key = None
|
||||
error_reason_translation_placeholders = None
|
||||
|
||||
try:
|
||||
with async_start_setup(
|
||||
|
@ -557,6 +572,8 @@ class ConfigEntry:
|
|||
result = False
|
||||
except ConfigEntryError as exc:
|
||||
error_reason = str(exc) or "Unknown fatal config entry error"
|
||||
error_reason_translation_key = exc.translation_key
|
||||
error_reason_translation_placeholders = exc.translation_placeholders
|
||||
_LOGGER.exception(
|
||||
"Error setting up entry %s for %s: %s",
|
||||
self.title,
|
||||
|
@ -569,6 +586,8 @@ class ConfigEntry:
|
|||
message = str(exc)
|
||||
auth_base_message = "could not authenticate"
|
||||
error_reason = message or auth_base_message
|
||||
error_reason_translation_key = exc.translation_key
|
||||
error_reason_translation_placeholders = exc.translation_placeholders
|
||||
auth_message = (
|
||||
f"{auth_base_message}: {message}" if message else auth_base_message
|
||||
)
|
||||
|
@ -583,7 +602,15 @@ class ConfigEntry:
|
|||
result = False
|
||||
except ConfigEntryNotReady as exc:
|
||||
message = str(exc)
|
||||
self._async_set_state(hass, ConfigEntryState.SETUP_RETRY, message or None)
|
||||
error_reason_translation_key = exc.translation_key
|
||||
error_reason_translation_placeholders = exc.translation_placeholders
|
||||
self._async_set_state(
|
||||
hass,
|
||||
ConfigEntryState.SETUP_RETRY,
|
||||
message or None,
|
||||
error_reason_translation_key,
|
||||
error_reason_translation_placeholders,
|
||||
)
|
||||
wait_time = 2 ** min(self._tries, 4) * 5 + (
|
||||
randint(RANDOM_MICROSECOND_MIN, RANDOM_MICROSECOND_MAX) / 1000000
|
||||
)
|
||||
|
@ -644,7 +671,13 @@ class ConfigEntry:
|
|||
if result:
|
||||
self._async_set_state(hass, ConfigEntryState.LOADED, None)
|
||||
else:
|
||||
self._async_set_state(hass, ConfigEntryState.SETUP_ERROR, error_reason)
|
||||
self._async_set_state(
|
||||
hass,
|
||||
ConfigEntryState.SETUP_ERROR,
|
||||
error_reason,
|
||||
error_reason_translation_key,
|
||||
error_reason_translation_placeholders,
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_setup_again(self, hass: HomeAssistant, *_: Any) -> None:
|
||||
|
@ -771,7 +804,12 @@ class ConfigEntry:
|
|||
|
||||
@callback
|
||||
def _async_set_state(
|
||||
self, hass: HomeAssistant, state: ConfigEntryState, reason: str | None
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
state: ConfigEntryState,
|
||||
reason: str | None,
|
||||
error_reason_translation_key: str | None = None,
|
||||
error_reason_translation_placeholders: dict[str, str] | None = None,
|
||||
) -> None:
|
||||
"""Set the state of the config entry."""
|
||||
if state not in NO_RESET_TRIES_STATES:
|
||||
|
@ -779,6 +817,12 @@ class ConfigEntry:
|
|||
_setter = object.__setattr__
|
||||
_setter(self, "state", state)
|
||||
_setter(self, "reason", reason)
|
||||
_setter(self, "error_reason_translation_key", error_reason_translation_key)
|
||||
_setter(
|
||||
self,
|
||||
"error_reason_translation_placeholders",
|
||||
error_reason_translation_placeholders,
|
||||
)
|
||||
self.clear_cache()
|
||||
async_dispatcher_send(
|
||||
hass, SIGNAL_CONFIG_ENTRY_CHANGED, ConfigEntryChange.UPDATED, self
|
||||
|
|
|
@ -131,6 +131,8 @@ async def test_get_entries(hass: HomeAssistant, client, clear_handlers) -> None:
|
|||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
{
|
||||
"domain": "comp2",
|
||||
|
@ -145,6 +147,8 @@ async def test_get_entries(hass: HomeAssistant, client, clear_handlers) -> None:
|
|||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": "Unsupported API",
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
{
|
||||
"domain": "comp3",
|
||||
|
@ -159,6 +163,8 @@ async def test_get_entries(hass: HomeAssistant, client, clear_handlers) -> None:
|
|||
"pref_disable_polling": False,
|
||||
"disabled_by": core_ce.ConfigEntryDisabler.USER,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
{
|
||||
"domain": "comp4",
|
||||
|
@ -173,6 +179,8 @@ async def test_get_entries(hass: HomeAssistant, client, clear_handlers) -> None:
|
|||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
{
|
||||
"domain": "comp5",
|
||||
|
@ -187,6 +195,8 @@ async def test_get_entries(hass: HomeAssistant, client, clear_handlers) -> None:
|
|||
"pref_disable_polling": False,
|
||||
"disabled_by": None,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -536,6 +546,8 @@ async def test_create_account(
|
|||
"pref_disable_polling": False,
|
||||
"title": "Test Entry",
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
"description": None,
|
||||
"description_placeholders": None,
|
||||
|
@ -615,6 +627,8 @@ async def test_two_step_flow(
|
|||
"pref_disable_polling": False,
|
||||
"title": "user-title",
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
"description": None,
|
||||
"description_placeholders": None,
|
||||
|
@ -1058,6 +1072,8 @@ async def test_get_single(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "user",
|
||||
"state": "loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1393,6 +1409,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1408,6 +1426,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": "Unsupported API",
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla2",
|
||||
"state": "setup_error",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1423,6 +1443,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1438,6 +1460,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla4",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1453,6 +1477,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla5",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1479,6 +1505,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1504,6 +1532,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla4",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1519,6 +1549,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla5",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1544,6 +1576,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1559,6 +1593,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1590,6 +1626,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1605,6 +1643,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": "Unsupported API",
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla2",
|
||||
"state": "setup_error",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1620,6 +1660,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1635,6 +1677,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla4",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1650,6 +1694,8 @@ async def test_get_matching_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla5",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1749,6 +1795,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1767,6 +1815,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": "Unsupported API",
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla2",
|
||||
"state": "setup_error",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1785,6 +1835,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1807,6 +1859,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1830,6 +1884,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1853,6 +1909,8 @@ async def test_subscribe_entries_ws(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1935,6 +1993,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1953,6 +2013,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1977,6 +2039,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -1999,6 +2063,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla3",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -2023,6 +2089,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -2046,6 +2114,8 @@ async def test_subscribe_entries_ws_filtered(
|
|||
"pref_disable_new_entities": False,
|
||||
"pref_disable_polling": False,
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
"source": "bla",
|
||||
"state": "not_loaded",
|
||||
"supports_reconfigure": False,
|
||||
|
@ -2225,6 +2295,8 @@ async def test_supports_reconfigure(
|
|||
"pref_disable_polling": False,
|
||||
"title": "Test Entry",
|
||||
"reason": None,
|
||||
"error_reason_translation_key": None,
|
||||
"error_reason_translation_placeholders": None,
|
||||
},
|
||||
"description": None,
|
||||
"description_placeholders": None,
|
||||
|
|
|
@ -821,6 +821,8 @@ async def test_as_dict(snapshot: SnapshotAssertion) -> None:
|
|||
"_setup_lock",
|
||||
"update_listeners",
|
||||
"reason",
|
||||
"error_reason_translation_key",
|
||||
"error_reason_translation_placeholders",
|
||||
"_async_cancel_retry_setup",
|
||||
"_on_unload",
|
||||
"reload_lock",
|
||||
|
|
Loading…
Reference in New Issue