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:
| SDK | Method | Example |
|---|---|---|
| iOS | string(_:args:) | strings.string("items.count", args: ["count": 3]) |
| Android | format(key, args) | airStrings.format("items.count", mapOf("count" to 3)) |
| Web | format(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.
Projects, Environments, and Promotion
How organizations, projects, and environments organize your strings, and how promotion moves changes between environments without retyping.
Bundles, Signing, and the CDN
What a bundle is, what happens when you publish, why every bundle is signed, and how key rotation works.