AI for Translation & Localization
Capable · M12 · lesson 12 of 21 · queued
Preview — browse every lesson free. Enroll to mark lessons complete, open partner links and save your progress. Login & enroll →
Locale Correctness
📖
now learning

Locale Correctness

15 min

The invoice that almost cost a German manufacturer a quarter of a million euros read perfectly. Every word of the English source had been rendered into flawless, idiomatic German by an LLM, a large language model, a general-purpose text predictor that translates as a side effect of guessing plausible next words. The reviewer skimmed it, nodded, and signed off, because it read like something a native speaker had written. The number in the total field was 1.250.000,00 in the German output, faithfully carried from a source that read 1,250,000.00. The catch was that the source had been a US English document where the comma is the thousands separator and the period is the decimal point, and the engine, working segment by segment, had treated one segment's 1.250 as a German-style number meaning one thousand two hundred fifty and "corrected" it back to 1,250 US-style in a later line item, while leaving the grand total in German notation. Two numbers in the same document now disagreed with each other by a factor of a thousand, and both read as completely natural to the eye that was reading for language. Nobody had mistranslated a single word. The German was beautiful. The locale was broken, and the broken locale is the subject of this entire lesson: the conventions an engine gets subtly, confidently, and expensively wrong while the prose stays gorgeous.

Locale Is Not Language

The first thing to unlearn is the assumption baked into the word "translation": that the job is converting one language into another. A locale is not a language. A locale is the full set of conventions a particular group of people uses to format and interpret information: how they write a date, which symbol separates the thousands from the hundreds in a number, where the currency sign sits relative to the amount, what unit they measure distance in, how formally they expect to be addressed, and how their names and addresses are ordered. Language is one ingredient of a locale. It is not the whole recipe, and the conventions that surround the language are exactly the ones an engine optimized for fluent prose treats as negligible decoration when they are in fact load-bearing facts.

The clearest way to feel the difference is to notice that the same language has many locales, and they disagree with each other in ways that matter. English is spoken in the United States and the United Kingdom, and the two are not interchangeable. en-US writes the date month first, as 03/04/2026 meaning the fourth of March; en-GB writes the same date day first, as 03/04/2026 meaning the third of April. Same digits, same separators, same language, opposite meaning, and no word in the sentence tells you which one you are looking at. en-US measures fuel economy in miles per gallon and weather in Fahrenheit; en-GB uses miles for road distance but litres at the pump and Celsius for weather, and writes "colour," "centre," and "organise" where en-US writes "color," "center," and "organize." A translation memory built for one is wrong for the other in a hundred small ways, and an engine that was trained on a soup of both will pick whichever convention was statistically more common in its training data, not the one the target market actually uses.

German shows the same fracture. de-DE, the German of Germany, and de-CH, the German of Switzerland, share grammar and vocabulary almost entirely, and then diverge on the conventions that surround the words. de-DE uses a period as the thousands separator and a comma as the decimal point, so a million and a half is 1.500.000,00; de-CH uses an apostrophe or a thin space for thousands, writing 1'500'000.00, and uses a period for the decimal. de-DE prices in euros; de-CH prices in Swiss francs, written CHF or Fr. and usually placed before the amount. de-CH famously does not use the letter ß at all, writing "Strasse" where de-DE writes "Straße." Two locales, one language, and a number formatted for the wrong one is not a stylistic preference. It is a factual error a Swiss reader will read as an amount different from the one you meant.

A locale is everything a market expects around the words, not the words themselves. The same language splits into locales that format the same fact in incompatible ways, and no amount of fluent prose tells you which convention is correct.

Why the Engine Is Structurally Blind Here

An MT engine, a machine-translation system that converts source text to target text without a human writing the words, and an LLM are both built to produce text that reads as natural target-language prose. Locale conventions are not prose. They are formatting facts that live in the same sentence as the words but obey rules that have nothing to do with grammar or fluency, and the engine has three structural weaknesses with them. First, it works segment by segment, the small unit of text the translation tool feeds it, so it rarely sees the whole document at once and cannot keep number formatting consistent across segments the way the opening invoice failed to. Second, it has no knowledge of which target locale you actually want unless you tell it; a request to "translate into German" does not say de-DE or de-CH, and the engine will guess. Third, and most dangerously, when it does reformat a number, a date, or a unit, it does so silently and fluently, producing a result that looks correct and is wrong, which is the exact failure mode this whole program is built to catch: the fluent error that does not trip the eye because it reads perfectly.

