🌍 A lightweight internationalization (i18n) module for browser and Node.js environments, with a size of only ~2KB!
- ✅ Zero dependencies, ultra-lightweight
- 📦 Supports nested access (e.g.,
settings.theme.light
) - 🔄 Supports string interpolation (
Hello, {name}
) - 🌐 Dynamic language switching
- ➕ Dynamic language addition
- ⚡ Internal caching mechanism for better performance
- 🧩 Built-in event system (e.g., listen to language changes)
Automatically generates language key path types. Built-in type inference support for IDE smart hints.
Using npm:
npm install mini-i18n
Using CDN:
<script src="https://cdn.jsdelivr.net/npm/mini-i18n"></script>
<!-- or -->
<script src="https://unpkg.com/mini-i18n"></script>
<script>
const i18n = new miniI18n.I18n({ .. })
</script>
import { I18n } from 'mini-i18n'
const languages = {
en: {
settings: {
title: 'Settings',
theme: { light: 'Light', dark: 'Dark' },
tags: ['a', 'b'],
},
greeting: 'Hello, {name}!',
},
zh: {
settings: {
title: '设置',
theme: { light: '浅色', dark: '深色' },
tags: ['甲', '乙'],
},
greeting: '你好, {name}!',
},
// 🔁 If you plan to add new languages later (e.g., 'jp'), you can define an empty object in advance to avoid TS errors
jp: {} // TIP: Define placeholder objects in advance
} as const // If using TypeScript, it's recommended to add `as const`
const i18n = new I18n({
defaultLanguage: 'en',
language: 'en',
languages,
})
// Get translations
i18n.t('settings.title') // => "Settings"
i18n.t('settings.tags.0') // => "a"
i18n.setLanguage('zh')
i18n.t('settings.title') // => "设置"
// Using interpolation
i18n.t('greeting', { params: { name: 'Lete' } }) // => "你好, Lete!"
// Listen to language changes
i18n.on('language:changed', (payload) => {
console.log('Language changed to:', payload.language)
})
i18n.on('language:added', (payload) => {})
// Cancel the listener
const unlistenMissingKey = i18n.on('missingKey', (payload) => {})
unlistenMissingKey()
Parameter | Type | Description |
---|---|---|
defaultLanguage |
keyof T |
The default language |
language |
keyof T |
The current language |
languages |
Record<string, object> |
The collection of language data |
interpolation (optional) |
{ prefix: string; suffix: string } |
Prefix and suffix for interpolation (default: {} ) |
Gets the translation content, supports nested access and interpolation.
i18n.t('settings.theme.light') // => "浅色"
i18n.t('greeting', { params: { name: 'World' } }) // => "你好, World!"
i18n.t('unknown.key', { defaultValue: 'Not found' }) // => "Not found"
Sets the specified language and clears the cache. Will trigger the language:changed
event.
Gets the current language.
Dynamically adds a new language package.
Clears the translation cache.
Listen for language change events.
i18n.on('language:changed', (payload) => {
console.log(`Language changed to: ${payload.language}`)
})
Listen for a language change only once.
i18n.once('language:changed', (payload) => {
console.log('One-time language switch:', payload.language)
})
Remove a previously registered event listener.
function fn() {}
i18n.on('language:changed', fn)
i18n.off('language:changed', fn)
Clear all or specific event listeners.
i18n.clear() // Clear all listeners
i18n.clear('language:changed') // Clear only 'change' listeners
You can also use the built-in event system separately:
import { EventEmitter } from 'mini-i18n'
const emitter = new EventEmitter()
const listener = () => console.log('triggered')
emitter.on('custom', listener)
emitter.emit('custom') // => triggered