Testing l10n & a11y
Translation and accessibility failures are silent until someone affected hits them. These checks make them loud before release.
Translation completeness
# Compile statistics for each catalog
$ msgfmt --statistics po/fa.po
po/fa.po: 214 translated messages, 3 untranslated.
Policy for first-party apps: zero untranslated strings in fa at
release. Untranslated strings fall back to English mid-sentence, which is
worse than a fully English build for readers.
Runtime translation testing
LANG=fa_IR.UTF-8run of the app: every screen read in Persian.- Trigger dynamic strings: toasts, error messages, plural cases (0, 1, 2, 5, 100 updates).
- Mixed-direction content: package names, paths, URLs inside Persian sentences render isolated and unbroken.
- Dialog and toast anchoring in RTL (they appear on the mirrored side).
- Desktop entry: launcher shows the Persian
Name[fa], search finds it with Persian keywords.
Accessibility testing
- Keyboard-only walkthrough of the primary flow, including dialogs and menus (rules: keyboard HIG).
- Orca pass: tab through the app and listen; every control announces name, role, and state. Common finds: unlabeled icon buttons, custom widgets with no accessible role.
- Contrast: sample real text and controls in both themes against the contrast rules.
- Scaling: 200% font scale without clipped or overlapping controls; test with Estedad, which is taller than Latin fonts at the same size.
- Reduced motion: with
prefers-reduced-motionset, animations stop and information does not depend on them.
Making it a gate
Both passes belong in the release checklist and in app PR descriptions:
[ ] fa_IR: no untranslated strings (msgfmt --statistics clean)
[ ] fa_IR: primary flow walked, RTL correct
[ ] Keyboard-only primary flow complete
[ ] Orca announces all primary controls
[ ] Both themes pass contrast on real content
A PR that skips these and touches UI is returned for testing, not merged with a promise.