Skip to content

andersoncustodio/i18n

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@andersoncustodio/i18n

Lightweight internationalization (i18n) library with:

  • Variable interpolation ({{name}})
  • CLDR plural rules (zero | one | two | few | many | other)
  • Locale and missing key fallbacks
  • PluralRules caching for performance
  • Zero dependencies (uses native Intl.PluralRules)

Installation

npm install @andersoncustodio/i18n

Requires Node >= 14.

Basic Usage

const { I18n } = require('@andersoncustodio/i18n');

const locales = {
    en: {
        greeting: 'Hello, {{name}}!',
        items: { zero: 'No items', one: 'One item', other: '{{count}} items' }
    },
    pt: {
        greeting: 'Olá, {{name}}!',
        items: { zero: 'Nenhum item', one: 'Um item', other: '{{count}} itens' }
    }
};

const i18n = new I18n(locales, () => 'en');

i18n.t('greeting', { name: 'João' });     // Hello, João!
i18n.t('items', { count: 0 });            // No items
i18n.t('items', { count: 1 });            // One item
i18n.t('items', { count: 5 });            // 5 items

Pluralization

Uses Intl.PluralRules to determine the correct plural category based on locale and count.

CLDR Categories

Category Description Example languages
zero Zero quantity Arabic
one Singular English, Portuguese, Russian
two Dual Arabic
few Few items Russian (2-4), Arabic (3-10)
many Many items Russian (5-20), Arabic (11-99)
other Default/fallback All languages

Russian Example

const ru = {
    items: {
        one: '{{count}} предмет',      // 1, 21, 31...
        few: '{{count}} предмета',     // 2-4, 22-24...
        many: '{{count}} предметов',   // 0, 5-20, 25-30...
        other: '{{count}} предмета'
    }
};

const i18n = new I18n({ ru }, () => 'ru', { defaultLocale: 'ru' });

i18n.t('items', { count: 1 });   // 1 предмет
i18n.t('items', { count: 2 });   // 2 предмета
i18n.t('items', { count: 5 });   // 5 предметов
i18n.t('items', { count: 21 });  // 21 предмет

Arabic Example

const ar = {
    items: {
        // 0
        zero: 'لا عناصر',
        // 1
        one: 'عنصر واحد',
        // 2
        two: 'عنصران',
        // 3-10
        few: '{{count}} عناصر',
        // 11-99
        many: '{{count}} عنصراً',
        // 100+
        other: '{{count}} عنصر'
    }
};

const i18n = new I18n({ ar }, () => 'ar', { defaultLocale: 'ar' });

i18n.t('items', { count: 0 });   // 'لا عناصر'
i18n.t('items', { count: 2 });   // 'عنصران'
i18n.t('items', { count: 11 });  // '11 عنصراً'

Fallbacks

  • Missing category falls back to other
  • Explicit zero key is used when count === 0, even if the language doesn't have a grammatical zero (like English)

Interpolation

Strings with {{variable}} are replaced with values from options:

i18n.t('greeting', { name: 'World' });  // Hello, World!
i18n.t('greeting');                     // Hello, {{name}}!

API

new I18n(locales, getLocale?, options?)
  • locales - Object with locale translations
  • getLocale - Function returning current locale
  • options.defaultLocale - Fallback locale (default: 'en')

Methods

  • t(keyPath, options?) - Translate a key
    • options.count - Number for pluralization
    • options.* - Variables for interpolation

Getters

  • locale - Current active locale
  • locales - Array of available locales

AsyncLocalStorage Example

const { AsyncLocalStorage } = require('node:async_hooks');
const { I18n } = require('@andersoncustodio/i18n');

const storage = new AsyncLocalStorage();
const i18n = new I18n(locales, () => storage.getStore()?.locale);

storage.run({ locale: 'pt' }, () => {
    console.log(i18n.t('greeting', { name: 'Maria' }));
});

License

MIT

About

Lightweight i18n library with interpolation and pluralization

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors