Convert translation helper to use async_get_integration (#23054)

* Convert translation helper to use async_get_integration

* Simplify after comments

* Lint

* Fix typing

* Typo
This commit is contained in:
Paulus Schoutsen 2019-04-12 17:10:19 -07:00 committed by GitHub
parent b767232e50
commit 3f69d0283d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 50 deletions

View File

@ -1,10 +1,9 @@
"""Translation string lookup helpers.""" """Translation string lookup helpers."""
import logging import logging
import pathlib from typing import Any, Dict, Iterable, Optional
from typing import Any, Dict, Iterable
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.loader import get_component, get_platform, bind_hass from homeassistant.loader import async_get_integration, bind_hass
from homeassistant.util.json import load_json from homeassistant.util.json import load_json
from .typing import HomeAssistantType from .typing import HomeAssistantType
@ -30,53 +29,38 @@ def flatten(data: Dict) -> Dict[str, Any]:
return recursive_flatten('', data) return recursive_flatten('', data)
def component_translation_file(hass: HomeAssistantType, component: str, async def component_translation_file(hass: HomeAssistantType, component: str,
language: str) -> str: language: str) -> Optional[str]:
"""Return the translation json file location for a component. """Return the translation json file location for a component.
For component one of: For component:
- components/light/.translations/nl.json - components/hue/.translations/nl.json
- components/.translations/group.nl.json
For platform one of: For platform:
- components/light/.translations/hue.nl.json
- components/hue/.translations/light.nl.json - components/hue/.translations/light.nl.json
If component is just a single file, will return None.
""" """
is_platform = '.' in component parts = component.split('.')
domain = parts[-1]
is_platform = len(parts) == 2
if not is_platform: integration = await async_get_integration(hass, domain)
module = get_component(hass, component) assert integration is not None, domain
assert module is not None
module_path = pathlib.Path(module.__file__) if is_platform:
if module.__name__ == module.__package__:
# light/__init__.py
filename = '{}.json'.format(language)
else:
# group.py
filename = '{}.{}.json'.format(component, language)
return str(module_path.parent / '.translations' / filename)
# It's a platform
parts = component.split('.', 1)
module = get_platform(hass, *parts)
assert module is not None, component
# Either within HA or custom_components
# Either light/hue.py or hue/light.py
module_path = pathlib.Path(module.__file__)
# Compare to parent so we don't have to strip off `.py`
if module_path.parent.name == parts[0]:
# this is light/hue.py
filename = "{}.{}.json".format(parts[1], language)
else:
# this is hue/light.py
filename = "{}.{}.json".format(parts[0], language) filename = "{}.{}.json".format(parts[0], language)
return str(integration.file_path / '.translations' / filename)
return str(module_path.parent / '.translations' / filename) module = integration.get_component()
# If it's a component that is just one file, we don't support translations
# Example custom_components/my_component.py
if module.__name__ != module.__package__:
return None
filename = '{}.json'.format(language)
return str(integration.file_path / '.translations' / filename)
def load_translations_files(translation_files: Dict[str, str]) \ def load_translations_files(translation_files: Dict[str, str]) \
@ -130,8 +114,12 @@ async def async_get_component_resources(hass: HomeAssistantType,
missing_components = components - set(translation_cache) missing_components = components - set(translation_cache)
missing_files = {} missing_files = {}
for component in missing_components: for component in missing_components:
missing_files[component] = component_translation_file( path = await component_translation_file(hass, component, language)
hass, component, language) # No translation available
if path is None:
translation_cache[component] = {}
else:
missing_files[component] = path
# Load missing files # Load missing files
if missing_files: if missing_files:

View File

@ -8,6 +8,7 @@ import pytest
from homeassistant import config_entries from homeassistant import config_entries
import homeassistant.helpers.translation as translation import homeassistant.helpers.translation as translation
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from tests.common import mock_coro
@pytest.fixture @pytest.fixture
@ -52,20 +53,20 @@ async def test_component_translation_file(hass):
'test_package' 'test_package'
}) })
assert path.normpath(translation.component_translation_file( assert path.normpath(await translation.component_translation_file(
hass, 'switch.test', 'en')) == path.normpath(hass.config.path( hass, 'switch.test', 'en')) == path.normpath(hass.config.path(
'custom_components', 'test', '.translations', 'switch.en.json')) 'custom_components', 'test', '.translations', 'switch.en.json'))
assert path.normpath(translation.component_translation_file( assert path.normpath(await translation.component_translation_file(
hass, 'switch.test_embedded', 'en')) == path.normpath(hass.config.path( hass, 'switch.test_embedded', 'en')) == path.normpath(hass.config.path(
'custom_components', 'test_embedded', '.translations', 'custom_components', 'test_embedded', '.translations',
'switch.en.json')) 'switch.en.json'))
assert path.normpath(translation.component_translation_file( assert await translation.component_translation_file(
hass, 'test_standalone', 'en')) == path.normpath(hass.config.path( hass, 'test_standalone', 'en'
'custom_components', '.translations', 'test_standalone.en.json')) ) is None
assert path.normpath(translation.component_translation_file( assert path.normpath(await translation.component_translation_file(
hass, 'test_package', 'en')) == path.normpath(hass.config.path( hass, 'test_package', 'en')) == path.normpath(hass.config.path(
'custom_components', 'test_package', '.translations', 'en.json')) 'custom_components', 'test_package', '.translations', 'en.json'))
@ -133,7 +134,7 @@ async def test_get_translations_loads_config_flows(hass, mock_config_flows):
mock_config_flows.append('component1') mock_config_flows.append('component1')
with patch.object(translation, 'component_translation_file', with patch.object(translation, 'component_translation_file',
return_value='bla.json'), \ return_value=mock_coro('bla.json')), \
patch.object(translation, 'load_translations_files', return_value={ patch.object(translation, 'load_translations_files', return_value={
'component1': {'hello': 'world'}}): 'component1': {'hello': 'world'}}):
translations = await translation.async_get_translations(hass, 'en') translations = await translation.async_get_translations(hass, 'en')