Engineeringこの記事を日本語で読む

Dates, numbers, and currency: the formatting bugs that hide in plain sight

Some of the most persistent localization bugs have nothing to do with translated text at all. A date, a number, or a price can be displayed with every word correctly translated and still read as wrong, or even ambiguous, to a player in another region — because the format around the value, not the value itself, is locale-specific.

These bugs are easy to miss in testing because a developer working in their own locale rarely notices that a format string is hardcoded to their own conventions. The bug only surfaces once the game is running for someone else.

Decimal separators and digit grouping

Not every locale uses a period for the decimal point and a comma to group thousands. Many use the reverse — a comma as the decimal point and a period (or a space) to group thousands. A number formatted with a hardcoded period-comma pattern will misrepresent the value for anyone using the opposite convention, and in the worst case make a large number look like a small decimal.

// The same value, formatted for two different locales
1234.5   // one convention
1234,5   // another convention

Date component order

The order of day, month, and year in a written date is not universal. Some locales write day before month, some write month before day, and some write year first. A date like 03/04/2026 is genuinely ambiguous without knowing which convention produced it — it can mean two different dates depending on the reader's assumption.

This matters for anything a player reads as a date: patch notes, event end times, save file timestamps, subscription renewal dates. A hardcoded component order is correct for exactly one convention and silently wrong, or dangerously ambiguous, for the rest.

12-hour vs 24-hour clocks

Time-of-day display splits along similar lines: some conventions use a 12-hour clock with an AM/PM marker, others use a 24-hour clock with no marker at all. An event timer or a daily-reset time shown in the wrong convention is not just cosmetically off — a player can misjudge how much time remains.

Currency symbol position and spacing

Where the currency symbol sits relative to the number, and whether there is a space between them, both vary by locale. Some conventions put the symbol before the number with no space, others put it after with a space, and the symbol itself may differ from the currency code. A store price built by concatenating a hardcoded symbol in front of a number will look correct in the locale it was built for and slightly off — or confusing — everywhere else.

The fix: format at display time, not at storage time

The pattern that avoids all of this is the same across dates, numbers, and currency: store the raw value — a timestamp, a plain number, a price in its smallest currency unit — and never a pre-formatted string. Formatting happens only at display time, using a locale-aware formatting API driven by the player's active locale, not the developer's.

  • Never bake a date, number, or price into a translated string as literal text — pass the raw value and let a formatting function produce the localized string
  • Treat the formatting function's output as the only correct representation for that locale — do not post-process it with your own string replacement
  • Test with at least one locale that uses the opposite decimal separator and date order from your own, specifically to catch hardcoded assumptions

Related articles