Translations ($t)
Strings live once, in i18n/<locale>.toml. Everything Android wants — strings.xml per locale, plurals, escaping — is derived from them.
A string
// i18n/en.toml
[home]
title = "Trending"
greeting = "Hello, %s" <Text>{$t("home.title")}</Text>
<Text>{$t("home.greeting", user.name)}</Text> Arguments fill the % placeholders, in order. A % in a string
with no arguments is literal.
Plurals
A table whose keys are CLDR quantities (zero, one, two, few, many, other) is a plural,
and other is required:
[cart]
items = { one = "%d item", other = "%d items" } <Text>{$t("cart.items", count = n)}</Text> Call a plural with count =; call anything else without it. Getting that
wrong is a build error, not a runtime surprise. count is not one of the
positional arguments — it supplies the %d itself.
Checked at build time
Every key is checked when the app builds:
- An unknown key is an error, with the nearest key suggested.
- A key missing from one locale's file is a warning naming it.
- A key nothing calls is a warning.
Debug builds also get Android's en-XA pseudo-locale: every character is
accented (so a literal string that skipped $t stands out in plain English),
the string is padded by the roughly 35% a real translation tends to grow, and the ends
are bracketed so truncation shows. Turning it on:
# whitehall.toml
[i18n]
default = "en"
pseudo = true $t works from a store or a worker as well as a screen, because it is backed
by the application context rather than by a composition.See Also
- Text — the component these usually land in
- Configuration —
[i18n]inwhitehall.toml