WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

andersoncustodio/i18n

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@andersoncustodio/i18n

Lightweight internationalization (i18n) library with:

  • Variable interpolation ({{name}})
  • Simple count-based pluralization (zero | one | other)
  • Locale and missing key fallbacks
  • Message function caching for performance

Installation

npm install @andersoncustodio/i18n

Requires Node >= 14 (private class fields # support).

Basic Usage

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

const locales = {
    en: {
        greeting: 'Hello, {{name}}!',
        apples: { zero: 'No apples', one: 'One apple', other: '{{count}} apples' }
    },
    pt: {
        greeting: 'Olá, {{name}}!',
        apples: { zero: 'Sem maçãs', one: 'Uma maçã', other: '{{count}} maçãs' }
    }
};

const i18n = new I18n(locales, () => currentLocale);

let currentLocale = 'en';
console.log(i18n.t('greeting', { name: 'João' })); // Hello, João!
currentLocale = 'pt';
console.log(i18n.t('greeting', { name: 'João' })); // Olá, João!

Fallback

  • Locale not found: uses the default locale (third constructor parameter, defaults to 'en').
  • Message key not found: returns the key path itself ("missing.key.path").

Interpolation

Strings with {{variable}} are transformed into templates. If a variable is not provided, the original placeholder remains: {{variable}}.

Pluralization

Define an object with zero, one, and other keys:

apples: { zero: 'No apples', one: 'One apple', other: '{{count}} apples' }

Selection is based on options.count.

API

new I18n(locales: Record<string, any>, getLocale?: () => string | undefined, defaultLocale?: string)
  • locales: Locales object. Each locale contains nested messages.
  • getLocale: Function that returns the current locale (e.g., from AsyncLocalStorage or request context).
  • defaultLocale: Default locale when getLocale returns no value or locale doesn't exist.

Methods:

  • t(keyPath: string, options?: Record<string, string | number>): string – resolves and interpolates a message.

Getters:

  • locale: string – returns the current active locale.
  • locales: string[] – returns an array of available locale keys.

Internal Cache

Each compiled key for a locale is stored internally to avoid recompiling the message function on subsequent calls.

Typing

The index.d.ts file exposes utility types for safe nested key resolution (NestedKeyOf). In TypeScript you get autocomplete for key paths.

AsyncLocalStorage Example

const { AsyncLocalStorage } = require('node:async_hooks');
const storage = new AsyncLocalStorage();
const i18n = new I18n(locales, () => storage.getStore()?.locale);

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

With Fastify

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

const storage = new AsyncLocalStorage();

const i18n = new I18n(
    {
        en: { greeting: 'Hello, {{name}}!' },
        pt: { greeting: 'Olá, {{name}}!' },
        es: { greeting: '¡Hola, {{name}}!' },
    },
    () => storage.getStore()?.locale
);

const t = i18n.t.bind(i18n);

fastify.addHook('onRequest', (request, reply, done) => {
    const store = {
        locale: request.headers['content-language'] || 'en',
    };

    storage.run(store, done);
});

fastify.get('/greeting/:name', (request, reply) => {
    const message = t('greeting', { name: request.params.name });
    reply.send({ message, locale: i18n.locale, locales: i18n.locales });
});

fastify.listen({ port: 3000, host: '0.0.0.0' }, (err) => {
    if (err) {
        console.error(err);
        process.exit(1);
    }
    console.log('Server running on http://localhost:3000');
});

Testing the Fastify Example

# English (en)
curl -H "Content-Language: en" http://localhost:3000/greeting/Anderson

# Portuguese (pt)
curl -H "Content-Language: pt" http://localhost:3000/greeting/Anderson

# Spanish (es)
curl -H "Content-Language: es" http://localhost:3000/greeting/Anderson

# Without header (uses default: en)
curl http://localhost:3000/greeting/Anderson

Best Practices

  • Keep messages short and without extra logic (the library doesn't execute JS in strings, only replaces placeholders).
  • Centralize pluralizations at a single level to avoid complexity.
  • Avoid interpolating unsanitized user values if rendering directly to HTML.

License

MIT

About

Lightweight i18n library with interpolation and pluralization

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published