aeat.locales._ast_scanner module¶
AST-based locale-key discovery for sites the regex scanner misses.
The regex scanner under locales.manager.LocaleManager
captures tr(”…”) and t(”…”) literal call sites. Two surfaces slip
past that contract:
Programmatic errors that pass a translation key to an exception constructor through a
message_key=/translation_key=kwarg rather than atr()call (for exampleWizardValidationError("wizard.errors.select_unknown")).f-string call sites whose JoinedStr starts with a literal dot-notation prefix matching the translation-key shape (for example
tr(f"cli.registry.metrics.{key}")) — the regex sees the prefix but cannot tell what follows. The scanner emits a<prefix>.*marker that the parity check treats as a namespace declaration rather than a single key.Bounded locale-key registries exposed as module constants whose names end in
_LOCALE_KEYor_LOCALE_KEYS. These constants centralize key selection for application policies that return translation keys to a later caller instead of callingtr()locally.
Both findings feed into
locales.manager.LocaleManager.get_codebase_keys() so the
parity audit covers programmatic emissions and dynamic namespaces.
- scan_source_tree(root)[source]¶
Walk
rootfor .py files and emit concrete dotted locale keys.Concrete keys are literal translation keys passed to error constructors (positional first argument or
message_key=kwarg). Dynamic namespaces (f-string and concatenation patterns) are returned byscan_namespace_markers()and routed through a separate parity check that asserts at least one concrete locale entry exists under each declared namespace prefix.
- scan_namespace_markers(root)[source]¶
Walk
rootfor .py files and emit dynamic-namespace markers.A namespace marker is a
<prefix>.*string identifying a family of keys whose tail is computed at runtime (f-string interpolation or string concatenation). Each marker passes the parity check when at least one concrete locale key starts with its prefix.