docs.core-concepts.icu-lite
ICU-lite formatting
What the built-in formatter supports (interpolation, plural, select, selectordinal) and what it deliberately leaves out.
What ICU-lite is
@ngx-runtime-i18n/core ships a tiny, dependency-free formatter called ICU-lite: interpolation plus plural, select, and selectordinal blocks, modeled loosely on ICU MessageFormat syntax.
import { formatIcu, type Catalog } from '@ngx-runtime-i18n/core';
const catalog: Catalog = {
hello: { user: 'Hello, {name}!' },
cart: { items: '{count, plural, one {1 item} other {# items}}' },
gender: '{gender, select, male {He is a developer} female {She is a developer} other {They are a developer}}',
};
formatIcu('en', 'hello.user', catalog, { name: 'Ashwin' }); // "Hello, Ashwin!"
formatIcu('en', 'cart.items', catalog, { count: 2 }); // "2 items"
formatIcu('en', 'gender', catalog, { gender: 'male' }); // "He is a developer"
formatIcu('en', 'gender', catalog, { gender: 'nonbinary' }); // "They are a developer" (falls back to "other")ICU-lite is not a full ICU implementation. It aims to cover the common 80% of message-formatting needs with a tiny footprint.
Supported
- Basic
{param}interpolation (tokens may include dots and hyphens for nested data). pluralblocks withone,other, exact-match selectors like=0or=2, and#replacement for the count.selectblocks with arbitrary named options (any string value, not justmale/female), falling back tootherwhen the value has no matching option or the param is missing.selectordinalblocks, using the same=nexact-match and#replacement asplural. Without a custom plural resolver,pluralandselectordinalboth fall back to a plainone-if-equal-to-1/otherrule — pass apluralResolverthat implements CLDR ordinal rules to get realone/two/few/otherordinal categories (for "1st"/"2nd"/"3rd"/"4th"-style output).- Nesting
plural,select, andselectordinalblocks inside each other, including the same keyword nested inside itself, to arbitrary depth.#stays bound to its nearest enclosingplural/selectordinalblock even when nested inside aselect. - Nested placeholders inside option bodies (balanced braces are retained).
Not supported
- ICU-style escaping or quoting (
''for a literal apostrophe,'{'to escape a brace) — quotes and braces pass through as written. - Argument types beyond
plural,select, andselectordinal(ICU'snumber,date,time, or custom formatters). - Escaping braces beyond the cases above; unmatched braces must not resemble valid tokens.
If your catalogs need full ICU MessageFormat — number/date/time formatting, or quote/brace escaping — ICU-lite doesn't cover it.
Keeping catalogs predictable
key supports dotted paths (e.g., hello.user) into a nested Catalog object, and formatIcu is pure and side-effect free. Keep catalogs flat-ish and predictable to avoid fragile deep paths.