This lesson uses the word i18n, the standard abbreviation for internationalization (the eighteen letters between the i and the n), for the practice of building content and software so that locale conventions can be swapped per market, and the related discipline of getting those conventions right for a given market is the heart of locale correctness. Internationalization (i18n) gives you the slots; locale correctness is filling each slot with the convention the target market actually uses. The engine fills the slots fluently and frequently wrongly, and the rest of this lesson is a guided tour of the specific traps, why they cost money, and how a real locale quality assurance pass catches them.

The Date Trap and the Number Trap

Two of the traps are so common, so silent, and so expensive that they deserve to be taken first and slowly: dates and numbers. They share a property that makes them uniquely dangerous, which is that the same string of characters is valid in more than one locale and means something different in each, so there is no malformed output to alert you. The error is not a broken thing. It is a correct-looking thing that means the wrong number or the wrong day.

Date Order: The Ambiguity With No Warning

Date order is the trap that catches everyone because the danger zone is invisible. There are three common orderings in the world. The United States uses month, day, year, so 03/04/2026 is the fourth of March. Most of Europe, Latin America, and much of the rest of the world uses day, month, year, so the same 03/04/2026 is the third of April. The international standard, ISO 8601, uses year, month, day, writing 2026-03-04, which is unambiguous and is the only format that cannot be misread, which is precisely why engineering pipelines store dates in it. The cruelty is in the overlap: for any day of the month from the thirteenth onward, the day number is greater than twelve, so a human or a machine can tell month-first from day-first because no month is the seventeenth. But for the first twelve days of any month, both readings are valid numbers, and 03/04/2026 is genuinely, mathematically ambiguous. The engine does not flag it. It just picks one, usually the convention most common in its training data, and produces an output that reads as a perfectly ordinary date and is off by, in the worst case, weeks.

The cost lands wherever a date drives an action. A contract expiry, a medication schedule that says to take a dose until a certain date, a shipping deadline, a warranty window, an appointment, a regulatory filing cutoff. Flip the day and the month on a "discontinue treatment by" date and you have a clinical safety error wrapped in fluent prose. Flip it on a payment-due date and you have a missed contractual deadline. The engine that swapped the order did nothing a reader can see, because the output is a real date, just the wrong one. The defense, which the quality assurance pass at the end of this lesson encodes, is never to trust a numeric date the engine produced and always to verify it against the source and reformat it into the unambiguous target-locale convention rather than carry the source's separators and order across untouched.

Decimal and Thousands Separators: The Factor of a Thousand

The number trap is the one from the opening invoice, and it is worth being precise about, because the symbols are simply swapped between major locales. In en-US and en-GB, the comma groups thousands and the period marks the decimal: one and a half million dollars and fifty cents is 1,500,000.50. In de-DE, French, Spanish, Italian, and much of continental Europe, the roles are reversed: the period (or a space) groups thousands and the comma marks the decimal, so the same amount is 1.500.000,50. Switzerland uses an apostrophe for thousands. India groups differently again, by two digits after the first three, so a hundred thousand is written 1,00,000 in the Indian numbering system. The same digit string, 1.250, means one and a quarter in a US document and one thousand two hundred fifty in a German one. There is no error message. There is only a number that reads as natural and is wrong by three orders of magnitude.

The engine fails at this in two distinct ways, and a good post-editor, the linguist who corrects machine output (the work is called MTPE, machine-translation post-editing), learns to watch for both. The first is failing to convert: the engine carries the source's separators straight into the target, so a US 1,250.00 appears unchanged in German text where a reader expects 1.250,00, and the German reader, applying German rules, reads 1,250.00 as one comma two five zero, a nonsense number, or worse, reads 1,250 as one and a quarter. The second is over-correcting inconsistently, the opening invoice's failure: the engine reformats some numbers and not others, or reinterprets a source number under the wrong locale's rules and reformats from that misreading, so different parts of the same document disagree. Both failures read as fluent. Neither is caught by reading for meaning, because there is no meaning in a separator; there is only a convention, and the convention is either right for the target locale or silently, expensively wrong.

