in python/moz/l10n/formats/mf2/validate.py [0:0]
def mf2_validate_message(msg: PatternMessage | SelectMessage) -> None:
"""
Validate that the message satisfies MessageFormat 2 validity constraints.
May reorder declarations.
May raise `MF2ValidationError`.
"""
if isinstance(msg, PatternMessage):
_validate_declarations(msg.declarations)
_validate_pattern(msg.pattern)
elif isinstance(msg, SelectMessage):
_validate_declarations(msg.declarations)
if not msg.selectors or not isinstance(msg.selectors, tuple):
raise MF2ValidationError(f"Invalid selectors: {msg.selectors}")
for sel in msg.selectors:
if isinstance(sel, VariableRef):
_validate_variable(sel)
else:
raise MF2ValidationError(f"Invalid selector: {sel}")
sel_name = sel.name
sel_expr = msg.declarations.get(sel_name, None)
while sel_expr is not None and sel_expr.function is None:
if (
isinstance(sel_expr.arg, VariableRef)
and sel_expr.arg.name != sel_name
):
sel_name = sel_expr.arg.name
sel_expr = msg.declarations.get(sel_name, None)
else:
sel_expr = None
if sel_expr is None:
raise MF2ValidationError(
msg, f"Missing selector annotation for ${sel.name}"
)
sel_count = len(msg.selectors)
if not isinstance(msg.variants, Mapping):
raise MF2ValidationError(f"Invalid variants: {msg.variants}")
for keys, pattern in msg.variants.items():
if not isinstance(keys, tuple):
raise MF2ValidationError(f"Invalid keys: {keys}")
for key in keys:
if not isinstance(key, str) and not isinstance(key, CatchallKey):
raise MF2ValidationError(f"Invalid key: {key}")
if len(keys) != sel_count:
raise MF2ValidationError(
f"Variant key mismatch, expected {sel_count} but found {len(keys)}",
)
_validate_pattern(pattern)
if (CatchallKey(),) * sel_count not in msg.variants:
raise MF2ValidationError("Missing fallback variant")
else:
raise MF2ValidationError(f"Invalid message: {msg}")