Live chat is one of the few products where i18n really matters at the edge. A French visitor on a Spanish e-commerce site will not type in English. A Japanese visitor will close the tab if the placeholder text is in English. We chose 12 languages for muro, covering ~80% of the public internet by visitor count, and built the widget i18n in a way that adds about 2 KB to the bundle.
The 12 supported languages
EN · FR · ES · DE · IT · PT · NL · JA · KO · ZH · AR (RTL) · RU. Eleven UI strings each, welcome, online status, reply ETA, typing indicator, type-message placeholder, send, attach, new message, conversation closed, reopen, powered-by line.
Resolution order
- 01Per-website language in the muro dashboard (
config.language) - 02
navigator.language(browser preference) when the site is set to auto-detect - 03
<html lang="…">of the host page - 04English fallback
In practice, most websites set the per-site default to match the site's primary language and let navigator.language override for visitors browsing in another tongue. That covers the long tail.
RTL: Arabic
Arabic flips everything, text direction, the side the launcher sits on, the bubble corners. We detect RTL via a simple isRtl(lang) check and add dir="rtl" on the widget root. Tailwind's logical properties (ms-3 instead of ml-3) handle the rest:
tsx<div dir={isRtl(lang) ? 'rtl' : 'ltr'} className="muro-widget">
<header className="ps-3 pe-2">…</header>
</div>Where the strings live
Plain TypeScript module, src/lib/i18n.ts, keyed by language code. No fancy ICU MessageFormat, no plural rules library; the strings we need are 11 short labels with at most one variable. JSON would have worked too; TS gives us autocomplete on the keys for free.
Agent side: the inbox stays English
The dashboard UI is in English regardless of the visitor's language, agents work in one tongue, see incoming messages in whatever language the visitor wrote. We deliberately don't translate the message body even when we detect a mismatch; agents prefer raw text + their own translation tool (DeepL, Apple's built-in) over an automatic translation that might subtly change meaning.
Adding a 13th language
It's a single file edit + a one-line type union update. Languages have come up: Polish, Turkish, Greek, Hebrew (RTL). We'll add them when we see real demand, typically when one customer's biggest market is in that language.
Multilingual chat is a quiet detail that earns trust the moment a visitor sees their language reflected back. It's also a feature we get asked about more than we'd expect, so this article exists mainly so the next person who asks gets a link instead of a paragraph.
