refactor(i18n): improve type safety and code quality in i18n_utils

- Add type guard function for str-keyed dicts
- Add I18nGroup TypedDict for better type checking
- Replace isinstance checks with TypeGuard-based validation
- Improve type annotations throughout
This commit is contained in:
LIghtJUNction
2026-03-31 20:15:28 +08:00
parent da12fca83d
commit 3eccbca2c9

View File

@@ -4,7 +4,16 @@
提供配置元数据的国际化键转换功能
"""
from typing import Any
from typing import TypedDict, TypeGuard
def _is_str_keyed_dict(value: object) -> TypeGuard[dict[str, object]]:
return isinstance(value, dict) and all(isinstance(key, str) for key in value)
class I18nGroup(TypedDict):
name: str
metadata: dict[str, object]
class ConfigMetadataI18n:
@@ -30,7 +39,7 @@ class ConfigMetadataI18n:
return f"{group}.{section}.{attr}"
@staticmethod
def convert_to_i18n_keys(metadata: dict[str, Any]) -> dict[str, Any]:
def convert_to_i18n_keys(metadata: dict[str, object]) -> dict[str, I18nGroup]:
"""
将配置元数据转换为使用国际化键
@@ -40,22 +49,22 @@ class ConfigMetadataI18n:
Returns:
使用国际化键的配置元数据字典
"""
result = {}
result: dict[str, I18nGroup] = {}
def convert_items(
group: str, section: str, items: dict[str, Any], prefix: str = ""
) -> dict[str, Any]:
items_result: dict[str, Any] = {}
group: str, section: str, items: dict[str, object], prefix: str = ""
) -> dict[str, object]:
items_result: dict[str, object] = {}
for field_key, field_data in items.items():
if not isinstance(field_data, dict):
if not _is_str_keyed_dict(field_data):
items_result[field_key] = field_data
continue
field_name = field_key
field_path = f"{prefix}.{field_name}" if prefix else field_name
field_result = {
field_result: dict[str, object] = {
key: value
for key, value in field_data.items()
if key not in {"description", "hint", "labels", "name"}
@@ -72,18 +81,18 @@ class ConfigMetadataI18n:
if "name" in field_data:
field_result["name"] = f"{group}.{section}.{field_path}.name"
if "items" in field_data and isinstance(field_data["items"], dict):
field_items = field_data.get("items")
if _is_str_keyed_dict(field_items):
field_result["items"] = convert_items(
group, section, field_data["items"], field_path
group, section, field_items, field_path
)
if "template_schema" in field_data and isinstance(
field_data["template_schema"], dict
):
template_schema = field_data.get("template_schema")
if _is_str_keyed_dict(template_schema):
field_result["template_schema"] = convert_items(
group,
section,
field_data["template_schema"],
template_schema,
f"{field_path}.template_schema",
)
@@ -92,13 +101,25 @@ class ConfigMetadataI18n:
return items_result
for group_key, group_data in metadata.items():
group_result = {
if not _is_str_keyed_dict(group_data):
continue
group_metadata: dict[str, object] = {}
group_result: I18nGroup = {
"name": f"{group_key}.name",
"metadata": {},
"metadata": group_metadata,
}
for section_key, section_data in group_data.get("metadata", {}).items():
section_result = {
metadata_sections = group_data.get("metadata")
if not _is_str_keyed_dict(metadata_sections):
result[group_key] = group_result
continue
for section_key, section_data in metadata_sections.items():
if not _is_str_keyed_dict(section_data):
continue
section_result: dict[str, object] = {
key: value
for key, value in section_data.items()
if key not in {"description", "hint", "labels", "name"}
@@ -108,12 +129,13 @@ class ConfigMetadataI18n:
if "hint" in section_data:
section_result["hint"] = f"{group_key}.{section_key}.hint"
if "items" in section_data and isinstance(section_data["items"], dict):
section_items = section_data.get("items")
if _is_str_keyed_dict(section_items):
section_result["items"] = convert_items(
group_key, section_key, section_data["items"]
group_key, section_key, section_items
)
group_result["metadata"][section_key] = section_result
group_metadata[section_key] = section_result
result[group_key] = group_result