mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add translations check script (#34272)
This commit is contained in:
parent
d011b46985
commit
1ffc3a00e7
@ -88,4 +88,4 @@ repos:
|
|||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
language: script
|
language: script
|
||||||
types: [json]
|
types: [json]
|
||||||
files: ^homeassistant/.+/manifest\.json$
|
files: ^homeassistant/.+/(manifest|strings)\.json$
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
"close": "Close",
|
"close": "Close",
|
||||||
"both_buttons": "Both buttons",
|
"both_buttons": "Both buttons",
|
||||||
"top_buttons": "Top buttons",
|
"top_buttons": "Top buttons",
|
||||||
"bottom_buttons" : "Bottom buttons",
|
"bottom_buttons": "Bottom buttons",
|
||||||
"button_1": "First button",
|
"button_1": "First button",
|
||||||
"button_2": "Second button",
|
"button_2": "Second button",
|
||||||
"button_3": "Third button",
|
"button_3": "Third button",
|
||||||
|
@ -57,8 +57,5 @@
|
|||||||
"title": "UniFi options 3/3"
|
"title": "UniFi options 3/3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"unknown_client_mac": "No client available in UniFi on that MAC address"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,15 @@ from . import (
|
|||||||
config_flow,
|
config_flow,
|
||||||
coverage,
|
coverage,
|
||||||
dependencies,
|
dependencies,
|
||||||
json,
|
|
||||||
manifest,
|
manifest,
|
||||||
services,
|
services,
|
||||||
ssdp,
|
ssdp,
|
||||||
|
translations,
|
||||||
zeroconf,
|
zeroconf,
|
||||||
)
|
)
|
||||||
from .model import Config, Integration
|
from .model import Config, Integration
|
||||||
|
|
||||||
PLUGINS = [
|
PLUGINS = [
|
||||||
json,
|
|
||||||
codeowners,
|
codeowners,
|
||||||
config_flow,
|
config_flow,
|
||||||
coverage,
|
coverage,
|
||||||
@ -25,6 +24,7 @@ PLUGINS = [
|
|||||||
manifest,
|
manifest,
|
||||||
services,
|
services,
|
||||||
ssdp,
|
ssdp,
|
||||||
|
translations,
|
||||||
zeroconf,
|
zeroconf,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
"""Validate integration JSON files."""
|
|
||||||
import json
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from .model import Integration
|
|
||||||
|
|
||||||
|
|
||||||
def validate_json_files(integration: Integration):
|
|
||||||
"""Validate JSON files for integration."""
|
|
||||||
for json_file in integration.path.glob("**/*.json"):
|
|
||||||
if not json_file.is_file():
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
json.loads(json_file.read_text())
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
relative_path = json_file.relative_to(integration.path)
|
|
||||||
integration.add_error("json", f"Invalid JSON file {relative_path}")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def validate(integrations: Dict[str, Integration], config):
|
|
||||||
"""Handle JSON files inside integrations."""
|
|
||||||
for integration in integrations.values():
|
|
||||||
if not integration.manifest:
|
|
||||||
continue
|
|
||||||
|
|
||||||
validate_json_files(integration)
|
|
90
script/hassfest/translations.py
Normal file
90
script/hassfest/translations.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
"""Validate integration translation files."""
|
||||||
|
import json
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
|
from .model import Integration
|
||||||
|
|
||||||
|
|
||||||
|
def data_entry_schema(*, require_title: bool, require_step_title: bool):
|
||||||
|
"""Generate a data entry schema."""
|
||||||
|
step_title_class = vol.Required if require_step_title else vol.Optional
|
||||||
|
data_entry_schema = {
|
||||||
|
vol.Optional("flow_title"): str,
|
||||||
|
vol.Required("step"): {
|
||||||
|
str: {
|
||||||
|
step_title_class("title"): str,
|
||||||
|
vol.Optional("description"): str,
|
||||||
|
vol.Optional("data"): {str: str},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vol.Optional("error"): {str: str},
|
||||||
|
vol.Optional("abort"): {str: str},
|
||||||
|
vol.Optional("create_entry"): {str: str},
|
||||||
|
}
|
||||||
|
if require_title:
|
||||||
|
data_entry_schema[vol.Required("title")] = str
|
||||||
|
|
||||||
|
return data_entry_schema
|
||||||
|
|
||||||
|
|
||||||
|
STRINGS_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional("title"): str,
|
||||||
|
vol.Optional("config"): data_entry_schema(
|
||||||
|
require_title=False, require_step_title=True
|
||||||
|
),
|
||||||
|
vol.Optional("options"): data_entry_schema(
|
||||||
|
require_title=False, require_step_title=False
|
||||||
|
),
|
||||||
|
vol.Optional("device_automation"): {
|
||||||
|
vol.Optional("action_type"): {str: str},
|
||||||
|
vol.Optional("condition_type"): {str: str},
|
||||||
|
vol.Optional("trigger_type"): {str: str},
|
||||||
|
vol.Optional("trigger_subtype"): {str: str},
|
||||||
|
},
|
||||||
|
vol.Optional("state"): {str: str},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
AUTH_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional("mfa_setup"): {
|
||||||
|
str: data_entry_schema(require_title=True, require_step_title=True)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ONBOARDING_SCHEMA = vol.Schema({vol.Required("area"): {str: str}})
|
||||||
|
|
||||||
|
|
||||||
|
def validate_translation_file(integration: Integration):
|
||||||
|
"""Validate translation files for integration."""
|
||||||
|
strings_file = integration.path / "strings.json"
|
||||||
|
|
||||||
|
if not strings_file.is_file():
|
||||||
|
return
|
||||||
|
|
||||||
|
strings = json.loads(strings_file.read_text())
|
||||||
|
|
||||||
|
if integration.domain == "auth":
|
||||||
|
schema = AUTH_SCHEMA
|
||||||
|
elif integration.domain == "onboarding":
|
||||||
|
schema = ONBOARDING_SCHEMA
|
||||||
|
else:
|
||||||
|
schema = STRINGS_SCHEMA
|
||||||
|
|
||||||
|
try:
|
||||||
|
schema(strings)
|
||||||
|
except vol.Invalid as err:
|
||||||
|
integration.add_error(
|
||||||
|
"translations", f"Invalid strings.json: {humanize_error(strings, err)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate(integrations: Dict[str, Integration], config):
|
||||||
|
"""Handle JSON files inside integrations."""
|
||||||
|
for integration in integrations.values():
|
||||||
|
validate_translation_file(integration)
|
@ -21,9 +21,7 @@ def main():
|
|||||||
args = get_arguments()
|
args = get_arguments()
|
||||||
|
|
||||||
module = importlib.import_module(f".{args.action}", "script.translations")
|
module = importlib.import_module(f".{args.action}", "script.translations")
|
||||||
module.run()
|
return module.run()
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -68,3 +68,5 @@ def run():
|
|||||||
|
|
||||||
print("Deleting keys:", ", ".join(map(str, to_delete)))
|
print("Deleting keys:", ", ".join(map(str, to_delete)))
|
||||||
print(lokalise.keys_delete_multiple(to_delete))
|
print(lokalise.keys_delete_multiple(to_delete))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
@ -61,3 +61,5 @@ def run():
|
|||||||
)
|
)
|
||||||
|
|
||||||
download.write_integration_translations()
|
download.write_integration_translations()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
@ -149,3 +149,5 @@ def run():
|
|||||||
run_download_docker()
|
run_download_docker()
|
||||||
|
|
||||||
write_integration_translations()
|
write_integration_translations()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
@ -48,3 +48,5 @@ def run():
|
|||||||
print()
|
print()
|
||||||
print("Updating keys")
|
print("Updating keys")
|
||||||
pprint(lokalise.keys_bulk_update(updates).json())
|
pprint(lokalise.keys_bulk_update(updates).json())
|
||||||
|
|
||||||
|
return 0
|
||||||
|
@ -82,3 +82,5 @@ def run():
|
|||||||
LOCAL_FILE.write_text(json.dumps(translations, indent=4, sort_keys=True))
|
LOCAL_FILE.write_text(json.dumps(translations, indent=4, sort_keys=True))
|
||||||
|
|
||||||
run_upload_docker()
|
run_upload_docker()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
@ -13,7 +13,7 @@ def get_base_arg_parser():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"action",
|
"action",
|
||||||
type=str,
|
type=str,
|
||||||
choices=["download", "clean", "upload", "develop", "migrate"],
|
choices=["clean", "develop", "download", "migrate", "upload"],
|
||||||
)
|
)
|
||||||
parser.add_argument("--debug", action="store_true", help="Enable log output")
|
parser.add_argument("--debug", action="store_true", help="Enable log output")
|
||||||
return parser
|
return parser
|
||||||
|
Loading…
x
Reference in New Issue
Block a user