svelte-i18next

Svelte I18next

Add support to a svelte kit project to use i18next

Svelte.i18next

Table of Contents

Introduction

Svelte.i18next is a library that makes it easy to add internationalization (i18n) support to your SvelteKit. It provides a simple interface for configuring i18next and managing translations.

Installation

To install Svelte.i18next, simply run:

pnpm install @maximux13/svelte-i18next i18next i18next-browser-languagedetector i18next-http-backend

Configuration

To set up Svelte.i18next in your project, you'll need to go through the following configuration steps:

i18n Config File

Step 1: Create an i18n Configuration File

Create a file named src/i18n.ts and populate it with the i18n configuration. Here is an example:

export default {
  supportedLngs: ['en', 'es'], // Supported languages
  fallbackLng: 'en', // Fallback language
  defaultNS: 'common' // Default namespace
};

Locale Files

Step 2: Create Locale Files

Create locale JSON files inside the static/locales/{lng}/{ns}.json directory. Replace {lng} with the language code (e.g., en, es) and {ns} with the namespace (e.g., common).

Example content for static/locales/en/common.json:

{
  "title": "Svelte i18next - Hello {{name}}!",
  "world": "World"
}

Server Initialization

Step 3: Initialize SvelteI18next Instance

In your src/i18n.server.ts, initialize a new SvelteI18next instance as shown below:

// src/i18n.server.ts
import Backend from 'i18next-http-backend';
import { SvelteI18next } from '@maximux13/svelte-i18next';
import i18n from './i18n';

const i18next = new SvelteI18next({
  i18next: {
    ...i18n,
    backend: { loadPath: '/locales/{{lng}}/{{ns}}.json' }
  },
  backend: Backend
});

export default i18next;

Add Server Hook

Step 4: Add Server Hook

Create a server hook to initialize i18next in src/hook.server.ts:

import type { Handle } from '@sveltejs/kit';
import { createInstance } from 'i18next';
import Backend from 'i18next-http-backend';

import i18n from './i18n';
import i18next from './i18n.server';

import { createFetchRequest } from '@maximux13/svelte-i18next';

export const handle: Handle = async (props) => {
  const { event, resolve } = props;

  const instance = createInstance();
  const lng = await i18next.getLocale(event);
  const ns = await i18next.getNamespaces(event);
  const request = createFetchRequest(event.fetch);

  await instance
    .use(Backend)
    .init({ ...i18n, backend: { loadPath: '/locales/{{lng}}/{{ns}}.json', request }, lng, ns });

  const initOptions = i18next.getInitOptions(instance);

  event.locals.i18n = Object.assign(instance, { initOptions });

  return resolve(event, {
    transformPageChunk: ({ html }) => html.replace('<html lang="en">', `<html lang="${lng}">`)
  });
};

Client Initialization

Step 5: Client Instance Setup

Finally, set up a client instance to expose i18next functionalities in your code. For example, in src/routes/+layout.server.ts and src/routes/+layout.ts:

src/routes/+layout.server.ts

import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ locals, depends }) => {
  depends('i18n:lng');

  return { i18n: locals.i18n.initOptions };
};

src/routes/+layout.ts

import type { LayoutLoad } from './$types';

import i18next from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';

import { createStore } from '@maximux13/svelte-i18next';

export const load: LayoutLoad = async ({ data }) => {
  i18next
    .use(Backend)
    .use(LanguageDetector)
    .init({
      ...data.i18n,
      detection: { caches: ['cookie'], order: ['htmlTag'] }
    });

  const store = createStore(i18next);

  return { i18n: store };
};

Usage

Once you've completed the Configuration steps, you can start using Svelte.i18next in your Svelte components and server-side code.

In Svelte Components

You can use the i18n store in your Svelte components to access translations. Here's an example:

<script lang="ts">
  export let data;

  $: ({ i18n } = data);
</script>

<h1>{$i18n.t('title', { name: $i18n.t('world') })}</h1>

In Svelte Server Code

You can also use i18n functionalities in your server-side code. For instance:

// Example in a server-side Svelte file
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ locals, depends }) => {
  depends('i18n:lng');

  return { world: locals.i18n.t('world') };
};