Dates and numbers are the deadly traps because the wrong output is not malformed, it is a valid-looking date or number that means something different in the target locale. There is no error to see, only a fact that is quietly off by weeks or by a factor of a thousand.

Units, Currency, and the Conversion the Engine Must Not Improvise

Dates and numbers are silent traps. Units and currency are louder, but they carry a second danger the engine is uniquely bad at: they sometimes require an actual conversion, a change in the value and not just the format, and an engine asked to convert will improvise a number that looks authoritative and is frequently wrong.

Measurement Units

Measurement units split the world into the metric system, used almost everywhere, and the US customary system of miles, pounds, gallons, and Fahrenheit, with the United Kingdom sitting in a famous halfway house of miles and pints alongside Celsius and litres. The locale question with units has two layers. The first is whether to convert at all. A recipe that says "preheat to 350°F" localized for a German audience should become "175°C," an actual conversion of the value, because a German oven is marked in Celsius and 350 degrees on it would be a furnace. A technical specification for a machine bolt, by contrast, must keep its exact engineering measurement and might add the converted value in parentheses rather than replace it, because the part is manufactured to one specification regardless of the reader's locale. Deciding which kind of content you are localizing is a human judgment about purpose, and the engine does not make it; it either leaves the unit untouched, which strands a Fahrenheit oven temperature in a Celsius market, or it converts when it should not have, silently changing a spec.

The second layer is the conversion itself, and this is where the engine is genuinely dangerous. Asked to turn miles into kilometres, an LLM will produce a number, and that number is generated as plausible text, not computed by a calculator, so it can be subtly wrong. It may round in a way that misstates a distance, or apply the conversion factor approximately, or convert correctly but then carry a number with false precision that implies an accuracy the source never had. A "5 mile" hike becoming "8.04672 km" is technically near-correct and practically absurd; the same hike becoming "8 km" is right; the same hike becoming "8.5 km" is simply wrong and reads exactly as confidently as the correct answer. Unit conversion is arithmetic, and arithmetic is the one thing a text predictor is structurally not doing even when it emits a number, which is why a locale quality pass treats every engine-produced converted value as a claim to be checked against an actual calculation, not a fact to be trusted.

Currency: Symbol, Placement, and the Conversion That Must Not Happen

Currency layers three separate problems on top of the number-separator trap. The first is the symbol itself: dollars, euros, pounds, yen, francs each have their own sign, and the same sign can mean different currencies, since $ is the United States dollar, the Canadian dollar, the Australian dollar, and several Latin American pesos, so a bare $ is ambiguous across locales and the unambiguous three-letter ISO code, USD, CAD, AUD, EUR, GBP, CHF, JPY, is what a careful localization uses where the currency could be mistaken. The second problem is placement, which varies by locale even for the same currency: en-US writes the symbol before the amount with no space, $1,250.00; many European locales write the symbol after the amount with a space and use their own separators, so the euro amount is 1.250,00 € in German and 1 250,00 € in French. An engine that carries the source placement into the target produces a price that reads as foreign and wrong to the local eye, the small tell that the content was machine-handled and never localized.

The third problem is the most dangerous and the one a quality pass guards most fiercely: whether a currency conversion should happen at all, and the answer is almost always no. Converting $1,250 into euros requires an exchange rate, exchange rates change every second, and a converted price baked into translated text is wrong the moment the rate moves and is a commercial and sometimes legal liability if it understates or overstates a real charge. The correct localization of a currency amount in running text is almost never to convert the value; it is to keep the amount and present it correctly, or to leave price display to the application's own pricing logic, which knows the live rate and the customer's actual currency. An engine asked to "make this German" may helpfully convert the dollar figure to a euro figure at some invented rate, producing a number that is fluent, specific, and a fabrication. The rule the post-editor carries is blunt: the engine formats currency, it does not convert it, and any converted figure the engine produced is a hallucination until a human with the actual rate and the actual business rule confirms it.

Formality, Register, and the Address the Engine Gets Too Friendly

