Settings i18n improvements (#22571)

* i18n improvements for settings UI

- deduplicate shared detector translation keys and centralize config translation resolution
- add missing i18n keys

* formatting
This commit is contained in:
Josh Hawkins
2026-03-22 13:03:24 -05:00
committed by GitHub
parent 74c89beaf9
commit b6c03c99de
12 changed files with 217 additions and 809 deletions
+48 -18
View File
@@ -190,20 +190,24 @@ def generate_section_translation(config_class: type) -> Dict[str, Any]:
def get_detector_translations(
config_schema: Dict[str, Any],
) -> tuple[Dict[str, Any], set[str]]:
"""Build detector type translations with nested fields based on schema definitions."""
) -> tuple[Dict[str, Any], Dict[str, Any], set[str]]:
"""Build detector type translations with nested fields based on schema definitions.
Returns a tuple of (type_translations, shared_fields, nested_field_keys).
Shared fields (identical across all detector types) are returned separately
to avoid duplication in the output.
"""
defs = config_schema.get("$defs", {})
detector_schema = defs.get("DetectorConfig", {})
discriminator = detector_schema.get("discriminator", {})
mapping = discriminator.get("mapping", {})
type_translations: Dict[str, Any] = {}
nested_field_keys: set[str] = set()
for detector_type, ref in mapping.items():
if not isinstance(ref, str):
continue
# First pass: collect all nested fields per detector type
all_nested: Dict[str, Dict[str, Any]] = {}
type_meta: Dict[str, Dict[str, str]] = {}
if not ref.startswith("#/$defs/"):
for detector_type, ref in mapping.items():
if not isinstance(ref, str) or not ref.startswith("#/$defs/"):
continue
ref_name = ref.split("/")[-1]
@@ -211,26 +215,49 @@ def get_detector_translations(
if not ref_schema:
continue
type_entry: Dict[str, str] = {}
meta: Dict[str, str] = {}
title = ref_schema.get("title")
description = ref_schema.get("description")
if title:
type_entry["label"] = title
meta["label"] = title
if description:
type_entry["description"] = description
meta["description"] = description
type_meta[detector_type] = meta
nested = extract_translations_from_schema(ref_schema, defs=defs)
nested_without_root = {
all_nested[detector_type] = {
k: v for k, v in nested.items() if k not in ("label", "description")
}
if nested_without_root:
type_entry.update(nested_without_root)
nested_field_keys.update(nested_without_root.keys())
# Find fields that are identical across all types that have them
shared_fields: Dict[str, Any] = {}
if all_nested:
# Collect all field keys across all types
all_keys: set[str] = set()
for nested in all_nested.values():
all_keys.update(nested.keys())
for key in all_keys:
values = [nested[key] for nested in all_nested.values() if key in nested]
if len(values) == len(all_nested) and all(v == values[0] for v in values):
shared_fields[key] = values[0]
# Build per-type translations with only unique (non-shared) fields
type_translations: Dict[str, Any] = {}
nested_field_keys: set[str] = set()
for detector_type, nested in all_nested.items():
type_entry: Dict[str, Any] = {}
type_entry.update(type_meta.get(detector_type, {}))
unique_fields = {k: v for k, v in nested.items() if k not in shared_fields}
if unique_fields:
type_entry.update(unique_fields)
nested_field_keys.update(unique_fields.keys())
if type_entry:
type_translations[detector_type] = type_entry
return type_translations, nested_field_keys
return type_translations, shared_fields, nested_field_keys
def main():
@@ -303,9 +330,12 @@ def main():
section_data.update(nested_without_root)
if field_name == "detectors":
detector_types, detector_field_keys = get_detector_translations(
config_schema
detector_types, shared_fields, detector_field_keys = (
get_detector_translations(config_schema)
)
# Add shared fields at the base detectors level
section_data.update(shared_fields)
# Add per-type translations (only unique fields per type)
section_data.update(detector_types)
for key in detector_field_keys:
if key == "type":