Typed Locale

Pluralization

Estimated reading time: 3 minutes

Typed-locale provides built-in support for pluralization, allowing you to handle different forms of a phrase based on a count. This is particularly useful for languages that have different rules for singular and plural forms.

Using the plural Function

To define a pluralized phrase, use the plural function in your translation object:

import {plural} from 'typed-locale'; export const en = { youHaveMessages: plural({ none: 'You have no messages', one: 'You have 1 message', other: 'You have {{count}} messages', }), } as const;

The plural function accepts an object with the following properties:

  • none (optional): Used when the count is zero.
  • one (optional): Used when the count is one.
  • other (required): Used for all other cases.

Using Pluralized Translations

When using a pluralized translation, you need to provide a count parameter:

const translator = createTranslator(en); console.log(translator(t => t.youHaveMessages({count: 0}))); // Output: 'You have no messages' console.log(translator(t => t.youHaveMessages({count: 1}))); // Output: 'You have 1 message' console.log(translator(t => t.youHaveMessages({count: 5}))); // Output: 'You have 5 messages'

Type Safety

The pluralization system in typed-locale is fully type-safe. TypeScript will ensure that you provide the required count parameter and will prevent you from using non-existent keys.

Pluralization with Other Variables

You can combine pluralization with other variables in your translations:

export const en = { userMessages: plural({ none: '{{name}} has no messages', one: '{{name}} has 1 message', other: '{{name}} has {{count}} messages', }), } as const; const translator = createTranslator(en); console.log(translator(t => t.userMessages({count: 3, name: 'Alice'}))); // Output: 'Alice has 3 messages'

Handling Complex Pluralization Rules

While the basic none, one, and other cases cover many languages, some languages have more complex pluralization rules. For these cases, you might need to use the other case and handle the specific rules in your application logic.

For example:

export const ru = { apples: plural({ one: '{{count}} яблоко', other: '{{count}} яблок', }), } as const; const translator = createTranslator(ru); function getRussianApples(count: number) { const phrase = translator(t => t.apples({count})); // Apply Russian-specific pluralization rules if (count % 10 === 1 && count % 100 !== 11) { return phrase; } else if ([2, 3, 4].includes(count % 10) && ![12, 13, 14].includes(count % 100)) { return phrase.replace('яблок', 'яблока'); } else { return phrase; } } console.log(getRussianApples(1)); // Output: '1 яблоко' console.log(getRussianApples(2)); // Output: '2 яблока' console.log(getRussianApples(5)); // Output: '5 яблок' console.log(getRussianApples(21)); // Output: '21 яблоко'

This approach allows you to handle complex pluralization rules while still benefiting from typed-locale's type safety and structure.