Quick Answer
To add internationalization (i18n) to Svelte, use svelte-i18n. Install with npm install svelte-i18n, create your dictionary files, initialize the library in your layout, and use the $t store to display translated text. For SvelteKit, ensure you handle the initialization on both server and client side to prevent hydration mismatches.
Introduction to Svelte Internationalization
Svelte's reactive nature makes it excellent for building multilingual applications. However, handling routing, state, and translation loading in SvelteKit requires a solid strategy. This guide covers how to implement robust i18n in Svelte applications in 2026.
Why Svelte Developers Need i18n?
- Global Reach: Apps built with Svelte are often performant and ideal for mobile web, where global audiences are growing.
- Accessibility: Native language support is a key part of web accessibility.
- SvelteKit Routing: Leveraging SvelteKit's file-system routing for localized URLs (e.g.,
/en/about,/fr/about) boosts SEO.
Choosing an i18n Library for Svelte
While there are several options, svelte-i18n remains the community standard due to its simplicity and usage of Svelte stores.
svelte-i18n
- Pros: Built on Svelte stores, lightweight, supports lazy loading.
- Cons: Requires manual setup for SvelteKit SSR.
typesafe-i18n / inlang
- Pros: Full type safety, zero-runtime overhead (compiles away).
- Cons: Stricter setup, steeper learning curve.
For this guide, we will focus on svelte-i18n as it provides the most "Svelte-like" developer experience.
Step-by-Step Implementation
Step 1: Install Dependencies
Terminalnpm install svelte-i18n
Step 2: Create Translation Files
Organize your translations in JSON files. Best practice is to split them by locale.
JSON1// src/locales/en.json 2{ 3 "greeting": "Hello, world!", 4 "nav": { 5 "home": "Home", 6 "about": "About" 7 } 8}
JSON1// src/locales/es.json 2{ 3 "greeting": "¡Hola, mundo!", 4 "nav": { 5 "home": "Inicio", 6 "about": "Sobre nosotros" 7 } 8}
Step 3: Configure i18n
Create an initialization file to register your loaders and set the default language.
JavaScript1// src/lib/i18n.js 2import { register, init, getLocaleFromNavigator } from 'svelte-i18n'; 3 4register('en', () => import('../locales/en.json')); 5register('es', () => import('../locales/es.json')); 6 7init({ 8 fallbackLocale: 'en', 9 initialLocale: getLocaleFromNavigator(), 10});
Note: In SvelteKit, you might want to determine initialLocale from the URL or cookies rather than navigator during SSR.
Step 4: Use Translations in Components
Use the t store provided by svelte-i18n.
SVELTE1<script> 2 import { t } from 'svelte-i18n'; 3</script> 4 5<h1>{$t('greeting')}</h1> 6 7<nav> 8 <a href="/">{$t('nav.home')}</a> 9 <a href="/about">{$t('nav.about')}</a> 10</nav>
Advanced Features
Handling Pluralization
svelte-i18n uses ICU message format for powerful pluralization support.
JSON{ "messages": "{count, plural, one {You have # message} other {You have # messages}}" }
SVELTE<p>{$t('messages', { values: { count: 5 } })}</p>
Date and Number Formatting
SVELTE1<script> 2 import { date, number } from 'svelte-i18n'; 3 const now = new Date(); 4</script> 5 6<p>Today is {$date(now, { format: 'long' })}</p> 7<p>Cost: {$number(1234.56, { style: 'currency', currency: 'USD' })}</p>
Lazy Loading Translations
For large apps, you don't want to bundle all languages. register() supports dynamic imports, which SvelteKit automatically handles as chunks.
JavaScriptregister('de', () => import('../locales/de.json'));
This ensures German translations are only loaded when the user switches to German.
Managing Translations at Scale with IntlPull
As your Svelte app grows, managing multiple JSON files becomes messy. Keys get out of sync, and translators struggle with raw JSON.
IntlPull integrates directly with your workflow:
- Extract: Automatically find new keys in your
.sveltefiles. - Upload: Push keys to IntlPull.
- Translate: Use AI or human translators in the dashboard.
- Sync: Pull updated JSON files back to your project.
Terminal# Example workflow npx @intlpullhq/cli push src/locales/en.json npx @intlpullhq/cli pull --languages es,fr,de
Frequently Asked Questions
Q: How do I handle SEO with Svelte i18n?
Answer: For SEO, use SvelteKit's parameterized routes (e.g., [lang]/about). This creates unique URLs for each language. Ensure you set the <html lang="en"> attribute dynamically in app.html or +layout.svelte based on the current route.
Q: Can I use typesafe-i18n with SvelteKit?
Answer: Yes, typesafe-i18n is an excellent choice if you rely heavily on TypeScript. It generates TypeScript definitions for your keys, preventing typos and missing translations at build time.
Q: Does svelte-i18n work with SSR?
Answer: Yes, but you must ensure init() is called during the server request handle hook or inside the root +layout.server.js / +layout.js to set the locale correctly before rendering HTML.
Q: How do I persist the user's language preference?
Answer: Store the preference in a cookie or localStorage. In SvelteKit, read the cookie in hooks.server.js to set the locale for the initial server render, ensuring no hydration mismatch occurs.
Conclusion
Svelte's simplicity extends to its internationalization ecosystem. By combining svelte-i18n for runtime translation and IntlPull for management, you can build truly global Svelte applications with minimal friction.
Ready to scale your Svelte app? Try IntlPull for free and automate your translation workflow today.
