Add support for loading add-on translation files (#2644)

* Add support for loading add-on translation files

* Fix storing translations for installed add-ons

* Allow YAML, force schema

* Adjust schema
This commit is contained in:
Joakim Sørensen 2021-03-01 11:44:24 +01:00 committed by GitHub
parent 8d42513ba8
commit 7a542aeb38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 1 deletions

View File

@ -54,6 +54,7 @@ from ..const import (
ATTR_STAGE,
ATTR_STARTUP,
ATTR_STDIN,
ATTR_TANSLATIONS,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_UART,
@ -185,6 +186,11 @@ class AddonModel(CoreSysAttributes, ABC):
"""Return repository of add-on."""
return self.data[ATTR_REPOSITORY]
@property
def translations(self) -> dict:
"""Return add-on translations."""
return self.data[ATTR_TANSLATIONS]
@property
def latest_version(self) -> AwesomeVersion:
"""Return latest version of add-on."""

View File

@ -21,6 +21,7 @@ from ..const import (
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_BUILD_FROM,
ATTR_CONFIGURATION,
ATTR_DESCRIPTON,
ATTR_DEVICES,
ATTR_DEVICETREE,
@ -71,6 +72,7 @@ from ..const import (
ATTR_STATE,
ATTR_STDIN,
ATTR_SYSTEM,
ATTR_TANSLATIONS,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_UART,
@ -343,12 +345,18 @@ SCHEMA_ADDON_USER = vol.Schema(
)
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,
}
),
)

View File

@ -82,6 +82,7 @@ from ..const import (
ATTR_STARTUP,
ATTR_STATE,
ATTR_STDIN,
ATTR_TANSLATIONS,
ATTR_UART,
ATTR_UDEV,
ATTR_UPDATE_AVAILABLE,
@ -265,6 +266,7 @@ class APIAddons(CoreSysAttributes):
ATTR_SERVICES: _pretty_services(addon),
ATTR_DISCOVERY: addon.discovery,
ATTR_IP_ADDRESS: None,
ATTR_TANSLATIONS: addon.translations,
ATTR_INGRESS: addon.with_ingress,
ATTR_INGRESS_ENTRY: None,
ATTR_INGRESS_URL: None,

View File

@ -109,6 +109,7 @@ ATTR_CHANNEL = "channel"
ATTR_CHASSIS = "chassis"
ATTR_CLI = "cli"
ATTR_CONFIG = "config"
ATTR_CONFIGURATION = "configuration"
ATTR_CONNECTED = "connected"
ATTR_CONNECTIONS = "connections"
ATTR_CONTAINERS = "containers"
@ -271,6 +272,7 @@ ATTR_TIMEZONE = "timezone"
ATTR_TITLE = "title"
ATTR_TMPFS = "tmpfs"
ATTR_TOTP = "totp"
ATTR_TANSLATIONS = "translations"
ATTR_TYPE = "type"
ATTR_UART = "uart"
ATTR_UDEV = "udev"

View File

@ -6,11 +6,12 @@ from typing import Any, Dict
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..addons.validate import SCHEMA_ADDON_CONFIG
from ..addons.validate import SCHEMA_ADDON_CONFIG, SCHEMA_ADDON_TRANSLATION
from ..const import (
ATTR_LOCATON,
ATTR_REPOSITORY,
ATTR_SLUG,
ATTR_TANSLATIONS,
FILE_SUFFIX_CONFIGURATION,
REPOSITORY_CORE,
REPOSITORY_LOCAL,
@ -129,6 +130,7 @@ 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)
self.addons[addon_slug] = addon_config
def _set_builtin_repositories(self):
@ -145,3 +147,29 @@ class StoreData(CoreSysAttributes):
# local repository
self.repositories[REPOSITORY_LOCAL] = builtin_data[REPOSITORY_LOCAL]
def _read_addon_translations(self, addon_path: Path) -> dict:
"""Read translations from add-ons folder."""
translations_dir = addon_path / "translations"
translations = {}
if not translations_dir.exists():
return translations
translation_files = [
translation
for translation in translations_dir.glob("*")
if translation.suffix in FILE_SUFFIX_CONFIGURATION
]
for translation in translation_files:
try:
translations[translation.stem] = SCHEMA_ADDON_TRANSLATION(
read_json_or_yaml_file(translation)
)
except (JsonFileError, YamlFileError, vol.Invalid):
_LOGGER.warning("Can't read translations from %s", translation)
continue
return translations

View File

@ -0,0 +1,34 @@
"""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
def test_loading_traslations(coresys: CoreSys, tmp_path):
"""Test loading add-translation."""
os.makedirs(tmp_path / "translations")
# no transaltions
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"}}))
for file in ("no.yaml", "de.yaml"):
_YAML.dump(
{"configuration": {"test": "test"}}, tmp_path / "translations" / file
)
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"