Numbers and units are facts. Formality is relationship, and it is the locale trap that does not crash anything and still loses customers, because getting it wrong is not an error the reader sees as a mistake. It is an error the reader feels as rudeness or as cloying false intimacy, and either one quietly damages the brand.

Formality, in the localization sense, is the register the language uses to encode the social distance between the speaker and the addressed person: how formal, how familiar, how respectful or how casual the address is. Many languages grammaticalize this distinction in a way English does not. The textbook case is the T-V distinction, named for the Latin pronouns tu and vos, the split between a familiar second-person form and a formal one. German has du (familiar) and Sie (formal); French has tu and vous; Spanish has and usted; Italian, Portuguese, Russian, and many others carry their own version. Choosing which to use is not a stylistic flourish. It is a decision about how the brand relates to the reader, and in some markets the wrong choice is a genuine offense: addressing an older or professional German customer as du in a banking app reads as presumptuous and disrespectful, while addressing a young consumer-brand audience as Sie in a casual gaming app reads as stiff and out of touch.

English source text hides this entirely. English "you" carries no formality marking at all, so an engine translating from English into German or French has to manufacture a formality level that the source did not specify, and it will pick one based on what was statistically common in training rather than what the brand requires. The result is usually inconsistent: the same product addresses the user as Sie in one screen and du in the next, because different segments triggered different statistical patterns, and the inconsistency itself reads as careless even before you judge whether either choice was right. East Asian languages raise the stakes further. Japanese encodes formality and honorific register far more elaborately than the T-V split, through entire systems of polite and humble and honorific verb forms (keigo), and an engine that produces fluent Japanese at the wrong politeness level produces text that is grammatical and socially wrong in a way that a Japanese reader registers instantly. Korean and several other languages carry comparable honorific systems. The formality decision is a brand and cultural judgment a human must set and enforce; the engine's job is to obey the chosen register consistently, and left to itself it neither chooses well nor stays consistent.

Address Formats and Name Order

Formality's quieter cousin is the structure of names and addresses, which varies by locale in ways that break forms and salutations when an engine or a template assumes the source structure is universal. Name order is the headline: many cultures, including Chinese, Japanese, Korean, Hungarian, and others, write the family name before the given name, so a Western template that labels the first field "first name" and greets the customer by it can address a Japanese customer by their family name as if it were intimate, or scramble the two entirely. Honorific titles and their placement vary. Address structure varies deeply: the order of street, number, postal code, district, city, and region differs by country, the postal code's position and format differ, and some locales put the house number before the street name while others reverse it. A salutation generated from a misparsed name, "Dear Mr. Tanaka Hiroshi" where the polite form is "Tanaka-san," or a mailing address assembled in the wrong order so the postal sort fails, is a locale error that an engine reproducing the source structure will create confidently and a reviewer reading only for language will skim straight past.

Formality is relationship, not fact, so its errors do not crash, they offend. English hides formality entirely, forcing the engine to invent a register the source never specified, and the brand pays for the invention in trust.

Sorting, Encoding, and the Traps Under the Text

Beneath the visible conventions sit two more locale traps that operate below the level of the sentence and break things a reader of the prose will never notice: collation, the locale-specific rules for sorting, and encoding, the system that maps characters to bytes.

Sorting Is a Locale Rule, Not an Alphabet

Alphabetical order feels universal until you cross a locale boundary. The order in which characters sort, called collation, is a property of the locale, not of the letters, and it differs in ways that surprise everyone who assumes A through Z is settled. Swedish sorts the letters å, ä, and ö after z, at the end of the alphabet, while German treats ä, ö, and ü as variants of a, o, and u and sorts them near those letters, so the same list of names comes out in a different order depending on which locale's rules apply. Spanish historically treated "ll" and "ch" as single sorting units. Languages with non-Latin scripts have entirely their own collation orders, and some scripts sort by stroke count or radical rather than by a phonetic alphabet. A directory, an index, a dropdown of countries, an autocomplete list, a sorted table of results: every one of these depends on collation, and a list sorted with the wrong locale's rules is subtly out of order in a way that makes a local user distrust the product, because the names are not where they expect to find them. The engine translating the list entries does nothing to the sort order; the locale failure is in the pipeline that sorts them, and it is the localization engineer's and the quality pass's job to ensure the sort uses the target locale's collation, not the source's.

