hass-core/script/translations/deduplicate.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

131 lines
3.9 KiB
Python
Raw Permalink Normal View History

"""Deduplicate translations in strings.json."""
import argparse
import json
from pathlib import Path
from homeassistant.const import Platform
from . import upload
from .develop import flatten_translations
from .util import get_base_arg_parser, load_json_from_path
def get_arguments() -> argparse.Namespace:
"""Get parsed passed in arguments."""
parser = get_base_arg_parser()
parser.add_argument(
"--limit-reference",
"--lr",
action="store_true",
help="Only allow references to same strings.json or common.",
)
return parser.parse_args()
STRINGS_PATH = "homeassistant/components/{}/strings.json"
ENTITY_COMPONENT_PREFIX = tuple(f"component::{domain}::" for domain in Platform)
def run():
"""Clean translations."""
args = get_arguments()
translations = upload.generate_upload_data()
flattened_translations = flatten_translations(translations)
flattened_translations = {
key: value
for key, value in flattened_translations.items()
# Skip existing references
if not value.startswith("[%key:")
}
primary = {}
secondary = {}
for key, value in flattened_translations.items():
if key.startswith("common::"):
primary[value] = key
elif key.startswith(ENTITY_COMPONENT_PREFIX):
primary.setdefault(value, key)
else:
secondary.setdefault(value, key)
merged = {**secondary, **primary}
# Questionable translations are ones that are duplicate but are not referenced
# by the common strings.json or strings.json from an entity component.
questionable = set(secondary.values())
suggest_new_common = set()
update_keys = {}
for key, value in flattened_translations.items():
if merged[value] == key or key.startswith("common::"):
continue
key_integration = key.split("::")[1]
key_to_reference = merged[value]
key_to_reference_integration = key_to_reference.split("::")[1]
is_common = key_to_reference.startswith("common::")
# If we want to only add references to own integrations
# but not include entity integrations
if (
args.limit_reference
and (key_integration != key_to_reference_integration and not is_common)
# Do not create self-references in entity integrations
or key_integration in Platform.__members__.values()
):
continue
if (
# We don't want integrations to reference arbitrary other integrations
key_to_reference in questionable
# Allow reference own integration
and key_to_reference_integration != key_integration
):
suggest_new_common.add(value)
continue
update_keys[key] = f"[%key:{key_to_reference}%]"
if suggest_new_common:
print("Suggested new common words:")
for key in sorted(suggest_new_common):
print(key)
components = sorted({key.split("::")[1] for key in update_keys})
strings = {}
for component in components:
comp_strings_path = Path(STRINGS_PATH.format(component))
strings[component] = load_json_from_path(comp_strings_path)
for path, value in update_keys.items():
parts = path.split("::")
parts.pop(0)
component = parts.pop(0)
to_write = strings[component]
while len(parts) > 1:
try:
to_write = to_write[parts.pop(0)]
except KeyError:
print(to_write)
raise
to_write[parts.pop(0)] = value
for component in components:
comp_strings_path = Path(STRINGS_PATH.format(component))
comp_strings_path.write_text(
json.dumps(
strings[component],
indent=2,
ensure_ascii=False,
),
encoding="utf-8",
)
return 0