Use With SvelteKit
In SvelteKit we eliminate race conditions by not sharing state using a store server-side. So we must create a getTranslator
function per request based on locale.
Get desired locales from cookies and request headers on server
There are three common methods employed to detect a user's desired locale. On the server you can use a root +layout.server.ts
to first check the language settings for the user's browser found in the accept-language
header and also check for a locale
cookie (you set this when users switch the language in your app).
routes/+layout.server.tsts
import type { LayoutServerLoad } from './$types'export const load: LayoutServerLoad = ({ cookies, request }) => {const acceptedLanguage = request.headers.get('accept-language')?.split(',')[0].trim()const chosenLocale = cookies.get('locale')return { acceptedLanguage, chosenLocale }}
Get desired locale from url on server/client
Pass that information to the +layout.ts
which runs both on server and client. Here you check the URL if your app stores the locale in the URL. Then you can use the locale information gathered to selected the appropriate locale that you support and create an instance of the translator functions using the methods you previously created.
routes/+layout.tsts
import type { LayoutLoad } from './$types'import { getSupportedLocale } from '$lib/poly-i18n/locales'import { getTranslator } from '$lib/poly-i18n'export const load: LayoutLoad = async ({ data: { acceptedLanguage, chosenLocale }, url: { searchParams } }) => {const urlLocale = searchParams.get('lang')const locale = getSupportedLocale(urlLocale || chosenLocale || acceptedLanguage)const t = await getTranslator({ locale })return { locale, t }}
This order of preference is important. The URL is the most important, then a cookie which indicates a previous user decision, and finally the browser's language settings.
Type your $page store
src/app.d.tsts
declare global {namespace App {interface PageData {locale: import('$lib/poly-i18n/locales').LocaleCode;t: Awaited<ReturnType<typeof import('$lib/poly-i18n').getTranslator>>;}}}
Use from page data store
Now you can use $page.data.t
and $page.data.locale
in Svelte files:
svelte
<script>import { page } from '$app/stores'</script>{$page.data.locale}, {$page.data.t('hello.world')}
In +page.svelte
and +layout.svelte
files you also could use data.t
and data.locale
:
+page.sveltesvelte
<script>export let data</script>{data.locale}, {data.t('hello.world')}
And in TS/JS files:
ts
import { get } from 'svelte/store'import { page } from '$app/stores'export function sayHi() {const { data: { t } } = get(page)alert(t('hello.world'))}
If you base locale off the url that's all you need for basic i18n in SvelteKit. If you only rely on cookies when a user [changes the locale] then you need to reload the page on locale change.
If you don't want to use $page.data.t
, but want something simple like $t
you can check out this idea from robertadamsonsmith
that uses a store passed down by context.
Our last item to set up is to allow users to [Change locale].