Don't translate state names in default agent responses (#136382)

Don't translate state names in responses
This commit is contained in:
Michael Hansen 2025-01-23 16:03:48 -06:00 committed by GitHub
parent a12255ea5d
commit 414fa4125e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 34 deletions

View File

@ -798,36 +798,13 @@ class DefaultAgent(ConversationEntity):
intent_response: intent.IntentResponse, intent_response: intent.IntentResponse,
recognize_result: RecognizeResult, recognize_result: RecognizeResult,
) -> str: ) -> str:
# Make copies of the states here so we can add translated names for responses.
matched = [
state_copy
for state in intent_response.matched_states
if (state_copy := core.State.from_dict(state.as_dict()))
]
unmatched = [
state_copy
for state in intent_response.unmatched_states
if (state_copy := core.State.from_dict(state.as_dict()))
]
all_states = matched + unmatched
domains = {state.domain for state in all_states}
translations = await translation.async_get_translations(
self.hass, language, "entity_component", domains
)
# Use translated state names
for state in all_states:
device_class = state.attributes.get("device_class", "_")
key = f"component.{state.domain}.entity_component.{device_class}.state.{state.state}"
state.state = translations.get(key, state.state)
# Get first matched or unmatched state. # Get first matched or unmatched state.
# This is available in the response template as "state". # This is available in the response template as "state".
state1: core.State | None = None state1: core.State | None = None
if intent_response.matched_states: if intent_response.matched_states:
state1 = matched[0] state1 = intent_response.matched_states[0]
elif intent_response.unmatched_states: elif intent_response.unmatched_states:
state1 = unmatched[0] state1 = intent_response.unmatched_states[0]
# Render response template # Render response template
speech_slots = { speech_slots = {
@ -849,11 +826,13 @@ class DefaultAgent(ConversationEntity):
"query": { "query": {
# Entity states that matched the query (e.g, "on") # Entity states that matched the query (e.g, "on")
"matched": [ "matched": [
template.TemplateState(self.hass, state) for state in matched template.TemplateState(self.hass, state)
for state in intent_response.matched_states
], ],
# Entity states that did not match the query # Entity states that did not match the query
"unmatched": [ "unmatched": [
template.TemplateState(self.hass, state) for state in unmatched template.TemplateState(self.hass, state)
for state in intent_response.unmatched_states
], ],
}, },
} }
@ -1506,12 +1485,6 @@ def _get_match_error_response(
# Entity is not in correct state # Entity is not in correct state
assert constraints.states assert constraints.states
state = next(iter(constraints.states)) state = next(iter(constraints.states))
if constraints.domains:
# Translate if domain is available
domain = next(iter(constraints.domains))
state = translation.async_translate_state(
hass, state, domain, None, None, None
)
return ErrorKey.ENTITY_WRONG_STATE, {"state": state} return ErrorKey.ENTITY_WRONG_STATE, {"state": state}

View File

@ -11,7 +11,7 @@ import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
import yaml import yaml
from homeassistant.components import conversation, cover, media_player from homeassistant.components import conversation, cover, media_player, weather
from homeassistant.components.conversation import default_agent from homeassistant.components.conversation import default_agent
from homeassistant.components.conversation.const import DATA_DEFAULT_ENTITY from homeassistant.components.conversation.const import DATA_DEFAULT_ENTITY
from homeassistant.components.conversation.default_agent import METADATA_CUSTOM_SENTENCE from homeassistant.components.conversation.default_agent import METADATA_CUSTOM_SENTENCE
@ -3152,3 +3152,29 @@ async def test_handle_intents_with_response_errors(
assert response is not None and response.error_code == error_code assert response is not None and response.error_code == error_code
else: else:
assert response is None assert response is None
@pytest.mark.usefixtures("init_components")
async def test_state_names_are_not_translated(
hass: HomeAssistant,
init_components: None,
) -> None:
"""Test that state names are not translated in responses."""
await async_setup_component(hass, "weather", {})
hass.states.async_set("weather.test_weather", weather.ATTR_CONDITION_PARTLYCLOUDY)
expose_entity(hass, "weather.test_weather", True)
with patch(
"homeassistant.helpers.template.Template.async_render"
) as mock_async_render:
result = await conversation.async_converse(
hass, "what is the weather like?", None, Context(), None
)
assert result.response.response_type == intent.IntentResponseType.QUERY_ANSWER
mock_async_render.assert_called_once()
assert (
mock_async_render.call_args.args[0]["state"].state
== weather.ATTR_CONDITION_PARTLYCLOUDY
)