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.
To install Svelte.i18next, simply run:
pnpm install @maximux13/svelte-i18next i18next i18next-browser-languagedetector i18next-http-backend
To set up Svelte.i18next in your project, you'll need to go through the following configuration steps:
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
};
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"
}
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;
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}">`)
});
};
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 };
};
Once you've completed the Configuration steps, you can start using Svelte.i18next in your Svelte components and server-side code.
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>
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.
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']
};
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'));
}
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.
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.
At its simplest, the Trans
component can be used to translate static text.
<Trans key="hello_world" />
You can also pass variables for interpolation.
<Trans key="greeting" values={{ name: 'John' }} />
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' }} />
You can declare the component as a string, representing the HTML tag name.
<Trans key="click_here" components={{ link: 'a' }} />
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' } }
}}
/>
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 ObjectThe components
prop can either be an array or an object, depending on your needs.
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']} />
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' }} />
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: '#/' } }
}}
/>
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.
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.
If you encounter any issues while using Svelte.i18next, please refer to the following resources for guidance:
This project is licensed under the MIT License. For more details, see the LICENSE file in the repository.