i18n-audit
Playwright i18n Audit
Checks that switching locale actually does something, that switch actually sticks, that right-to-left layouts don't visually fall apart, and that nothing's silently still showing a raw translation key or the wrong language.
Scope boundary
This is mechanical correctness — did the text change, did the layout survive, does a hreflang tag point where it should — not translation quality review. It can flag something that looks obviously broken (a raw key like HOMEPAGE_HERO_TITLE instead of a sentence, a garbled machine-translation artifact, an English sentence sitting untranslated in an otherwise-translated page) but doesn't grade whether a translation is natural, idiomatic, or culturally appropriate beyond that. Same reasoning as this toolkit staying out of visual design opinions — that's a different kind of judgment than what the rest of this toolkit does.
Relationship to the other skills
Reuse scenario-mapper's page list, applied per-locale. Reuse visual-snapshot's capture mechanism for RTL layout checks — whether a right-to-left layout actually mirrors correctly is fundamentally a visual question, not something worth re-deriving a separate capture step for. hreflang correctness is this skill's job, not seo-audit's — that skill validates a single page's metadata exists and is structurally sound; this one validates that locale variants of the same content correctly reference each other.
Core principles (and why)
Leaked translation keys are pattern-matched, not confirmed — flag for review, don't assert as fact. Text that looks like a code identifier (HOMEPAGE_HERO_TITLE, {{missing_key}}, dotted paths like home.hero.title) instead of a sentence is a strong signal something's untranslated, but pattern-matching on "looks like an identifier rather than prose" has real false-positive risk — a legitimate SKU or product code can look similar. Flag it as a candidate for review, not a confirmed bug.
Text overflow from translation expansion is mechanically checkable, not just visual. Translated text is often meaningfully longer than the source (German and Finnish especially) — compare an element's scrollWidth/scrollHeight against its visible clientWidth/clientHeight to catch silent clipping or overflow programmatically, rather than relying entirely on spotting it by eye in a screenshot.
Locale persistence matters as much as the switch itself. A switcher that works on the page it's clicked from but silently resets to default on the next navigation is a common, easy-to-miss bug — check the selected locale survives at least one subsequent navigation, not just that switching itself works.