Core Concepts

Locales and String Formats

BCP 47 locales, the two string formats (text and icu), key naming rules, and how each SDK formats ICU messages.

Locales

Locales are BCP 47 language tags: en-US, ja, pt-BR, and so on. Each locale gets its own published bundle, and SDKs fetch only the locale they need: by default the device or runtime locale, or a fixed one you configure.

Keys

Keys are flat identifiers, not a nested tree. Dots are just a naming convention (onboarding.welcome_title), which keeps lookups unambiguous.

  • Allowed characters: letters, digits, underscore, and dot ([a-zA-Z0-9_.])
  • Length: 1 to 256 characters

Two formats, no more

Every string has exactly one of two formats:

  • text: plain text, served and rendered verbatim.
  • icu: an ICU MessageFormat pattern, parsed at render time with the arguments you pass. Use it for plurals, gendered variants, and value interpolation.

There is no third value, and no default: you choose the format when you create the string.

ICU by example

A plural pattern picks the right variant for a count and substitutes it where # appears:

{count, plural, one {# item} other {# items}}

With count = 3 this renders as 3 items; with count = 1, 1 item.

A select pattern branches on an arbitrary argument:

{gender, select, male {He} female {She} other {They}}

With gender = "female" this renders as She.

Formatting methods per SDK

Each SDK has one method that formats an icu string with arguments:

SDKMethodExample
iOSstring(_:args:)strings.string("items.count", args: ["count": 3])
Androidformat(key, args)airStrings.format("items.count", mapOf("count" to 3))
Webformat(key, args)airstrings.format('items.count', { count: 3 })

Called on a text string, these methods return the value as-is and ignore the arguments. On a formatting error or a missing key they fall back to the raw pattern or the key name. They never throw and never crash your UI.

The braces gotcha

Braces are only meaningful in icu strings. A text string containing {name} is served and rendered verbatim. Nothing interpolates it. If you want placeholders, the string must be icu. The CLI warns when you save a text value that contains braces, but the write still goes through, since literal braces can be legitimate in plain text.

On this page