ICU Message Format
Translate ICU MessageFormat messages with the Babelize SDK: plural, select, and selectordinal stay intact while only the human-readable text changes.
The SDK supports ICU MessageFormat — the standard for complex pluralization, gender selection, and ordinal numbers. Use babelize.icu() for messages that need more than a simple singular/plural split.
Basic Usage
import { babelize } from "@babelize/sdk";
babelize.icu(
"{count, plural, one {# item} other {# items}}",
{ count: 3 },
);How It Works
babelize.icu():
- Parses the message into an AST — no fragile string splitting.
- Translates the leaf text inside each
plural/select/selectordinaloption through the normal Babelize translation pipeline (cache →/v1/translate). - Preserves the ICU structure exactly:
#(pound),{arg}placeholders,number/date/timeformatters, and rich-text tags are never touched. - Formats the translated message with your values via
Intl.MessageFormat.
If the string isn't valid ICU (or has no ICU syntax), it falls back to a plain t() translation.
The build plugins don't extract babelize.icu() messages into the lockfile. Each option's text is looked up like any babelize() string, so it is translated only when that exact text is in the lockfile or the SDK was initialized with an API key (server-side). In the browser, without a key, use babelize.p() or babelize.plural() for plurals that should be translated at build time.
Plural
babelize.icu("{count, plural, one {# item} other {# items}}", { count: 1 }); // "1 item"
babelize.icu("{count, plural, one {# item} other {# items}}", { count: 5 }); // "5 items"Note the # is ICU's placeholder for the plural value — it's resolved automatically.
Select (gender, etc.)
babelize.icu(
"{gender, select, male {He} female {She} other {They}}",
{ gender: "male" },
);SelectOrdinal
babelize.icu("{n, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}", { n: 3 }); // "3rd"Nested Plural + Select
babelize.icu(
`{gender, select,
male {He has {n, plural, one {# apple} other {# apples}}}
female {She has {n, plural, one {# apple} other {# apples}}}
other {They have {n} apples}}`,
{ gender: "female", n: 2 },
);Arguments and Formatters Are Preserved
babelize.icu(
"{count, plural, one {# item} other {# items}} — {total, number} in {folder}",
{ count: 2, total: 1234.5, folder: "inbox" },
);The {total, number} formatter and {folder} placeholder pass through translation untouched and are formatted per the active locale.
In React
import { useBabelize } from "@babelize/sdk/react";
function CartItemCount({ count }: { count: number }) {
const babelize = useBabelize();
return (
<p>
{babelize.icu(
"{count, plural, one {# item} other {# items}}",
{ count },
)}
</p>
);
}Translation Semantics
ICU structure is preserved exactly; only the human-readable text inside options is translated. This means a message authored once in English can be translated and formatted correctly in any locale — including languages whose plural rules differ from English — because the plural/select options are already expanded and the target translation is applied per option.
Further Reading
Last updated: 2026-11-01
Pluralization
Handle plurals with the Babelize SDK: simple singular and plural pairs, explicit CLDR forms such as few and many via Intl.PluralRules, React usage, and storage.
Context-Aware Translation
Translate whole sentences that contain React elements like links and bold text. babelize.tag() keeps each sentence intact so languages can reorder parts.