svelte-i18n
Lightweight i18n library for Svelte 5, inspired by vue-i18n, providing a complete internationalization solution.
Features
- Create i18n instances via createI18n with flexible configuration
- Reactive translation function t(), supports nested keys and namespaces
- String interpolation with {name} placeholders
- Pluralization with custom pluralization rules
- Fallback locale: auto fallback when translation is missing
- Dynamic loading / merging of language messages
- Automatic browser language detection
- localStorage persistence
- Full TypeScript type definitions
- Compatible with CommonJS and ES Modules
Installation
npm Install
# npm
npm install @free-walk/svelte-i18n
# cnpm(国内镜像)
cnpm install @free-walk/svelte-i18n
# yarn
yarn add @free-walk/svelte-i18n
# pnpm
pnpm add @free-walk/svelte-i18n Peer Dependencies
Make sure the following dependencies are installed:
npm install svelte ES Module Import
import { createI18n } from '@free-walk/svelte-i18n' CommonJS Require
const { createI18n } = require('@free-walk/svelte-i18n') CDN Usage
You can also use it directly via CDN (for quick prototyping or online demos):
<script src="https://unpkg.com/@free-walk/svelte-i18n@1.2.0/dist/svelte-i18n.iife.js"></script>
<script>
// 全局变量 SvelteI18n
const i18n = SvelteI18n.createI18n({ locale: 'zh', messages: { ... } })
</script>Quick Start
import { createI18n } from '@free-walk/svelte-i18n'
const i18n = createI18n({
locale: 'zh',
fallbackLocale: 'en',
messages: {
zh: {
greeting: '你好 {name}',
nav: { home: '首页', about: '关于' },
},
en: {
greeting: 'Hello {name}',
nav: { home: 'Home', about: 'About' },
},
},
})
// 在 Svelte 组件中使用
const { t, locale } = i18n <!-- App.svelte -->
<script>
import { i18n } from './i18n'
const { t, locale, setLocale } = i18n
</script>
<h1>{$t('greeting', { name: 'World' })}</h1>
<p>{$t('nav.home')}</p>
<button onclick={() => setLocale($locale === 'zh' ? 'en' : 'zh')}>
Switch Language
</button>createI18n
Factory function to create an i18n instance, returning a complete internationalization toolkit.
Function Signature
function createI18n(options: I18nOptions): I18nInstanceConfiguration
| Property | Type | Required | Description |
|---|---|---|---|
locale | string | Yes | Current locale identifier (required) |
fallbackLocale | string | No | Fallback locale, used when translation is missing |
messages | LocaleMessages | No | Multi-locale messages mapping object |
pluralizationRules | PluralizationRules | No | Custom pluralization rules mapping |
persist | boolean | No | Whether to persist to localStorage |
persistKey | string | No | localStorage storage key name |
detectBrowserLocale | boolean | No | Whether to auto-detect browser language |
availableLocales | string[] | No | Available locales list (for browser detection matching) |
Translation
Translation function (derived store, reactive)
// 基础翻译
$t('greeting')
// 嵌套键
$t('nav.home')
// 带插值
$t('greeting', { name: 'World' })
// 命令式翻译(非响应式)
i18n.translate('greeting', { name: 'World' })Interpolation
Use {name} placeholders for string interpolation.
// 语言消息
messages: {
zh: { welcome: '欢迎 {name},你有 {count} 条消息' },
en: { welcome: 'Welcome {name}, you have {count} messages' },
}
// 使用
$t('welcome', { name: '张三', count: 5 })
// => '欢迎 张三,你有 5 条消息'Pluralization
Use | to separate plural forms, pass a number to auto-select.
Message format: zero | singular | plural
// 语言消息
messages: {
en: {
apple: 'no apple | one apple | {count} apples',
car: 'no cars | {count} car | {count} cars',
},
}
// 使用:传入数字作为第二个参数
$t('apple', 0) // => 'no apple'
$t('apple', 1) // => 'one apple'
$t('apple', 5) // => '5 apples' Custom Pluralization Rules
const i18n = createI18n({
locale: 'ru',
messages: { ru: { ... } },
pluralizationRules: {
ru: (choice, choicesLength) => {
if (choice === 0) return 0
const teen = choice > 10 && choice < 20
const lastDigit = choice % 10
if (lastDigit === 1 && !teen) return 1
if (lastDigit >= 2 && lastDigit <= 4 && !teen) return 2
return choicesLength < 4 ? 2 : 3
},
},
})Dynamic Loading
Supports dynamic loading or merging of language messages at runtime.
loadMessages: overwrite loading
// 覆盖式加载
i18n.loadMessages('ja', {
greeting: 'こんにちは {name}',
})
i18n.setLocale('ja') mergeMessages: incremental merge
// 增量合并(不覆盖已有键)
i18n.mergeMessages('zh', {
newModule: {
title: '新模块',
desc: '描述',
},
})API Reference
| Property / Method | Type | Description |
|---|---|---|
locale | Writable<string> | Current locale (writable store, reactive) |
t | Readable<(key, params?) => string> | Translation function (derived store, reactive) |
translate(key, params?) | (key, params?) => string | Imperative translation (non-reactive, reads current value) |
setLocale(locale) | (string) => void | Switch locale |
getLocale() | () => string | Get current locale |
loadMessages(locale, messages) | (string, Messages) => void | Dynamically load messages (overwrites existing) |
mergeMessages(locale, messages) | (string, Messages) => void | Merge messages (does not overwrite existing keys) |
availableLocales() | () => string[] | Get all registered locales |
hasKey(key, locale?) | (string, string?) => boolean | Check if a key has a translation |
createSimpleI18n
Simplified factory function, only needs default locale and messages, auto-infers fallback locale.
import { createSimpleI18n } from '@free-walk/svelte-i18n'
const { t, locale, toggle } = createSimpleI18n('zh', {
zh: {
hello: '你好',
nav: { home: '首页' },
},
en: {
hello: 'Hello',
nav: { home: 'Home' },
},
})
// toggle() — Cycle through available locales | Method | Description |
|---|---|
toggle() | Cycle through available locales |