DEV Community

golflover
golflover

Posted on

What Shipping Hebrew RTL Actually Takes: Anatomy of an 11-Language Release

Everybody "supports multiple languages." Almost nobody ships Hebrew.

When we closed the v3.131.x line on MeshCtx — an open-core (AGPLv3) memory layer for AI agents — the headline feature wasn't a model integration or a new API. It was making the 11th language, Hebrew, real: not Google-translated menu strings, but a full right-to-left experience with behavioral tests. Here's what that actually involved, with numbers from the public changelog.

The inventory is bigger than you think

  • 1,458 keys in the server-side translation registry, plus 270 landing-page keys and 66 chat keys. That's the whole product surface, catalogued.
  • The Windows installer (NSIS) carries all 11 languages via MUI_LANGUAGE — and yes, there was a bug where page translation binding required MUI_LANGUAGE to be declared before MUI_PAGE. That class of installer-level i18n bug never shows up in your app code.
  • macOS bundles declare CFBundleLocalizations = 11, so the OS-level language picker matches what the app can actually do.

RTL is layout surgery, not translation

Arabic and Hebrew flip the writing direction, and every left-to-right assumption breaks:

  • 10 pages flip their dir attribute for Arabic; the server renders the first screen already set to dir=ar|he, so there's no direction-flip flash on load.
  • Icons, progress bars, back arrows, and numbers embedded inside RTL sentences all need explicit handling. The test suite asserts actual RTL behavior in E2E (Hebrew), not just "the font loaded."
  • The full smoke matrix ran 9/9: wizard, chips, comparison cards, clipboard import, Hebrew-RTL flow, skip-persistence.

Translation quality is a test problem

278 i18n-related tests live inside a regression baseline of 3,790 passing tests. Two checks worth stealing:

  1. Cross-parity: landing-page keys are diffed against source keys, so a deleted feature can't leave orphaned strings behind.
  2. Rendered-layer scanning: all 11 languages × 6 pages are swept for raw key names leaking into the UI — the "you see signup.title instead of text" class of bug, caught before release.

One release fixed 30 stale default model IDs inside i18n_translations.json itself — proof that translation files rot like code does.

Make it ops, not a one-off

The UI shows per-language health badges, so missing coverage is visible and assignable — community contributors can pick a language and see exactly what's missing. A single September batch back-filled 65 pages. Localization became a maintained surface with its own CI story.

Steal these three ideas

  1. Underserved locales are cheap distribution. Competition density in RTL locales is a fraction of English's.
  2. Installer/OS-level localization is part of i18n. If the OS picker says 11 languages, your app better ship 11.
  3. Badges turn translation into a backlog. Visible gaps get closed; invisible gaps rot.

MeshCtx is AGPLv3, downloads for Windows/macOS/Linux on the releases page. If your project is stuck at "English plus machine-translated Spanish," the registry-plus-badges pattern above is the cheapest upgrade path.

Which locale does your tool ignore? It's probably the one your competitors ignore too — that's the opportunity.

Top comments (0)