Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ def websocket_get_themes(
"type": "frontend/get_translations",
vol.Required("language"): str,
vol.Required("category"): str,
vol.Optional("integration"): str,
vol.Optional("integration"): vol.All(cv.ensure_list, [str]),
vol.Optional("config_flow"): bool,
}
)
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/onboarding/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.core import callback
from homeassistant.helpers.system_info import async_get_system_info
from homeassistant.helpers.translation import async_get_translations

from .const import (
DEFAULT_AREAS,
Expand Down Expand Up @@ -147,8 +148,8 @@ async def post(self, request, data):
await person.async_create_person(hass, data["name"], user_id=user.id)

# Create default areas using the users supplied language.
translations = await hass.helpers.translation.async_get_translations(
data["language"], "area", DOMAIN
translations = await async_get_translations(
hass, data["language"], "area", {DOMAIN}
)

area_registry = await hass.helpers.area_registry.async_get_registry()
Expand Down
13 changes: 8 additions & 5 deletions homeassistant/helpers/translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import asyncio
from collections import ChainMap
from collections.abc import Mapping
from collections.abc import Iterable, Mapping
import logging
from typing import Any

Expand Down Expand Up @@ -286,7 +286,7 @@ async def async_get_translations(
hass: HomeAssistant,
language: str,
category: str,
integration: str | None = None,
integrations: Iterable[str] | None = None,
config_flow: bool | None = None,
) -> dict[str, Any]:
"""Return all backend translations.
Expand All @@ -297,8 +297,8 @@ async def async_get_translations(
"""
lock = hass.data.setdefault(TRANSLATION_LOAD_LOCK, asyncio.Lock())

if integration is not None:
components = {integration}
if integrations is not None:
components = set(integrations)
elif config_flow:
components = (await async_get_config_flows(hass)) - hass.config.components
elif category == "state":
Expand All @@ -310,7 +310,10 @@ async def async_get_translations(
}

async with lock:
cache = hass.data.setdefault(TRANSLATION_FLATTEN_CACHE, _TranslationCache(hass))
if TRANSLATION_FLATTEN_CACHE in hass.data:
cache = hass.data[TRANSLATION_FLATTEN_CACHE]
else:
cache = hass.data[TRANSLATION_FLATTEN_CACHE] = _TranslationCache(hass)
cached = await cache.async_fetch(language, category, components)

return dict(ChainMap(*cached))
54 changes: 53 additions & 1 deletion tests/components/frontend/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ async def test_get_translations(hass, ws_client):
"""Test get_translations command."""
with patch(
"homeassistant.components.frontend.async_get_translations",
side_effect=lambda hass, lang, category, integration, config_flow: {
side_effect=lambda hass, lang, category, integrations, config_flow: {
"lang": lang
},
):
Expand All @@ -444,6 +444,58 @@ async def test_get_translations(hass, ws_client):
assert msg["result"] == {"resources": {"lang": "nl"}}


async def test_get_translations_for_integrations(hass, ws_client):
"""Test get_translations for integrations command."""
with patch(
"homeassistant.components.frontend.async_get_translations",
side_effect=lambda hass, lang, category, integration, config_flow: {
"lang": lang,
"integration": integration,
},
):
await ws_client.send_json(
{
"id": 5,
"type": "frontend/get_translations",
"integration": ["frontend", "http"],
"language": "nl",
"category": "lang",
}
)
msg = await ws_client.receive_json()

assert msg["id"] == 5
assert msg["type"] == TYPE_RESULT
assert msg["success"]
assert set(msg["result"]["resources"]["integration"]) == {"frontend", "http"}


async def test_get_translations_for_single_integration(hass, ws_client):
"""Test get_translations for integration command."""
with patch(
"homeassistant.components.frontend.async_get_translations",
side_effect=lambda hass, lang, category, integrations, config_flow: {
"lang": lang,
"integration": integrations,
},
):
await ws_client.send_json(
{
"id": 5,
"type": "frontend/get_translations",
"integration": "http",
"language": "nl",
"category": "lang",
}
)
msg = await ws_client.receive_json()

assert msg["id"] == 5
assert msg["type"] == TYPE_RESULT
assert msg["success"]
assert msg["result"] == {"resources": {"lang": "nl", "integration": ["http"]}}


async def test_auth_load(hass):
"""Test auth component loaded by default."""
frontend = await async_get_integration(hass, "frontend")
Expand Down
29 changes: 23 additions & 6 deletions tests/helpers/test_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,29 @@ async def test_translation_merging_loaded_apart(hass, caplog):
assert "component.sensor.state.moon__phase.first_quarter" in translations

translations = await translation.async_get_translations(
hass, "en", "state", integration="sensor"
hass, "en", "state", integrations={"sensor"}
)

assert "component.sensor.state.moon__phase.first_quarter" in translations


async def test_translation_merging_loaded_together(hass, caplog):
"""Test we merge translations of two integrations when they are loaded at the same time."""
hass.config.components.add("hue")
hass.config.components.add("homekit")
hue_translations = await translation.async_get_translations(
hass, "en", "config", integrations={"hue"}
)
homekit_translations = await translation.async_get_translations(
hass, "en", "config", integrations={"homekit"}
)

translations = await translation.async_get_translations(
hass, "en", "config", integrations={"hue", "homekit"}
)
assert translations == hue_translations | homekit_translations


async def test_caching(hass):
"""Test we cache data."""
hass.config.components.add("sensor")
Expand All @@ -320,14 +337,14 @@ async def test_caching(hass):
)

load_sensor_only = await translation.async_get_translations(
hass, "en", "state", integration="sensor"
hass, "en", "state", integrations={"sensor"}
)
assert load_sensor_only
for key in load_sensor_only:
assert key.startswith("component.sensor.state.")

load_light_only = await translation.async_get_translations(
hass, "en", "state", integration="light"
hass, "en", "state", integrations={"light"}
)
assert load_light_only
for key in load_light_only:
Expand All @@ -341,20 +358,20 @@ async def test_caching(hass):
side_effect=translation._build_resources,
) as mock_build:
load_sensor_only = await translation.async_get_translations(
hass, "en", "title", integration="sensor"
hass, "en", "title", integrations={"sensor"}
)
assert load_sensor_only
for key in load_sensor_only:
assert key == "component.sensor.title"
assert len(mock_build.mock_calls) == 0

assert await translation.async_get_translations(
hass, "en", "title", integration="sensor"
hass, "en", "title", integrations={"sensor"}
)
assert len(mock_build.mock_calls) == 0

load_light_only = await translation.async_get_translations(
hass, "en", "title", integration="media_player"
hass, "en", "title", integrations={"media_player"}
)
assert load_light_only
for key in load_light_only:
Expand Down