Skip to content
Locale Lab

A field guide to the technical side of localization.

21 short chapters on how software breaks in other languages, written for the people who work alongside a localization team: product managers, engineers, designers, marketers. Each chapter pairs a live demo with the mechanism underneath it and a note from a real incident.

The parts read in order, starting with failures visible on screen. Dipping in also works: every chapter stands alone. The last chapter is the audit: a checkout screen shipped broken in three markets, with twelve planted bugs to find.

Start with one of these

Three chapters answer the questions planning meetings ask most. Each demo runs in under a minute with no setup.

Part 1

Getting oriented · What localization work is made of

Four terms (i18n, l10n, g11n, t9n) and four layers of machinery (Unicode, CLDR, ICU, BCP 47) cover most of this guide. One chapter puts them in place before the others use them.

  1. 01OrientationWhat localization work is made of~6 minOne sentence rendered in three locales, and the four layers that did the work: Unicode characters, CLDR data, the ICU/Intl engine, and the BCP 47 tag that named the request.

Part 2

Three visible failures · Layout swell, formatting, plural grammar

The three most common ways a shipped product breaks in another language. These chapters also establish the habit the rest of the guide depends on: the locale decides, not the code.

  1. 02Text expansionTranslation length variance & layout flex~6 minA button resized against real German, Russian, and Finnish strings until it breaks, with the swell measured in pixels and characters.
  2. 03FormattersIntl.* APIs and CLDR data~8 min$1,234.56 / 1.234,56 € / ¥1,235 / ١٬٢٣٤٫٥٦: one number, 24 locales. Skeleton-style controls included.
  3. 04Plurals & genderNumeric agreement & gender selection~10 minOne count, dragged across languages, renders each language's own plural forms (яблоко / яблока / яблок), with a trace of how an i18n runtime resolves the string. Ordinals and gender are included.

Part 3

The Intl toolbox · The APIs that already know the answer

The browser ships locale data for lists, ranges, sorting, time zones, and calendars, plus the negotiation step that decides which locale a user gets. Most i18n bugs come from code that does not ask it.

  1. 05Lists & rangesList, range & duration formatting~6 min'A, B und C', 'Jan 3 – 5', '2–4 items', '1 hr 20 min': the joining and range side of the Intl API surface. The connective word and the collapsed date are both locale data.
  2. 06SortingLocale-aware sorting and comparison~6 minPolish ł sorts between l and m. Swedish ä sorts after z. German has two competing orderings (dictionary vs phonebook). Icelandic sorts the phone book by first name. The same list reshuffles across six locales.
  3. 07Time zonesTime zones & calendar edge cases~8 minHalf-hour offsets, leap seconds, the day Samoa skipped Dec 30, and why Australia/Lord_Howe shifts the clock 30 minutes for DST.
  4. 08CalendarsCalendar systems & week conventions~8 minJuly 29, 2026 is also 15 Safar 1448, 15 Av 5786, and Reiwa 8. Eight calendars over one date, both modern Japanese era changes frame by frame, and the locale data that says whose weekend is Friday.
  5. 09Locale fallbackLocale matching & fallback chains~8 minThe bundle has pt-PT and a user arrives from São Paulo. The demo shows which language they get, and which of three negotiation algorithms decided.

Part 4

Scripts and layout · Writing systems meet CSS

Text that wraps by dictionary, fonts negotiated per character, right-to-left scripts, and layouts that must mirror. None of these bugs appear in an English-only build; they surface only once the locale loads.

  1. 10Line-breakingWrapping rules & word segmentation~7 minWhy CSS `line-break: strict` matters for CJK and Thai, and what happens at narrow widths in 9 locales.
  2. 11CJK fallbackFont stacks & glyph coverage~7 minThe font the browser used for each glyph, and why a 'pure sans-serif' headline switches to the OS default for one Hanzi, with a different default on each platform.
  3. 12BiDiUnicode bidi algorithm & directional isolates~10 minNumbers, English brand names, code, and timestamps embedded in an Arabic sentence show what Unicode isolates fix and what they do not.
  4. 13RTL mirroringLayout mirroring & CSS logical properties~8 minThe same app frame built twice (physical CSS against logical CSS), toggled between English and Arabic. Chevrons, progress bars, and paddings mirror in one column and break in the other.

Part 5

Strings, names, and input · Data that comes from people

A string's .length lies. Names do not fit a first/last schema, and most parsers fail on 1.234,56.

  1. 14Unicode pitfallsStrings, bytes, and what users see~8 mintoLocaleLowerCase('tr') turns 'ID' into 'ıd', not 'id' (this is how Spring CVE-2024-38820 happens). 'café' === 'café' returns false. 'family emoji'.length === 11.
  2. 15EncodingBytes, encodings, and charset mismatch~7 minThe same text as UTF-8 bytes vs UTF-16 code units. Then a live mojibake reproduction: café saved as UTF-8 and misread as Windows-1252 becomes café, computed in the browser.
  3. 16Input parsingLocale-aware input handling~7 minNumber('1.234,56') is NaN. A German user typing a price, an Egyptian user typing ١٢٣٤, and a parser that asks the locale for its separators before it reads a digit.
  4. 17Address & namePersonal data & form fields~8 minPatrick McKenzie's 40 falsehoods, applied to a real form. UK postcode vs JP 〒, Spanish two surnames, Hungarian surname-first, why most CRM schemas are wrong.

Part 6

Shipping translations · The pipeline, the QA step, the audit

How strings travel: externalization, translation files, translation memory, the pseudolocalization pass that finds bugs before translators start, and the review round that scores the returned work. The last chapter is an audit over everything covered.

  1. 18Translation pipelineExternalization, file formats & TM~9 minA hardcoded string gets externalized, the same message appears as gettext PO, XLIFF 2.0, and ICU JSON, and a translation memory prices repetition with fuzzy matches.
  2. 19PseudolocPre-translation QA~6 minAny pasted string comes back in accented, expanded, and RTL-flipped variants. CI pipelines run the same wire-protocol-friendly transforms.
  3. 20LQA scoringHow to measure translation quality~12 minA seeded review round: ten German checkout segments, each error filed by MQM dimension and severity, and the official penalty arithmetic deciding whether the delivery passes. Clean segments are included, because over-flagging also costs.
  4. 21The auditEvery failure class, composed~15 minA checkout screen shipped in three markets, with twelve planted failures drawn from across the guide. Flag them all, then check against the answer key.