mirror of
https://github.com/home-assistant/core.git
synced 2025-12-24 12:59:34 +00:00
Add support for service translations (#95984)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""Validate dependencies."""
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
from typing import Any
|
||||
@@ -25,7 +27,7 @@ def exists(value: Any) -> Any:
|
||||
|
||||
FIELD_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("description"): str,
|
||||
vol.Optional("description"): str,
|
||||
vol.Optional("name"): str,
|
||||
vol.Optional("example"): exists,
|
||||
vol.Optional("default"): exists,
|
||||
@@ -46,7 +48,7 @@ FIELD_SCHEMA = vol.Schema(
|
||||
|
||||
SERVICE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("description"): str,
|
||||
vol.Optional("description"): str,
|
||||
vol.Optional("name"): str,
|
||||
vol.Optional("target"): vol.Any(selector.TargetSelector.CONFIG_SCHEMA, None),
|
||||
vol.Optional("fields"): vol.Schema({str: FIELD_SCHEMA}),
|
||||
@@ -70,7 +72,7 @@ def grep_dir(path: pathlib.Path, glob_pattern: str, search_pattern: str) -> bool
|
||||
return False
|
||||
|
||||
|
||||
def validate_services(integration: Integration) -> None:
|
||||
def validate_services(config: Config, integration: Integration) -> None:
|
||||
"""Validate services."""
|
||||
try:
|
||||
data = load_yaml(str(integration.path / "services.yaml"))
|
||||
@@ -92,15 +94,75 @@ def validate_services(integration: Integration) -> None:
|
||||
return
|
||||
|
||||
try:
|
||||
SERVICES_SCHEMA(data)
|
||||
services = SERVICES_SCHEMA(data)
|
||||
except vol.Invalid as err:
|
||||
integration.add_error(
|
||||
"services", f"Invalid services.yaml: {humanize_error(data, err)}"
|
||||
)
|
||||
|
||||
# Try loading translation strings
|
||||
if integration.core:
|
||||
strings_file = integration.path / "strings.json"
|
||||
else:
|
||||
# For custom integrations, use the en.json file
|
||||
strings_file = integration.path / "translations/en.json"
|
||||
|
||||
strings = {}
|
||||
if strings_file.is_file():
|
||||
with contextlib.suppress(ValueError):
|
||||
strings = json.loads(strings_file.read_text())
|
||||
|
||||
# For each service in the integration, check if the description if set,
|
||||
# if not, check if it's in the strings file. If not, add an error.
|
||||
for service_name, service_schema in services.items():
|
||||
if "name" not in service_schema:
|
||||
try:
|
||||
strings["services"][service_name]["name"]
|
||||
except KeyError:
|
||||
integration.add_error(
|
||||
"services",
|
||||
f"Service {service_name} has no name and is not in the translations file",
|
||||
)
|
||||
|
||||
if "description" not in service_schema:
|
||||
try:
|
||||
strings["services"][service_name]["description"]
|
||||
except KeyError:
|
||||
integration.add_error(
|
||||
"services",
|
||||
f"Service {service_name} has no description and is not in the translations file",
|
||||
)
|
||||
|
||||
# The same check is done for the description in each of the fields of the
|
||||
# service schema.
|
||||
for field_name, field_schema in service_schema.get("fields", {}).items():
|
||||
if "description" not in field_schema:
|
||||
try:
|
||||
strings["services"][service_name]["fields"][field_name][
|
||||
"description"
|
||||
]
|
||||
except KeyError:
|
||||
integration.add_error(
|
||||
"services",
|
||||
f"Service {service_name} has a field {field_name} with no description and is not in the translations file",
|
||||
)
|
||||
|
||||
if "selector" in field_schema:
|
||||
with contextlib.suppress(KeyError):
|
||||
translation_key = field_schema["selector"]["select"][
|
||||
"translation_key"
|
||||
]
|
||||
try:
|
||||
strings["selector"][translation_key]
|
||||
except KeyError:
|
||||
integration.add_error(
|
||||
"services",
|
||||
f"Service {service_name} has a field {field_name} with a selector with a translation key {translation_key} that is not in the translations file",
|
||||
)
|
||||
|
||||
|
||||
def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
"""Handle dependencies for integrations."""
|
||||
# check services.yaml is cool
|
||||
for integration in integrations.values():
|
||||
validate_services(integration)
|
||||
validate_services(config, integration)
|
||||
|
||||
@@ -326,6 +326,20 @@ def gen_strings_schema(config: Config, integration: Integration) -> vol.Schema:
|
||||
),
|
||||
slug_validator=cv.slug,
|
||||
),
|
||||
vol.Optional("services"): cv.schema_with_slug_keys(
|
||||
{
|
||||
vol.Required("name"): translation_value_validator,
|
||||
vol.Required("description"): translation_value_validator,
|
||||
vol.Optional("fields"): cv.schema_with_slug_keys(
|
||||
{
|
||||
vol.Required("name"): str,
|
||||
vol.Required("description"): translation_value_validator,
|
||||
},
|
||||
slug_validator=translation_key_validator,
|
||||
),
|
||||
},
|
||||
slug_validator=translation_key_validator,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user