Internationalization in SvelteKit

Hey Janis,

You could certainly use a catch-all route. However, that will force you to handle the routing logic manually, which I find a little stressful personally :sweat_smile:

If you don't mind duplicating your +page.svelte files in a few places, then I think you can avoid any catch-all routes.

There's a convenient solution for the layout. SvelteKit provides a global store for all the data you query in your application:

<script>
  import { page } from { $app/stores }
</script>

<pre>
  <!-- This will display all of the data fetched in your application -->
  {JSON.stringify($page)}
</pre>

You can use this in your +layout.svelte file to use the data fetched in your +page.server.js file (we already do this to handle metadata in the starter projects).

Therefore, you can query your global data in +page.server.js and then access it from $page in your +layout.svelte to get a localized header and footer. For example:

// src/routes/[[preview=preview]]/[lang=lang]/[uid]/+page.server.js

import { asText } from '@prismicio/client';

import { createClient } from '$lib/prismicio';

export async function load({ params, fetch, cookies }) {
	const client = createClient({ fetch, cookies });

	const settings = await client.getSingle('settings', { // 👈 Fetch your global data localized
		lang: params.lang || 'en-us'
	});

	const page = await client.getByUID('page', params.uid, {
		lang: params.lang
	});

	return {
		settings, // 👈 Return your global data
		page,
		title: asText(page.data.title),
		meta_description: page.data.meta_description,
		meta_title: page.data.meta_title,
		meta_image: page.data.meta_image.url
	};
}

export async function entries() {
	const client = createClient();

	const pages = await client.getAllByType('page');

	return pages.map((page) => {
		return { uid: page.uid };
	});
}

and:

<!-- src/routes/+layout.svelte --> 

<script>
	import { PrismicPreview } from '@prismicio/svelte/kit';
	import { page } from '$app/stores';
	import { repositoryName } from '$lib/prismicio';
</script>

<svelte:head>
	<title>{$page.data.title}</title>
	{#if $page.data.meta_description}
		<meta name="description" content={$page.data.meta_description} />
	{/if}
	{#if $page.data.meta_title}
		<meta name="og:title" content={$page.data.meta_title} />
	{/if}
	{#if $page.data.meta_image}
		<meta name="og:image" content={$page.data.meta_image} />
		<meta name="twitter:card" content="summary_large_image" />
	{/if}
</svelte:head>

<header>
	<nav>
		<!-- 👇 Use your global data -->
		<h1>{$page.data.settings.data.website_title}</h1> 
	</nav>
</header>

<ul>
	<li><a href="/">English</a></li>
	<li><a href="/fr-fr">French</a></li>
</ul>

<main>
	<slot />
</main>

<PrismicPreview {repositoryName} />

I've updated the Stackblitz example:

Let me know if that helps!

Sam