Encoding: The Bytes That Carry the Locale

Encoding is the system that maps the characters you see on screen to the bytes a computer stores, and it is the silent foundation under every locale, because every accented letter, every non-Latin script, every currency symbol, and every special character in a formatted number depends on the bytes being read with the encoding they were written in. The modern standard, UTF-8, can represent every character in every living script, which is why a correctly built pipeline can carry German umlauts, French accents, the euro sign, Cyrillic, Japanese, Arabic, and emoji in the same file without trouble. Encoding failures appear when a file is written in one encoding and read as another: the accented and non-Latin characters turn into mojibake, the garbled runs of question marks, boxes, and nonsense symbols that appear when bytes meant for one encoding are interpreted as another. A German "ü" becomes "ü," a euro sign becomes a three-character smear, an entire Japanese screen becomes a wall of boxes.

Encoding is rarely the engine's own fault, because the engine works in characters, not bytes; it is a pipeline failure at the boundaries where files are imported, exported, and handed between tools, and it is precisely the kind of locale problem that a careful number or formality fix is useless against if the bytes underneath are wrong. But the engine can introduce encoding's quieter relatives: substituting a curly quote for a straight one, a non-breaking space for a regular space, a full-width punctuation mark for a half-width one, or an invisible zero-width character, any of which can corrupt a downstream match, a search, a currency-format check, or a postal-code validation while looking on screen exactly like the correct character. A locale that is perfect in every visible convention and broken in its encoding displays as mojibake to the very users it was localized for, which is the most visibly amateur failure of all, and the cheapest to prevent by fixing the encoding to UTF-8 end to end and normalizing the characters the engine might silently swap.

A Worked Locale Quality Assurance Pass

Now put it together on a real file, because the discipline only becomes real when it is a repeatable pass rather than a list of warnings. Imagine an English source marketing-and-billing page for a software product, machine-translated into German for the German market (de-DE), pre-populated by the engine into every segment before the post-editor opened it. The page contains a launch date, a price, a trial length in days, a distance figure in a customer testimonial, a formal salutation, and a sorted list of supported countries. The post-editor's locale quality assurance pass does not read it for fluency first; the fluency is the engine's strong suit and the trap. It reads it for locale, convention by convention, against the source and against the de-DE rules.

The pass walks the file with a fixed sequence, and each step catches a specific failure from the lessons above:

  • Confirm the exact target locale. The job says "German," but the pass pins it to de-DE, not de-CH or de-AT, because the separators, currency, and the ß all hinge on which German this is. Every later check uses the de-DE rule set, not a generic "German."
  • Verify every date against the source and reformat to the target convention. The source 03/04/2026 is read against the source's en-US context as the fourth of March, confirmed against any surrounding text, and rewritten in an unambiguous de-DE form, 04.03.2026, never carried across with US order or US separators. Any date in the first twelve days of a month is treated as a flag to check the source explicitly, because that is the ambiguous zone.
  • Recheck every number's separators across the whole document for consistency. The price, the trial-day count, and the testimonial distance are each checked so the period now groups thousands and the comma marks the decimal, and crucially they are checked against each other so no two numbers in the file use different conventions, the failure that broke the opening invoice.
  • Treat every currency figure as format-only and every converted figure as suspect. A US $49.00 becomes 49,00 $ only if dollars are genuinely intended for this market; if the German market is priced in euros, the amount is not converted by the engine at an invented rate but flagged for the pricing logic or a human with the real price, and the symbol moves to the German placement after the amount.
  • Verify any unit conversion with an actual calculation. A testimonial "drove 200 miles to the office" is converted to about 322 km only after the arithmetic is checked by hand or by a calculator, not trusted from the engine's emitted number, and the precision is sanity-checked so it does not read as falsely exact.
  • Enforce one consistent formality throughout. The brand's chosen register, say formal Sie for a billing context, is verified on every salutation and every instruction so the page does not drift between Sie and du across segments, and the salutation parses the customer name in the correct order.
  • Verify the sorted country list uses de-DE collation. The list is checked to sort by German rules, not carried over in the source's English order, so a German user finds each country where German collation places it.
  • Confirm the file is UTF-8 and the special characters render. The umlauts, the ß, the euro sign, and any accented country names are confirmed to display as themselves and not as mojibake, and any engine-substituted curly quotes, non-breaking spaces, or full-width characters are normalized.

