@kapsula-chat/i18n
v1.0.0
Published
Lightweight chainable i18n for TypeScript with reactive plural forms and a Svelte component
Downloads
14
Maintainers
Readme
i18n
A lightweight, chainable i18n library for TypeScript. Translations live right next to the strings they describe — no external config files, no key lookups.
Installation
bun installUsage
Basic translation
Call .tr(lang, translation) on any string. Chain as many languages as you need. The result behaves exactly like a regular string.
import './i18n'
import { setLanguage } from './i18n'
const label = 'Save'.tr('ru', 'Сохранить').tr('de', 'Speichern')
setLanguage('en')
`${label}` // 'Save'
setLanguage('ru')
`${label}` // 'Сохранить'Plural forms
Pass an object of CLDR plural categories (one, few, many, other, etc.) and a count as the third argument. Plural selection is handled by the built-in Intl.PluralRules.
const msg = 'item'.tr('ru', { one: 'элемент', few: 'элемента', many: 'элементов' }, 3)
// → 'элемента'Reactive plural forms
Pass a function as the count to make plurals react to changing values:
let count = 1
const msg = 'item'.tr('ru', { one: 'элемент', few: 'элемента', many: 'элементов' }, () => count)
`${msg}` // 'элемент'
count = 5
`${msg}` // 'элементов'Reacting to language changes
Use onChange to subscribe to language switches:
const label = 'Save'.tr('ru', 'Сохранить')
const off = label.onChange(value => {
console.log('New value:', value)
})
setLanguage('ru') // logs: 'New value: Сохранить'
off() // unsubscribeSvelte component
For large text blocks or rich HTML, use the <Tr> component. It renders its content only when the current language matches lang. Reactively updates on language change.
<script>
import Tr from 'i18n/Tr.svelte'
import { setLanguage } from 'i18n'
</script>
<Tr lang="en">
<p>This is a <strong>large</strong> block of English text.</p>
</Tr>
<Tr lang="ru">
<p>Это <strong>большой</strong> блок русского текста.</p>
</Tr>When no lang is given, the block is always visible (useful as a fallback):
<Tr lang="ru">Привет!</Tr>
<Tr>Hello!</Tr> <!-- shown for all other languages -->API
setLanguage(lang: string)
Sets the active language. Accepts BCP 47 tags ('en', 'ru', 'zh-CN'); normalised to the base language code.
getLanguage(): string
Returns the current language code.
onLanguageChange(fn): () => void
Subscribes to language changes. Returns an unsubscribe function.
normalizeLanguage(lang): string
Normalises a language tag to a two-letter code, falling back to 'en'.
String.prototype.tr(lang, value, n?)
Extends any string with a translation. Returns a Translated instance that proxies all standard string methods.
| Parameter | Type | Description |
|-----------|------|-------------|
| lang | string | Language code |
| value | string \| PluralForms | Translation string or plural forms object |
| n | number \| (() => number) | Count for plural selection (optional) |
Translated
| Member | Description |
|--------|-------------|
| .tr(lang, value, n?) | Adds another language translation (immutable) |
| .onChange(callback) | Subscribes to value changes on language switch; returns unsubscribe function |
| .toString() | Returns the translation for the current language |
