The idea
A command-line tool that drives your app through a list of routes, renders each one in every locale you ship plus a synthetic pseudo-locale with artificially inflated strings, and reports the places where text no longer fits its box. Output is a report of element selectors with cropped screenshots, and a non-zero exit code so CI can block the regression. It does not try to fix your CSS; it tells you which 40 components will embarrass you in German, Finnish, and Russian.
Why build this
Every team that localizes hits this and almost nobody has a systematic answer. English is a compact language: translations into German or Finnish routinely run 35–50% longer, and a button sized to "Save" becomes "Änderungen speichern". The failures are visual, so unit tests miss them entirely, and they surface weeks later as a screenshot in a support ticket from a market nobody on the team reads.
The usual fallback is a human clicking through the app in each locale before a release, which does not scale past three languages and does not happen at all under deadline. Meanwhile the ingredients to automate it are now boring: headless browsers are reliable in CI, every frontend already keeps its copy in a structured message catalogue, and layout overflow is measurable from the DOM rather than guessed from pixels.
Stack sketch
- CLI in TypeScript with
commander, shipped on npm, designed to run unchanged in GitHub Actions - Playwright with Chromium, one browser context per locale, routes supplied either as a URL list or a small user-written script for flows behind a login
- Catalogue readers for i18next JSON, ICU MessageFormat, and gettext
.po; the pseudo-locale generator expands each string by a configurable factor, substitutes accented glyphs so hardcoded English stands out, and leaves{placeholders}untouched - Detection as an injected page script: walk text-bearing elements, compare
scrollWidth/scrollHeightagainstclientWidth/clientHeight, checkgetClientRects()for overlap between siblings, and checkdocument.documentElement.scrollWidthagainst the viewport for horizontal page overflow - SQLite for run history plus PNG crops on disk; a static HTML report and a JSON artifact for machines
- Fonts pinned and preloaded through Playwright's route interception, so a slow CDN cannot change the measurements between runs
Scope for v1
In:
- localens run --routes routes.ts --locales de,fi,ru --pseudo as the whole interface
- Three findings only: clipped text, overlapping siblings, horizontal page overflow
- A suppressions.yml keyed by selector plus finding type, because intentional ellipsis is everywhere
- HTML report, JSON output, exit code
Out: - RTL mirroring audits - Native mobile apps - Any comparison against design files - Translation management of any kind - Automatic CSS fixes or suggestions
Where it could go
RTL is the obvious second act and a much harder one: Arabic and Hebrew need mirrored layout, flipped icons, and bidirectional text handling, and the same rendering harness can check all three once you decide what "correct" looks like. Native mobile is the other direction, driving Maestro or XCUITest and measuring from the accessibility tree instead of the DOM.
The most useful expansion is turning findings back into prevention. Once you know a given string key breaks at 28 characters, that is a per-key length budget you can push into Crowdin or Weblate through their APIs, so a translator sees the limit while writing rather than a developer seeing a screenshot three weeks later. At that point the tool stops being a test and becomes part of the authoring loop.
Watch out for
False positives will decide whether anyone keeps it in CI — truncation is often deliberate, so suppression has to be as easy as the finding, and the detector should trust an explicit text-overflow: ellipsis on an ancestor rather than flagging it. The second trap is nondeterminism: unpinned fonts, lazy images, and animations all shift measurements, and a check that fails randomly gets deleted within a week.