i18n-rtl-l10nlisted
Install: claude install-skill zakariaf/CatchLaw
# i18n, RTL & Localization
One contract: **store canonical, localize at render.** Every conversion and formatting lives in
one `l10n` layer; feature widgets receive value objects and already-localized strings, never raw
formatting logic. RTL is a layout discipline, not a translation task — author with logical
geometry so it mirrors by construction. Applies to any app that ships more than one locale or any
RTL locale (Arabic, Persian, Hebrew, Sorani Kurdish, Urdu).
Read the reference for the task at hand:
- `references/arb-and-icu.md` — the ARB add/translate workflow, `l10n.yaml`, ICU plural/select, placeholder typing.
- `references/rtl-and-bidi.md` — the directional-geometry allow/ban table, icon mirroring, bidi isolation, CustomPainter pinned LTR, RTL charts.
- `references/numerals-and-calendars.md` — digit systems, separator traps, format/parse, calendar projection.
Run `scripts/check_arb_parity.sh` and `scripts/check_i18n_bans.sh` before a PR.
## Non-negotiable rules
1. **Every user-facing string goes through gen-l10n.** Add the key to the template `app_en.arb`
first, then read it via `AppLocalizations.of(context)`. Set `nullable-getter: false` in
`l10n.yaml` so the getter is non-null and a missing/typo key is a **compile error**, not a
silent empty widget. Never hardcode a literal in `Text`, `tooltip:`, `label:`, `hint:`, or
`semanticsLabel:`. Never call `AppLocalizations.of` above the `Localizations` scope (e.g. in
`main()` before `runApp`).
2. **Key