diff --git a/supervisor/addons/data.py b/supervisor/addons/data.py index fab368184..077e77cb9 100644 --- a/supervisor/addons/data.py +++ b/supervisor/addons/data.py @@ -1,6 +1,5 @@ """Init file for Supervisor add-on data.""" from copy import deepcopy -import logging from typing import Any, Dict from ..const import ( @@ -17,8 +16,6 @@ from ..utils.common import FileConfiguration from .addon import Addon from .validate import SCHEMA_ADDONS_FILE -_LOGGER: logging.Logger = logging.getLogger(__name__) - Config = Dict[str, Any] diff --git a/supervisor/addons/model.py b/supervisor/addons/model.py index 9da8c472a..5a679ccb3 100644 --- a/supervisor/addons/model.py +++ b/supervisor/addons/model.py @@ -54,9 +54,9 @@ from ..const import ( ATTR_STAGE, ATTR_STARTUP, ATTR_STDIN, - ATTR_TANSLATIONS, ATTR_TIMEOUT, ATTR_TMPFS, + ATTR_TRANSLATIONS, ATTR_UART, ATTR_UDEV, ATTR_URL, @@ -189,7 +189,7 @@ class AddonModel(CoreSysAttributes, ABC): @property def translations(self) -> dict: """Return add-on translations.""" - return self.data[ATTR_TANSLATIONS] + return self.data[ATTR_TRANSLATIONS] @property def latest_version(self) -> AwesomeVersion: diff --git a/supervisor/addons/validate.py b/supervisor/addons/validate.py index e873eb43c..d5100a978 100644 --- a/supervisor/addons/validate.py +++ b/supervisor/addons/validate.py @@ -72,9 +72,9 @@ from ..const import ( ATTR_STATE, ATTR_STDIN, ATTR_SYSTEM, - ATTR_TANSLATIONS, ATTR_TIMEOUT, ATTR_TMPFS, + ATTR_TRANSLATIONS, ATTR_UART, ATTR_UDEV, ATTR_URL, @@ -322,6 +322,20 @@ SCHEMA_BUILD_CONFIG = vol.Schema( extra=vol.REMOVE_EXTRA, ) +SCHEMA_TRANSLATION_CONFIGURATION = vol.Schema( + { + vol.Required(ATTR_NAME): str, + vol.Optional(ATTR_DESCRIPTON): vol.Maybe(str), + }, + extra=vol.REMOVE_EXTRA, +) + + +SCHEMA_ADDON_TRANSLATIONS = vol.Schema( + {vol.Optional(ATTR_CONFIGURATION): {str: SCHEMA_TRANSLATION_CONFIGURATION}}, + extra=vol.REMOVE_EXTRA, +) + # pylint: disable=no-value-for-parameter SCHEMA_ADDON_USER = vol.Schema( @@ -344,19 +358,15 @@ SCHEMA_ADDON_USER = vol.Schema( extra=vol.REMOVE_EXTRA, ) - -SCHEMA_ADDON_TRANSLATION = vol.Schema( - {vol.Optional(ATTR_CONFIGURATION): {str: str}}, extra=vol.REMOVE_EXTRA -) - - SCHEMA_ADDON_SYSTEM = vol.All( _migrate_addon_config(), _SCHEMA_ADDON_CONFIG.extend( { vol.Required(ATTR_LOCATON): str, vol.Required(ATTR_REPOSITORY): str, - vol.Optional(ATTR_TANSLATIONS, default={}): SCHEMA_ADDON_TRANSLATION, + vol.Required(ATTR_TRANSLATIONS, default=dict): { + str: SCHEMA_ADDON_TRANSLATIONS + }, } ), ) diff --git a/supervisor/api/addons.py b/supervisor/api/addons.py index 2d9e0365f..3ee9ae103 100644 --- a/supervisor/api/addons.py +++ b/supervisor/api/addons.py @@ -82,7 +82,7 @@ from ..const import ( ATTR_STARTUP, ATTR_STATE, ATTR_STDIN, - ATTR_TANSLATIONS, + ATTR_TRANSLATIONS, ATTR_UART, ATTR_UDEV, ATTR_UPDATE_AVAILABLE, @@ -266,7 +266,7 @@ class APIAddons(CoreSysAttributes): ATTR_SERVICES: _pretty_services(addon), ATTR_DISCOVERY: addon.discovery, ATTR_IP_ADDRESS: None, - ATTR_TANSLATIONS: addon.translations, + ATTR_TRANSLATIONS: addon.translations, ATTR_INGRESS: addon.with_ingress, ATTR_INGRESS_ENTRY: None, ATTR_INGRESS_URL: None, diff --git a/supervisor/const.py b/supervisor/const.py index 49c8d6b1b..216de18d6 100644 --- a/supervisor/const.py +++ b/supervisor/const.py @@ -283,7 +283,7 @@ ATTR_TIMEZONE = "timezone" ATTR_TITLE = "title" ATTR_TMPFS = "tmpfs" ATTR_TOTP = "totp" -ATTR_TANSLATIONS = "translations" +ATTR_TRANSLATIONS = "translations" ATTR_TYPE = "type" ATTR_UART = "uart" ATTR_UDEV = "udev" diff --git a/supervisor/store/data.py b/supervisor/store/data.py index 9bd2749c8..f9e666d68 100644 --- a/supervisor/store/data.py +++ b/supervisor/store/data.py @@ -6,12 +6,12 @@ from typing import Any, Dict import voluptuous as vol from voluptuous.humanize import humanize_error -from ..addons.validate import SCHEMA_ADDON_CONFIG, SCHEMA_ADDON_TRANSLATION +from ..addons.validate import SCHEMA_ADDON_CONFIG, SCHEMA_ADDON_TRANSLATIONS from ..const import ( ATTR_LOCATON, ATTR_REPOSITORY, ATTR_SLUG, - ATTR_TANSLATIONS, + ATTR_TRANSLATIONS, FILE_SUFFIX_CONFIGURATION, REPOSITORY_CORE, REPOSITORY_LOCAL, @@ -130,7 +130,9 @@ class StoreData(CoreSysAttributes): # store addon_config[ATTR_REPOSITORY] = repository addon_config[ATTR_LOCATON] = str(addon.parent) - addon_config[ATTR_TANSLATIONS] = self._read_addon_translations(addon.parent) + addon_config[ATTR_TRANSLATIONS] = self._read_addon_translations( + addon.parent + ) self.addons[addon_slug] = addon_config def _set_builtin_repositories(self): @@ -164,12 +166,14 @@ class StoreData(CoreSysAttributes): for translation in translation_files: try: - translations[translation.stem] = SCHEMA_ADDON_TRANSLATION( + translations[translation.stem] = SCHEMA_ADDON_TRANSLATIONS( read_json_or_yaml_file(translation) ) - except (ConfigurationFileError, vol.Invalid): - _LOGGER.warning("Can't read translations from %s", translation) + except (ConfigurationFileError, vol.Invalid) as err: + _LOGGER.warning( + "Can't read translations from %s - %s", translation, err + ) continue return translations diff --git a/tests/store/test_translation_load.py b/tests/store/test_translation_load.py index b7aa17522..5266afdea 100644 --- a/tests/store/test_translation_load.py +++ b/tests/store/test_translation_load.py @@ -1,14 +1,9 @@ """Test loading add-translation.""" # pylint: disable=import-error,protected-access -import json import os -from ruamel.yaml import YAML - from supervisor.coresys import CoreSys - -_YAML = YAML() -_YAML.allow_duplicate_keys = True +from supervisor.utils.common import write_json_or_yaml_file def test_loading_traslations(coresys: CoreSys, tmp_path): @@ -18,17 +13,22 @@ def test_loading_traslations(coresys: CoreSys, tmp_path): assert coresys.store.data._read_addon_translations(tmp_path) == {} for file in ("en.json", "es.json"): - with open(tmp_path / "translations" / file, "w") as lang_file: - lang_file.write(json.dumps({"configuration": {"test": "test"}})) + write_json_or_yaml_file( + tmp_path / "translations" / file, + {"configuration": {"test": {"name": "test", "test": "test"}}}, + ) for file in ("no.yaml", "de.yaml"): - _YAML.dump( - {"configuration": {"test": "test"}}, tmp_path / "translations" / file + write_json_or_yaml_file( + tmp_path / "translations" / file, + {"configuration": {"test": {"name": "test", "test": "test"}}}, ) translations = coresys.store.data._read_addon_translations(tmp_path) - assert translations["en"]["configuration"]["test"] == "test" - assert translations["es"]["configuration"]["test"] == "test" - assert translations["no"]["configuration"]["test"] == "test" - assert translations["de"]["configuration"]["test"] == "test" + assert translations["en"]["configuration"]["test"]["name"] == "test" + assert translations["es"]["configuration"]["test"]["name"] == "test" + assert translations["no"]["configuration"]["test"]["name"] == "test" + assert translations["de"]["configuration"]["test"]["name"] == "test" + + assert "test" not in translations["en"]["configuration"]["test"]