mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 16:57:10 +00:00
Take integration title from manifest if not translated (#34283)
This commit is contained in:
parent
3d9ae1b8bd
commit
94a3cec4bf
@ -1,5 +1,4 @@
|
||||
{
|
||||
"title": "Philips Hue",
|
||||
"config": {
|
||||
"step": {
|
||||
"init": {
|
||||
|
@ -1,8 +1,11 @@
|
||||
"""Translation string lookup helpers."""
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, Dict, Iterable, Optional
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.loader import (
|
||||
Integration,
|
||||
async_get_config_flows,
|
||||
async_get_integration,
|
||||
bind_hass,
|
||||
@ -32,8 +35,9 @@ def flatten(data: Dict) -> Dict[str, Any]:
|
||||
return recursive_flatten("", data)
|
||||
|
||||
|
||||
async def component_translation_file(
|
||||
hass: HomeAssistantType, component: str, language: str
|
||||
@callback
|
||||
def component_translation_file(
|
||||
component: str, language: str, integration: Integration
|
||||
) -> Optional[str]:
|
||||
"""Return the translation json file location for a component.
|
||||
|
||||
@ -49,9 +53,6 @@ async def component_translation_file(
|
||||
domain = parts[-1]
|
||||
is_platform = len(parts) == 2
|
||||
|
||||
integration = await async_get_integration(hass, domain)
|
||||
assert integration is not None, domain
|
||||
|
||||
if is_platform:
|
||||
filename = f"{parts[0]}.{language}.json"
|
||||
return str(integration.file_path / ".translations" / filename)
|
||||
@ -105,26 +106,47 @@ def build_resources(
|
||||
async def async_get_component_resources(
|
||||
hass: HomeAssistantType, language: str
|
||||
) -> Dict[str, Any]:
|
||||
"""Return translation resources for all components."""
|
||||
if TRANSLATION_STRING_CACHE not in hass.data:
|
||||
hass.data[TRANSLATION_STRING_CACHE] = {}
|
||||
if language not in hass.data[TRANSLATION_STRING_CACHE]:
|
||||
hass.data[TRANSLATION_STRING_CACHE][language] = {}
|
||||
translation_cache = hass.data[TRANSLATION_STRING_CACHE][language]
|
||||
"""Return translation resources for all components.
|
||||
|
||||
# Get the set of components
|
||||
We go through all loaded components and platforms:
|
||||
- see if they have already been loaded (exist in translation_cache)
|
||||
- load them if they have not been loaded yet
|
||||
- write them to cache
|
||||
- flatten the cache and return
|
||||
"""
|
||||
# Get cache for this language
|
||||
cache = hass.data.setdefault(TRANSLATION_STRING_CACHE, {})
|
||||
translation_cache = cache.setdefault(language, {})
|
||||
|
||||
# Get the set of components to check
|
||||
components = hass.config.components | await async_get_config_flows(hass)
|
||||
|
||||
# Calculate the missing components
|
||||
missing_components = components - set(translation_cache)
|
||||
# Calculate the missing components and platforms
|
||||
missing_loaded = components - set(translation_cache)
|
||||
missing_domains = {loaded.split(".")[-1] for loaded in missing_loaded}
|
||||
|
||||
missing_integrations = dict(
|
||||
zip(
|
||||
missing_domains,
|
||||
await asyncio.gather(
|
||||
*[async_get_integration(hass, domain) for domain in missing_domains]
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
# Determine paths of missing components/platforms
|
||||
missing_files = {}
|
||||
for component in missing_components:
|
||||
path = await component_translation_file(hass, component, language)
|
||||
for loaded in missing_loaded:
|
||||
parts = loaded.split(".")
|
||||
domain = parts[-1]
|
||||
integration = missing_integrations[domain]
|
||||
|
||||
path = component_translation_file(loaded, language, integration)
|
||||
# No translation available
|
||||
if path is None:
|
||||
translation_cache[component] = {}
|
||||
translation_cache[loaded] = {}
|
||||
else:
|
||||
missing_files[component] = path
|
||||
missing_files[loaded] = path
|
||||
|
||||
# Load missing files
|
||||
if missing_files:
|
||||
@ -134,6 +156,14 @@ async def async_get_component_resources(
|
||||
assert load_translations_job is not None
|
||||
loaded_translations = await load_translations_job
|
||||
|
||||
# Translations that miss "title" will get integration put in.
|
||||
for loaded, translations in loaded_translations.items():
|
||||
if "." in loaded:
|
||||
continue
|
||||
|
||||
if "title" not in translations:
|
||||
translations["title"] = missing_integrations[loaded].name
|
||||
|
||||
# Update cache
|
||||
translation_cache.update(loaded_translations)
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
"""Test the translation helper."""
|
||||
# pylint: disable=protected-access
|
||||
import asyncio
|
||||
from os import path
|
||||
from unittest.mock import patch
|
||||
import pathlib
|
||||
|
||||
from asynctest import Mock, patch
|
||||
import pytest
|
||||
|
||||
from homeassistant.generated import config_flows
|
||||
import homeassistant.helpers.translation as translation
|
||||
from homeassistant.loader import async_get_integration
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import mock_coro
|
||||
@ -43,14 +45,28 @@ async def test_component_translation_file(hass):
|
||||
assert await async_setup_component(hass, "test_standalone", {"test_standalone"})
|
||||
assert await async_setup_component(hass, "test_package", {"test_package"})
|
||||
|
||||
(
|
||||
int_test,
|
||||
int_test_embedded,
|
||||
int_test_standalone,
|
||||
int_test_package,
|
||||
) = await asyncio.gather(
|
||||
async_get_integration(hass, "test"),
|
||||
async_get_integration(hass, "test_embedded"),
|
||||
async_get_integration(hass, "test_standalone"),
|
||||
async_get_integration(hass, "test_package"),
|
||||
)
|
||||
|
||||
assert path.normpath(
|
||||
await translation.component_translation_file(hass, "switch.test", "en")
|
||||
translation.component_translation_file("switch.test", "en", int_test)
|
||||
) == path.normpath(
|
||||
hass.config.path("custom_components", "test", ".translations", "switch.en.json")
|
||||
)
|
||||
|
||||
assert path.normpath(
|
||||
await translation.component_translation_file(hass, "switch.test_embedded", "en")
|
||||
translation.component_translation_file(
|
||||
"switch.test_embedded", "en", int_test_embedded
|
||||
)
|
||||
) == path.normpath(
|
||||
hass.config.path(
|
||||
"custom_components", "test_embedded", ".translations", "switch.en.json"
|
||||
@ -58,12 +74,14 @@ async def test_component_translation_file(hass):
|
||||
)
|
||||
|
||||
assert (
|
||||
await translation.component_translation_file(hass, "test_standalone", "en")
|
||||
translation.component_translation_file(
|
||||
"test_standalone", "en", int_test_standalone
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
assert path.normpath(
|
||||
await translation.component_translation_file(hass, "test_package", "en")
|
||||
translation.component_translation_file("test_package", "en", int_test_package)
|
||||
) == path.normpath(
|
||||
hass.config.path(
|
||||
"custom_components", "test_package", ".translations", "en.json"
|
||||
@ -118,6 +136,8 @@ async def test_get_translations(hass, mock_config_flows):
|
||||
async def test_get_translations_loads_config_flows(hass, mock_config_flows):
|
||||
"""Test the get translations helper loads config flow translations."""
|
||||
mock_config_flows.append("component1")
|
||||
integration = Mock(file_path=pathlib.Path(__file__))
|
||||
integration.name = "Component 1"
|
||||
|
||||
with patch.object(
|
||||
translation, "component_translation_file", return_value=mock_coro("bla.json")
|
||||
@ -125,6 +145,12 @@ async def test_get_translations_loads_config_flows(hass, mock_config_flows):
|
||||
translation,
|
||||
"load_translations_files",
|
||||
return_value={"component1": {"hello": "world"}},
|
||||
), patch(
|
||||
"homeassistant.helpers.translation.async_get_integration",
|
||||
return_value=integration,
|
||||
):
|
||||
translations = await translation.async_get_translations(hass, "en")
|
||||
assert translations == {"component.component1.hello": "world"}
|
||||
assert translations == {
|
||||
"component.component1.title": "Component 1",
|
||||
"component.component1.hello": "world",
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user