This commit is contained in:
122
i18n_key_sync/validate.py
Normal file
122
i18n_key_sync/validate.py
Normal file
@@ -0,0 +1,122 @@
|
||||
"""Validation of i18n keys against locale files."""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, Set
|
||||
|
||||
|
||||
@dataclass
|
||||
class ValidationResult:
|
||||
"""Result of validating i18n keys against locale files."""
|
||||
|
||||
missing_keys: Set[str] = field(default_factory=set)
|
||||
unused_keys: Set[str] = field(default_factory=set)
|
||||
matching_keys: Set[str] = field(default_factory=set)
|
||||
extra_keys_per_locale: Dict[str, Set[str]] = field(default_factory=dict)
|
||||
|
||||
@property
|
||||
def total_missing(self) -> int:
|
||||
"""Total count of missing keys."""
|
||||
return len(self.missing_keys)
|
||||
|
||||
@property
|
||||
def total_unused(self) -> int:
|
||||
"""Total count of unused keys."""
|
||||
return len(self.unused_keys)
|
||||
|
||||
@property
|
||||
def total_matching(self) -> int:
|
||||
"""Total count of matching keys."""
|
||||
return len(self.matching_keys)
|
||||
|
||||
@property
|
||||
def is_valid(self) -> bool:
|
||||
"""Check if there are no missing or unused keys."""
|
||||
return len(self.missing_keys) == 0 and len(self.unused_keys) == 0
|
||||
|
||||
|
||||
class Validator:
|
||||
"""Validate extracted i18n keys against locale files."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the validator."""
|
||||
|
||||
def validate(
|
||||
self,
|
||||
extracted_keys: Set[str],
|
||||
locale_keys: Dict[str, Set[str]],
|
||||
) -> ValidationResult:
|
||||
"""Validate extracted keys against locale keys.
|
||||
|
||||
Args:
|
||||
extracted_keys: Set of keys extracted from source code.
|
||||
locale_keys: Dictionary mapping locale names to their key sets.
|
||||
|
||||
Returns:
|
||||
ValidationResult with missing, unused, and matching keys.
|
||||
|
||||
"""
|
||||
if not locale_keys:
|
||||
return ValidationResult(
|
||||
missing_keys=extracted_keys,
|
||||
unused_keys=set(),
|
||||
matching_keys=set(),
|
||||
)
|
||||
|
||||
result = ValidationResult()
|
||||
|
||||
for locale, keys in locale_keys.items():
|
||||
locale_missing = extracted_keys - keys
|
||||
locale_unused = keys - extracted_keys
|
||||
locale_matching = keys & extracted_keys
|
||||
|
||||
result.missing_keys.update(locale_missing)
|
||||
result.unused_keys.update(locale_unused)
|
||||
result.matching_keys.update(locale_matching)
|
||||
result.extra_keys_per_locale[locale] = locale_unused
|
||||
|
||||
return result
|
||||
|
||||
def validate_for_locale(
|
||||
self,
|
||||
extracted_keys: Set[str],
|
||||
locale_keys: Set[str],
|
||||
locale_name: str = "",
|
||||
) -> ValidationResult:
|
||||
"""Validate keys against a single locale.
|
||||
|
||||
Args:
|
||||
extracted_keys: Set of keys extracted from source code.
|
||||
locale_keys: Set of keys in the locale file.
|
||||
locale_name: Name of the locale (for reporting).
|
||||
|
||||
Returns:
|
||||
ValidationResult for the single locale.
|
||||
|
||||
"""
|
||||
missing_keys = extracted_keys - locale_keys
|
||||
unused_keys = locale_keys - extracted_keys
|
||||
matching_keys = locale_keys & extracted_keys
|
||||
|
||||
return ValidationResult(
|
||||
missing_keys=missing_keys,
|
||||
unused_keys=unused_keys,
|
||||
matching_keys=matching_keys,
|
||||
)
|
||||
|
||||
def get_summary(self, result: ValidationResult) -> Dict[str, int]:
|
||||
"""Get a summary of the validation result.
|
||||
|
||||
Args:
|
||||
result: ValidationResult to summarize.
|
||||
|
||||
Returns:
|
||||
Dictionary with summary statistics.
|
||||
|
||||
"""
|
||||
return {
|
||||
"missing_keys": len(result.missing_keys),
|
||||
"unused_keys": len(result.unused_keys),
|
||||
"matching_keys": len(result.matching_keys),
|
||||
"total_keys_in_code": len(result.missing_keys) + len(result.matching_keys),
|
||||
"total_keys_in_locale": len(result.unused_keys) + len(result.matching_keys),
|
||||
}
|
||||
Reference in New Issue
Block a user