Skip to content

ilingo

A tiny, framework-agnostic translation library for TypeScript. Pluggable stores, BCP-47 fallback chains, ICU-lite plurals, Intl-powered formatters — all in a few kilobytes.

MIT licensed · Node 22+ · ESM-only · TypeScript-first

ilingo.get(ctx)

chain: en

cart.greetingWelcome, Peter!
cart.items3 items in your cart
cart.totalTotal: €49.90

One library. Six superpowers.

Every layer is replaceable, every contract is documented, every line is typed.

🪶

Tiny core

Two-dependency runtime, ESM-only, browser-safe. Ships in kilobytes, not megabytes.

🧩

Pluggable stores

A 3-method IStore port — in-memory by default, file-system adapter included, write your own in a few lines.

🌍

BCP-47 fallback

Locale-first resolution walks pt-BR → pt → en automatically. Override with a string, array, function, or opt out.

🔢

ICU-lite plurals

Intl.PluralRules-backed selection over CLDR categories. Explicit @plural marker keeps namespaces unambiguous.

🎨

Intl formatters

Inline {{value, number(...)}}, date, and list modifiers — all locale-aware, all memoised per instance.

🔒

Type-safe keys

defineCatalog() captures literal shapes; Ilingo<typeof catalog> refuses typos and requires count on plural keys.

From zero to first translation

Three steps. No decorators, no compiler plugins, no build-time codegen.

npm install ilingo

# Optional adapters
npm install @ilingo/fs        # load locales from disk
npm install @ilingo/vue       # Vue 3 plugin
npm install @ilingo/vuelidate # Vuelidate validator messages
@ilingo/vue

First-class Vue 3 integration

A drop-in plugin that wires provide / inject for the Ilingo instance and a reactive locale Ref — plus a useTranslation composable and an <ITranslate> component.

  • Reactive. Translations re-compute on locale / count / data changes.
  • Idempotent install. Call install() any number of times — it merges into an existing instance instead of clobbering it.
  • No boilerplate. One plugin, two composables, one component. The whole surface fits on a postcard.
Read the Vue guide →
CartHeader.vue
<script setup>
import { injectLocale, useTranslation } from '@ilingo/vue';

const locale = injectLocale();
const greeting = useTranslation({
    group: 'cart',
    key: 'greeting',
    data: { name: 'Paul' },
});
const items = useTranslation({
    group: 'cart',
    key: 'items',
    count: 3,
});
</script>

<template>
    <button @click="locale = 'de'">DE</button>
    <button @click="locale = 'en'">EN</button>

    <p>{{ greeting }}</p>
    <p>{{ items }}</p>

    <ITranslate path="cart.greeting" :data="{ name: 'Peter' }" />
</template>

Released under the MIT License.