|
7 | 7 |
|
8 | 8 |
|
9 | 9 | # sveltekit-i18n |
10 | | -`sveltekit-i18n` is a tiny library with no external dependencies, built for [Svelte](https://github.com/sveltejs/svelte) and [SvelteKit](https://github.com/sveltejs/kit). It glues [@sveltekit-i18n/base](https://github.com/sveltekit-i18n/base) and [@sveltekit-i18n/parser-default](https://github.com/sveltekit-i18n/parsers/tree/master/parser-default) together to provide you the most straightforward `sveltekit-i18n` solution. |
11 | 10 |
|
12 | | -## Key features |
| 11 | +A lightweight, powerful internationalization (i18n) library designed specifically for [SvelteKit](https://github.com/sveltejs/kit). This package combines [@sveltekit-i18n/base](https://github.com/sveltekit-i18n/base) with [@sveltekit-i18n/parser-default](https://github.com/sveltekit-i18n/parsers/tree/master/parser-default) to provide the quickest way to add multilingual support to your SvelteKit applications. |
13 | 12 |
|
14 | | -✅ SvelteKit ready\ |
15 | | -✅ SSR support\ |
16 | | -✅ Custom data sources – no matter if you are using local files or remote API to get your translations\ |
17 | | -✅ Module-based – your translations are loaded for visited pages only (and only once!)\ |
18 | | -✅ Component-scoped translations – you can create multiple instances with custom definitions\ |
19 | | -✅ Custom modifiers – you can modify the input data the way you really need\ |
20 | | -✅ TS support\ |
21 | | -✅ No external dependencies |
| 13 | +## Why sveltekit-i18n? |
22 | 14 |
|
23 | | -## Usage |
| 15 | +- 🚀 **SvelteKit-optimized** – Built specifically for SvelteKit with full SSR support |
| 16 | +- 📦 **Minimal dependencies** – Only ecosystem packages (base + parser-default) |
| 17 | +- ⚡ **Smart loading** – Translations load only for visited pages (lazy loading) |
| 18 | +- 🎯 **Route-based** – Automatic translation loading based on your routes |
| 19 | +- 🔧 **Flexible** – Support for custom data sources (local files, APIs, databases) |
| 20 | +- 🌐 **Multiple parsers** – Choose the syntax that fits your needs |
| 21 | +- 📝 **TypeScript** – Complete type definitions and typed API |
| 22 | +- 🎨 **Component-scoped** – Create multiple translation instances for different parts of your app |
| 23 | + |
| 24 | +## Installation |
| 25 | + |
| 26 | +```bash |
| 27 | +npm install sveltekit-i18n |
| 28 | +``` |
| 29 | + |
| 30 | +## Quick Start |
| 31 | + |
| 32 | +### 1. Create your translation files |
| 33 | + |
| 34 | +```json |
| 35 | +// src/lib/translations/en/common.json |
| 36 | +{ |
| 37 | + "greeting": "Hello, {{name}}!", |
| 38 | + "nav.home": "Home", |
| 39 | + "nav.about": "About" |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +```json |
| 44 | +// src/lib/translations/cs/common.json |
| 45 | +{ |
| 46 | + "greeting": "Ahoj, {{name}}!", |
| 47 | + "nav.home": "Domů", |
| 48 | + "nav.about": "O nás" |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +### 2. Setup i18n configuration |
24 | 53 |
|
25 | | -Setup `translations.js` in your lib folder... |
26 | 54 | ```javascript |
| 55 | +// src/lib/translations/index.js |
27 | 56 | import i18n from 'sveltekit-i18n'; |
28 | 57 |
|
29 | 58 | /** @type {import('sveltekit-i18n').Config} */ |
30 | | -const config = ({ |
| 59 | +const config = { |
31 | 60 | loaders: [ |
32 | 61 | { |
33 | 62 | locale: 'en', |
34 | 63 | key: 'common', |
35 | | - loader: async () => ( |
36 | | - await import('./en/common.json') |
37 | | - ).default, |
38 | | - }, |
39 | | - { |
40 | | - locale: 'en', |
41 | | - key: 'home', |
42 | | - routes: ['/'], // you can use regexes as well! |
43 | | - loader: async () => ( |
44 | | - await import('./en/home.json') |
45 | | - ).default, |
46 | | - }, |
47 | | - { |
48 | | - locale: 'en', |
49 | | - key: 'about', |
50 | | - routes: ['/about'], |
51 | | - loader: async () => ( |
52 | | - await import('./en/about.json') |
53 | | - ).default, |
| 64 | + loader: async () => (await import('./en/common.json')).default, |
54 | 65 | }, |
55 | 66 | { |
56 | 67 | locale: 'cs', |
57 | 68 | key: 'common', |
58 | | - loader: async () => ( |
59 | | - await import('./cs/common.json') |
60 | | - ).default, |
61 | | - }, |
62 | | - { |
63 | | - locale: 'cs', |
64 | | - key: 'home', |
65 | | - routes: ['/'], |
66 | | - loader: async () => ( |
67 | | - await import('./cs/home.json') |
68 | | - ).default, |
69 | | - }, |
70 | | - { |
71 | | - locale: 'cs', |
72 | | - key: 'about', |
73 | | - routes: ['/about'], |
74 | | - loader: async () => ( |
75 | | - await import('./cs/about.json') |
76 | | - ).default, |
| 69 | + loader: async () => (await import('./cs/common.json')).default, |
77 | 70 | }, |
78 | 71 | ], |
79 | | -}); |
| 72 | +}; |
80 | 73 |
|
81 | 74 | export const { t, locale, locales, loading, loadTranslations } = new i18n(config); |
82 | 75 | ``` |
83 | 76 |
|
84 | | -...load your translations in `+layout.js`... |
| 77 | +### 3. Load translations in your layout |
85 | 78 |
|
86 | 79 | ```javascript |
| 80 | +// src/routes/+layout.js |
87 | 81 | import { loadTranslations } from '$lib/translations'; |
88 | 82 |
|
89 | | -/** @type {import('@sveltejs/kit').Load} */ |
| 83 | +/** @type {import('./$types').LayoutLoad} */ |
90 | 84 | export const load = async ({ url }) => { |
91 | 85 | const { pathname } = url; |
| 86 | + |
| 87 | + const initLocale = 'en'; // determine from cookie, user preference, etc. |
| 88 | + |
| 89 | + await loadTranslations(initLocale, pathname); |
| 90 | + |
| 91 | + return {}; |
| 92 | +}; |
| 93 | +``` |
92 | 94 |
|
93 | | - const initLocale = 'en'; // get from cookie, user session, ... |
| 95 | +### 4. Use translations in your components |
94 | 96 |
|
95 | | - await loadTranslations(initLocale, pathname); // keep this just before the `return` |
| 97 | +```svelte |
| 98 | +<!-- src/routes/+page.svelte --> |
| 99 | +<script> |
| 100 | + import { t } from '$lib/translations'; |
| 101 | +</script> |
96 | 102 |
|
97 | | - return {}; |
98 | | -} |
| 103 | +<h1>{$t('greeting', { name: 'World' })}</h1> |
| 104 | +
|
| 105 | +<nav> |
| 106 | + <a href="/">{$t('nav.home')}</a> |
| 107 | + <a href="/about">{$t('nav.about')}</a> |
| 108 | +</nav> |
| 109 | +``` |
| 110 | + |
| 111 | +## Key Features |
| 112 | + |
| 113 | +### Route-based Loading |
| 114 | + |
| 115 | +Load translations only for specific routes to optimize performance: |
| 116 | + |
| 117 | +```javascript |
| 118 | +const config = { |
| 119 | + loaders: [ |
| 120 | + { |
| 121 | + locale: 'en', |
| 122 | + key: 'home', |
| 123 | + routes: ['/'], // Load only on homepage |
| 124 | + loader: async () => (await import('./en/home.json')).default, |
| 125 | + }, |
| 126 | + { |
| 127 | + locale: 'en', |
| 128 | + key: 'about', |
| 129 | + routes: ['/about'], // Load only on about page |
| 130 | + loader: async () => (await import('./en/about.json')).default, |
| 131 | + }, |
| 132 | + ], |
| 133 | +}; |
99 | 134 | ``` |
100 | 135 |
|
101 | | -...and include your translations within pages and components. |
| 136 | +### Placeholders and Modifiers |
| 137 | + |
| 138 | +Use dynamic values in your translations: |
| 139 | + |
| 140 | +```json |
| 141 | +{ |
| 142 | + "welcome": "Welcome, {{name}}!", |
| 143 | + "items": "You have {{count:number;}} {{count; 1:item; default:items;}}." |
| 144 | +} |
| 145 | +``` |
102 | 146 |
|
103 | 147 | ```svelte |
104 | 148 | <script> |
105 | 149 | import { t } from '$lib/translations'; |
106 | | -
|
107 | | - const pageName = 'This page is Home page!'; |
108 | 150 | </script> |
109 | 151 |
|
110 | | -<div> |
111 | | - <!-- you can use `placeholders` and `modifiers` in your definitions (see docs) --> |
112 | | - <h2>{$t('common.page', { pageName })}</h2> |
113 | | - <p>{$t('home.content')}</p> |
114 | | -</div> |
| 152 | +<p>{$t('welcome', { name: 'Alice' })}</p> |
| 153 | +<p>{$t('items', { count: 5 })}</p> |
| 154 | +``` |
| 155 | + |
| 156 | +## Documentation |
| 157 | + |
| 158 | +**📖 [Complete Documentation Index](./docs/INDEX.md)** – Find everything in one place |
| 159 | + |
| 160 | +### Quick Links |
| 161 | + |
| 162 | +- 🚀 [Getting Started Guide](./docs/GETTING_STARTED.md) – 15-minute tutorial |
| 163 | +- 🏗️ [Architecture Overview](./docs/ARCHITECTURE.md) – How everything works |
| 164 | +- 📚 [API Documentation](./docs/README.md) – Complete reference |
| 165 | +- ✨ [Best Practices](./docs/BEST_PRACTICES.md) – Production-ready patterns |
| 166 | +- 🔧 [Troubleshooting](./docs/TROUBLESHOOTING.md) – Common issues & FAQ |
| 167 | + |
| 168 | +## Examples |
| 169 | + |
| 170 | +Explore working examples for different use cases: |
| 171 | + |
| 172 | +- [Multi-page app](./examples/multi-page) – Most common setup |
| 173 | +- [Locale-based routing](./examples/locale-router) – SEO-friendly URLs (e.g., `/en/about`) |
| 174 | +- [Component-scoped translations](./examples/component-scoped-ssr) – Isolated translation contexts |
| 175 | +- [Custom parsers](./examples/parser-icu) – Using ICU message format |
| 176 | +- [All examples](./examples) – Complete list of examples |
| 177 | + |
| 178 | +## Advanced Usage |
| 179 | + |
| 180 | +### Need a different parser? |
| 181 | + |
| 182 | +This library uses `@sveltekit-i18n/parser-default`. If you need ICU message format or want to create your own parser, use [@sveltekit-i18n/base](https://github.com/sveltekit-i18n/base) directly: |
| 183 | + |
| 184 | +```javascript |
| 185 | +import i18n from '@sveltekit-i18n/base'; |
| 186 | +import parser from '@sveltekit-i18n/parser-icu'; |
| 187 | + |
| 188 | +const config = { |
| 189 | + parser: parser(), |
| 190 | + // ... rest of config |
| 191 | +}; |
115 | 192 | ``` |
116 | 193 |
|
117 | | -## More info |
118 | | -[Docs](https://github.com/sveltekit-i18n/lib/tree/master/docs/README.md)\ |
119 | | -[Examples](https://github.com/sveltekit-i18n/lib/tree/master/examples)\ |
120 | | -[Changelog](https://github.com/sveltekit-i18n/lib/releases) |
| 194 | +Learn more about [parsers](https://github.com/sveltekit-i18n/parsers). |
| 195 | + |
| 196 | +## TypeScript Support |
| 197 | + |
| 198 | +Full TypeScript support with complete type definitions for configuration and API: |
| 199 | + |
| 200 | +```typescript |
| 201 | +import i18n, { type Config } from 'sveltekit-i18n'; |
| 202 | + |
| 203 | +const config: Config = { |
| 204 | + loaders: [ |
| 205 | + // ... your loaders |
| 206 | + ], |
| 207 | +}; |
| 208 | + |
| 209 | +export const { t, locale, locales, loading, loadTranslations } = new i18n(config); |
| 210 | +``` |
| 211 | + |
| 212 | +**Note:** The library provides type definitions but does not automatically infer translation keys from your JSON files. You can create custom type-safe wrappers if needed (see [Best Practices](./docs/BEST_PRACTICES.md#typescript-patterns)). |
| 213 | + |
| 214 | +## Contributing |
| 215 | + |
| 216 | +We welcome contributions! Please read our [Contributing Guide](./CONTRIBUTING.md) for details on: |
| 217 | + |
| 218 | +- Development setup and workflow |
| 219 | +- Git workflow (rebase-based, linear history) |
| 220 | +- Commit guidelines (atomic commits) |
| 221 | +- Pull request process |
| 222 | +- Code standards and testing |
| 223 | + |
| 224 | +**Note:** We're currently looking for maintainers. If you're interested in helping maintain this project, please reach out via [this issue](https://github.com/sveltekit-i18n/lib/issues/197). |
| 225 | + |
| 226 | +## Changelog |
| 227 | + |
| 228 | +See [Releases](https://github.com/sveltekit-i18n/lib/releases) for version history. |
| 229 | + |
| 230 | +## Related Packages |
| 231 | + |
| 232 | +- [@sveltekit-i18n/base](https://github.com/sveltekit-i18n/base) – Core functionality with custom parser support |
| 233 | +- [@sveltekit-i18n/parser-default](https://github.com/sveltekit-i18n/parsers/tree/master/parser-default) – Default message parser |
| 234 | +- [@sveltekit-i18n/parser-icu](https://github.com/sveltekit-i18n/parsers/tree/master/parser-icu) – ICU message format parser |
| 235 | + |
| 236 | +## License |
| 237 | + |
| 238 | +MIT |
0 commit comments