Notice what this pass is and is not. It is not a reading for whether the German sounds good; the engine already made it sound good, and that fluency is exactly what let the locale errors hide. It is a structured verification of each locale convention against the source and against the explicit target-locale rule set, in a fixed order, so that no convention is skipped because it happened to read naturally. The output of the pass is a file where every date, number, currency, unit, formality choice, sort order, and byte is correct for de-DE, scored and defensible, rather than a file that merely reads well. This is the same discipline that runs through the whole program, applied to locale: you do not trust the fluent surface, you verify the convention underneath it against the source and the target's actual rules.

The Concrete Locale Checklist

Distilled to something a post-editor can pin beside the screen and run on every file, the locale check is this:

  • Locale, not language. Pin the exact target locale (de-DE vs de-CH, en-US vs en-GB) before checking anything, because every other convention depends on it.
  • Dates. Verify order against the source, watch the first twelve days of the month as the ambiguous zone, and reformat to the unambiguous target convention rather than carrying source order and separators across.
  • Numbers. Confirm the decimal and thousands separators match the target locale and are consistent across the entire document, not just within a segment.
  • Units. Decide convert-or-keep by content purpose, and verify every conversion with real arithmetic, not the engine's emitted number, and avoid false precision.
  • Currency. Use the unambiguous ISO code where the symbol is ambiguous, place the symbol per the target locale, and never let the engine convert a value at an invented rate.
  • Formality and register. Set the brand's T-V or honorific level deliberately and enforce it consistently across every segment; never let the source's unmarked English "you" make the choice for you.
  • Names and addresses. Respect target name order and address structure rather than forcing the source template's field order.
  • Sorting. Ensure any sorted list uses the target locale's collation, not the source's.
  • Encoding. Confirm UTF-8 end to end, verify special characters render as themselves, and normalize engine-substituted characters before delivery.

Key Takeaways

  • A locale is the full set of conventions a market uses to format and interpret information, not the language. The same language splits into locales (en-US vs en-GB, de-DE vs de-CH) that format the same fact in incompatible ways, and fluent prose never tells you which convention is correct.
  • Dates and numbers are the deadly silent traps because the wrong output is not malformed, it is a valid-looking date or number that means something different in the target locale. Date order is genuinely ambiguous for the first twelve days of any month, and decimal and thousands separators are swapped between major locales, so an error can be off by weeks or by a factor of a thousand with no warning.
  • Units and currency sometimes require an actual conversion, and the engine improvises numbers as plausible text rather than computing them. Verify every unit conversion with real arithmetic, and treat currency as format-only: place the symbol per the target locale, use the ISO code where the symbol is ambiguous, and never let the engine convert a value at an invented exchange rate.
  • Formality is relationship, not fact, so its errors do not crash, they offend. English hides formality entirely, forcing the engine to invent a T-V or honorific register the source never specified, which it does inconsistently across segments. The brand must set the register deliberately and enforce it everywhere.
  • Name order, address structure, and collation (locale-specific sorting) are pipeline-level locale traps. Swedish, German, Spanish, and non-Latin scripts each sort differently, and a list sorted with the source locale's rules is subtly and distrust-inducingly out of order for the target user.
  • Encoding maps characters to bytes; UTF-8 carries every living script, and mojibake appears when bytes are read in the wrong encoding. A locale perfect in every visible convention but broken in encoding displays as garbage to the very users it was localized for, the most visibly amateur failure and the cheapest to prevent.
  • A locale quality assurance pass is a fixed-sequence verification of each convention against the source and the explicit target-locale rule set, not a reading for fluency. The fluency is the engine's strength and the trap; the pass exists precisely because a perfectly fluent rendering can carry a locale error the meaning-reader skims straight past.
  • The organizing principle is the program's recurring discipline applied to locale: you do not trust the fluent surface, you verify the convention underneath it against the source and the target market's actual rules, pinning the exact locale first because every other check depends on it.