Pluralization
Leaves can be plural objects keyed by CLDR category (zero | one | two | few | many | other). Ilingo selects the matching form via Intl.PluralRules keyed by the resolved locale.
TS/JS: definePlural
Author plurals with the definePlural helper. Its argument type is PluralForms, so you get autocomplete for the CLDR categories and a compile error on a missing other / non-CLDR key:
import { defineNamespace, defineTranslations, definePlural } from 'ilingo';
defineNamespace('cart', [
defineTranslations({
items: definePlural({
one: '{{count}} item',
other: '{{count}} items',
}),
}),
]);definePlural returns a plural node ({ type: 'plural', data: forms }). A plain { one, other } object passed to defineTranslations is not a plural — it's a key-nested map, so siblings called one, other, etc. are reachable via dotted access. Only a node produced by definePlural (or the literal { "type": "plural", ... } form in JSON) is interpreted as a plural.
JSON
JSON cannot call functions, so a plural is spelled as a literal plural node inside the file's translations node:
{
"type": "translations",
"data": {
"items": {
"type": "plural",
"data": { "one": "{{count}} item", "other": "{{count}} items" }
}
}
}Both forms produce identical runtime data — Intl.PluralRules doesn't care which authoring path produced the leaf.
Selection rules
await ilingo.get({ namespace: 'cart', key: 'items', count: 0 }); // 'other' (en has no 'zero')
await ilingo.get({ namespace: 'cart', key: 'items', count: 1 }); // 'one'
await ilingo.get({ namespace: 'cart', key: 'items', count: 5 }); // 'other'- If the selected category is absent,
otheris used. - The locale used by
Intl.PluralRulesis the resolved locale (the one that actually yielded the leaf), not the requested one. Useful whenen-US → enfalls back and you want the English plural rules to apply.
Caching
Intl.PluralRules instances are cached per locale on the Ilingo instance. Repeated calls do not reallocate.
Round-tripping
Plural leaves go through store.set() cleanly — StoreSetContext.value accepts a string or a plural node (definePlural(...) / { type: 'plural', data }), not the unwrapped PluralForms, so the store recognises and unwraps it on read. FSStore.set persists it as JSON unchanged.