Svelte Integration

Learn how to integrate i18next with Svelte applications for internationalization.

Integrate i18next with your Svelte application to support multiple languages using Lengrise-managed translations.

Prerequisites

  • Svelte project (v3.0.0+ or SvelteKit)
  • Node.js (v16.0.0+)
  • Package manager (npm, yarn, or pnpm)
  • Translations downloaded from Lengrise

Pull Translation Files

First, you must pull your translation files from Lengrise API. These files will contain all the translated text for your application.

  1. Go to the Installation Guide and follow the steps to download your translations
  2. Place the downloaded JSON files in your project as shown in the project structure below
  3. Ensure that each language has its own JSON file named with the language code (e.g., en.json, es.json)

Integration Setup

After downloading your translation files, install the necessary packages:

npm install i18next i18next-browser-languagedetector i18next-http-backend --save

Project Structure

For a typical Svelte project, you'll want to organize your files like this:

package.jsonadd
svelte.config.jsadd
srcadd
App.svelteadd
main.jsadd
i18n.jsadd
componentsadd
LanguageSwitcher.svelteadd
routesadd
+page.svelteadd
staticadd
localesadd
en.jsonadd
es.jsonadd

For SvelteKit, place the locales folder in static/locales so it's served as a static asset.

Configuration Steps

1. Create i18next Configuration

Create a file called src/i18n.js to initialize i18next:

import { writable, derived } from "svelte/store";
import i18next from "i18next";
import { browser } from "$app/environment"; // For SvelteKit
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-http-backend";

// Create a writable store with the active language
export const locale = writable("en");

// Create a derived store with the translations
export const locales = {
  en: "English",
  es: "Español",
};

// Initialize i18next
export const i18n = i18next
  // Load translations using http backend
  .use(Backend)
  // Detect user language
  .use(LanguageDetector)
  // Initialize with configuration
  .init({
    // If you're using SvelteKit, check for browser environment
    ...(browser
      ? {
          backend: {
            loadPath: "/locales/{{lng}}.json",
          },
        }
      : {}),

    // Default language
    fallbackLng: "en",
    // Supported languages
    supportedLngs: ["en", "es"],
    // Debug mode in development
    debug: import.meta.env.DEV,

    // Interpolation configuration
    interpolation: {
      escapeValue: false, // Not needed for Svelte as it handles escaping
    },
  });

// Create a derived store with a translate function
export const t = derived(locale, ($locale) => (key, params) => {
  if (!i18next.isInitialized) {
    return "";
  }
  return i18next.t(key, { ...params, lng: $locale });
});

// Function to change the language
export function changeLanguage(newLocale) {
  if (Object.keys(locales).includes(newLocale)) {
    locale.set(newLocale);
    i18next.changeLanguage(newLocale);
  }
}

// Initialize locale from i18next
i18next.on("initialized", () => {
  locale.set(i18next.language);
});

// Update locale when language changes
i18next.on("languageChanged", (lng) => {
  locale.set(lng);
});

2. Create a Language Switcher Component

Create a file called src/components/LanguageSwitcher.svelte:

<script>
  import { locale, locales, changeLanguage } from '../i18n.js';
</script>

