What is a Locale, and how is it different from the user’s language?

2.2.6 · L2 · Interview

Predict first

What does this print?

print(1234.5.formatted(.number.locale(Locale(identifier: "de_DE"))))
  • 1,234.5
  • 1.234,5
  • 1 234,5

Predict first

What does this print?

let l = Locale(identifier: "fr_CA")
print(l.language.languageCode?.identifier ?? "-", l.region?.identifier ?? "-")
  • fr CA
  • fr FR
  • ca FR

Mental model. Language is what words you speak. Locale is also whether you write 1,234.5 or 1.234,5, and whether the week starts on Sunday or Monday.

Locale bundles the conventions a person expects: language, region, calendar, decimal and grouping separators, currency, measurement system and first weekday. A user can pick English as their language and Germany as their region, and then see dates and numbers formatted the German way while your UI text is in English.

Formatters follow the locale, while your translated strings follow the language list (see the Bundle section). Locale.current is a snapshot; autoupdatingCurrent tracks settings changes. For machine-readable text (wire formats, file names) never use the user’s locale: use a fixed one like en_US_POSIX.

German uses a dot for grouping and a comma for the decimal. The value is the same; only the convention changes.

Language (fr) and region (CA) are separate fields of one locale.

Common traps

  • Formatting wire data with the current locale. A German user would write a decimal comma into your JSON.
  • Equating language with region. “Is this a US user?” is a region question, not a language one.

They might follow up with

  • How do you test other locales? Pass an explicit Locale(identifier:) to the formatter, or set the scheme’s App Region.
  • Is the metric system a locale property? Yes: locale.measurementSystem.

Related questions

  • 2.2.7 FormatStyle or DateFormatter: which do you reach for?
  • 2.6.5 How does the app pick its language at runtime, and how is that different from Locale?

← How does Calendar handle “add a month”, “next Friday” and “start of…   FormatStyle or DateFormatter: which do you reach for? →