Note: We use depends('i18n:lng'); to invalidate the data when the language changes. This invalidation is triggered by the i18n store when calling $i18n.changeLanguage method.

Advanced Features

Managing Namespaces

To manage namespaces, specify which namespaces should be loaded on each page by setting the ns property in your page or layout configuration. For example:

// src/routes/page.(server).ts
export const config = {
  ns: ['page']
};

This will load the page namespace for the corresponding page. You can also use an array to load multiple namespaces:

export const config = {
  ns: ['page', 'otherNamespace']
};

getFixedT

The getFixedT function allows you to use a fixed translation function in your server-side code. Example:

// Inside a server-side Svelte file
export function GET(event) {
  const t = i18next.getFixedT(event, { locale: 'en', namespaces: 'test', options: {} });
  return new Response(t('title'));
}

Trans Component

The Trans component provides a convenient way to include complex translations with HTML tags and Svelte components.

Props

Prop Type Description
i18n i18n i18n store instance (required if not wrapped in provider)
t i18n.t Custom translation function
tOptions object Options to pass to the translation function
key string Translation key
values object Values for interpolation
count number Count for pluralization
context string Context for pluralization
ns string Namespace
defaultValue string Default value
components array/object Components to be used for interpolation

For detailed usage of the Trans component, please refer to this section.

Trans Component Usage

The Trans component is designed to handle more complex translations that may include HTML tags, variables, and even Svelte components. Below are some examples and use-cases where you might find the Trans component useful.

Basic Usage

At its simplest, the Trans component can be used to translate static text.

<Trans key="hello_world" />

With Variables

You can also pass variables for interpolation.

<Trans key="greeting" values={{ name: 'John' }} />

With HTML Tags

HTML tags can be included in the translation string and mapped to actual HTML tags using the components prop.

Example translation string: Click <link>here</link>

<Trans key="click_here" components={{ link: 'a' }} />

Different Ways to Declare Components

As a String

You can declare the component as a string, representing the HTML tag name.

<Trans key="click_here" components={{ link: 'a' }} />
As an Object

You can also declare the component as an object, providing more options including props.

<Trans
  key="click_here"
  components={{
    link: { component: 'a', props: { href: '/page' } }
  }}
/>
As a Svelte Component

You can use a Svelte component directly and pass props to it.

<Trans
  key="click_here"
  components={{
    link: { component: CustomLink, props: { href: '/page' } }
  }}
/>

components as an Array or Object

The components prop can either be an array or an object, depending on your needs.

As an Array

When declared as an array, the components will replace the tags in the order they appear in the translation string.

Translation string: Hello <0>World</0> and <1>universe</1>

<Trans key="key" components={['strong', 'i']} />
As an Object

When declared as an object, you can use meaningful keys to represent your tags, making your code more readable.

Translation string: Hello <bold>World</bold> and <italic>universe</italic>

<Trans key="key" components={{ bold: 'strong', italic: 'i' }} />

Passing Props to Components

You can pass additional props to the components by using the object notation.

<Trans
  key="click_here"
  components={{
    bold: { component: 'strong', props: { class: 'font-semibold' } },
    link: { component: CustomLink, props: { href: '#/' } }
  }}
/>

Advanced Props

The Trans component also accepts a number of advanced props like count, context, defaultValue, and so on.

<Trans key="itemCount" count={5} />

This could translate to "5 items" depending on your translation string and pluralization rules.

Acknowledgements

This library was inspired by the excellent work of SergioDXA on the remix-i18next library. Special thanks to all contributors and users for their support and feedback.

Troubleshooting

If you encounter any issues while using Svelte.i18next, please refer to the following resources for guidance:

  • Documentation: Make sure to read the documentation carefully for any configuration or usage details you might have missed.
  • GitHub Issues: Feel free to open an issue on our GitHub repository if you encounter bugs or have feature requests.
  • Community Support: For general questions and discussions, you can join the Svelte community or other relevant forums.

License

This project is licensed under the MIT License. For more details, see the LICENSE file in the repository.

Top categories

Loading Svelte Themes