Appearance
ICU interpolation
Translation strings hold templates. Your app passes values when calling t().
Simple variables
String in admin:
text
Hello, {name}!In code:
ts
t("common.welcome", { name: "Ada" });
// → "Hello, Ada!"Plurals
String in admin:
text
{count, plural, one {# item} other {# items}}In code:
ts
t("items.count", { count: 1 }); // → "1 item"
t("items.count", { count: 3 }); // → "3 items"Plural rules follow the active locale via ICU MessageFormat.
Select rules
ICU select and selectordinal are supported through the same formatter. Prefer plurals for counts; use select for gender or enum-like branches.
Where values live
| Stored in StringPush | Passed in your app |
|---|---|
"Hello, {name}!" | { name: user.displayName } |
| Plural template | { count: cart.items.length } |
Translators edit templates; developers supply runtime data — same model as i18next, FormatJS, and most TMS exports.
Framework adapters
All adapters delegate to the same t(key, values) API:
- React —
useTranslation()and<Trans values={…} /> - Vue —
useTranslation() - Angular —
translatepipe with params
Troubleshooting
| Symptom | Fix |
|---|---|
Literal {name} in UI | Pass { name: … } to t() |
| Wrong plural branch | Check locale; verify count is a number |
| Raw ICU string shown | Malformed MessageFormat in bundle — fix string in admin |
Malformed ICU in a published string falls back to the raw template so your app keeps running.