<div class="language-switcher">
  {#each Object.entries(locales) as [code, name]}
    <button
      class:active={$locale === code}
      on:click={() => changeLanguage(code)}
    >
      {name}
    </button>
  {/each}
</div>

<style>
  .language-switcher {
    display: flex;
    gap: 0.5rem;
  }

  button {
    padding: 0.3rem 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
  }

  button.active {
    background: #4a4a4a;
    color: white;
    border-color: #4a4a4a;
  }
</style>

3. Update Your Main App Component

Update your src/App.svelte or SvelteKit layout file:

<script>
  import { onMount } from 'svelte';
  import { t, i18n, locale } from './i18n.js';
  import LanguageSwitcher from './components/LanguageSwitcher.svelte';

  // Check if i18next is initialized
  let initialized = false;

  onMount(() => {
    // Wait for i18next to initialize
    i18n.then(() => {
      initialized = true;
    });
  });
</script>

{#if initialized}
  <header>
    <h1>{$t('welcome.title')}</h1>
    <LanguageSwitcher />
  </header>

  <main>
    <p>{$t('welcome.description')}</p>

    <section>
      <h2>{$t('features.title')}</h2>
      <ul>
        <li>{$t('features.easy')}</li>
        <li>{$t('features.fast')}</li>
        <li>{$t('features.flexible')}</li>
      </ul>
    </section>

    <!-- Example with parameters -->
    <p>{$t('greeting', { name: 'Svelte Developer' })}</p>
  </main>
{:else}
  <div>Loading translations...</div>
{/if}

<style>
  header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 2rem;
  }

  main {
    padding: 1rem;
  }
</style>

Using Translations

Basic Usage in Components

Use the t store to access translations in your Svelte components:

<script>
  import { t } from '../i18n.js';
</script>

<div>
  <h1>{$t('page.title')}</h1>
  <p>{$t('page.description')}</p>
</div>

Translations with Parameters

Pass parameters to your translations:

<script>
  import { t } from '../i18n.js';
  let username = 'John';
  let unreadCount = 5;
</script>

<div>
  <p>{$t('welcome.user', { name: username })}</p>
  <p>{$t('messages.unread', { count: unreadCount })}</p>
</div>

Create a Translation Component

For reusable translations, you can create a Translation component:

<!-- src/components/Trans.svelte -->
<script>
  import { t } from '../i18n.js';

  export let key = '';
  export let params = {};
</script>

<span>{$t(key, params)}</span>

Then use it in your components:

<script>
  import Trans from './components/Trans.svelte';
</script>

<div>
  <h1><Trans key="page.title" /></h1>
  <p><Trans key="welcome.user" params={{ name: 'Sarah' }} /></p>
</div>

Working with Pluralization

Your translation files in static/locales/en.json:

{
  "welcome": {
    "title": "Welcome to our app",
    "description": "This is a multilingual Svelte application"
  },
  "features": {
    "title": "Features",
    "easy": "Easy to use",
    "fast": "Fast translation",
    "flexible": "Flexible integration"
  },
  "greeting": "Hello, {{name}}!",
  "items": "{{count}} item",
  "items_plural": "{{count}} items",
  "messages": {
    "unread": "You have {{count}} unread message",
    "unread_plural": "You have {{count}} unread messages"
  }
}

And static/locales/es.json:

{
  "welcome": {
    "title": "Bienvenido a nuestra aplicación",
    "description": "Esta es una aplicación Svelte multilingüe"
  },
  "features": {
    "title": "Características",
    "easy": "Fácil de usar",
    "fast": "Traducción rápida",
    "flexible": "Integración flexible"
  },
  "greeting": "¡Hola, {{name}}!",
  "items": "{{count}} artículo",
  "items_plural": "{{count}} artículos",
  "messages": {
    "unread": "Tienes {{count}} mensaje sin leer",
    "unread_plural": "Tienes {{count}} mensajes sin leer"
  }
}

SvelteKit Integration

If you're using SvelteKit, you can initialize i18next in a layout file or hooks:

Update your hooks.server.js (Optional)

For server-side language detection in SvelteKit:

// src/hooks.server.js
import i18next from "i18next";
import Backend from "i18next-fs-backend";
import { locale } from "$lib/i18n";

// Initialize i18next on the server
i18next.use(Backend).init({
  // Server-side loading of translations
  backend: {
    loadPath: "static/locales/{{lng}}.json",
  },
  // Default language
  fallbackLng: "en",
  // Supported languages
  supportedLngs: ["en", "es"],
  // Interpolation
  interpolation: {
    escapeValue: false,
  },
});

export async function handle({ event, resolve }) {
  // Get preferred language from cookies or headers
  const lang =
    event.cookies.get("i18next") ||
    event.request.headers.get("accept-language")?.split(",")[0] ||
    "en";

  // Set language for this request
  event.locals.lang = lang;

  // Add translation function to locals
  event.locals.t = (key, params) => i18next.t(key, { lng: lang, ...params });

  return resolve(event);
}

Resources

For more detailed information, check out these resources: