Need help with SvelteKit Internationalization (i18n)

Hello Prismic Community, I'm trying to implement internationalization with Prismic and SvelteKit and I couldn't find the documentation to do it in SvelteKit. I am new to front-end development so could anyone please help me or point me to the right direction? I just found out about Prismic and I would really like to continue using it.

The only thing that I found about this online: Internationalization in SvelteKit - #6 by samlittlefair
and I couldn't get the StackBlitz example to work on my end.

Hi @ilyaizenberg ,

Have you tried building this project locally?

Can you explain in more detail what problems your facing and what errors you're seeing?

The more detailed information you can give us about your project and steps, the better. It'll help us help you faster :slight_smile:

I think you misunderstand the issue, there is no issue, so there's nothing to debug, I didn't change anything from the starter template, I'm just trying to figure out how internationalization works in Prismic.

I will try again: here's the code I'm working with: Start a project with SvelteKit & Prismic (github.com)

Could you help me hook it up with internationalization?

No worries, here's a step-by-step guide to adding Internationalisation to the minimal starter.

  1. Add a file called lang.js to the params folder:
export function match(param) {
	console.log({ lang: { param } });
	console.log(param === 'fr-fr');
	return param === 'fr-fr';
}
  1. Add a folder called [lang=lang] inside the folder [[preview=preview]]
  2. Inside this folder add a filed called +page.svelte
<script>
	import { SliceZone } from '@prismicio/svelte';

	import { components } from '$lib/slices';

	export let data;
</script>

<SliceZone slices={data.page.data.slices} {components} />
  1. Add another file called +page.server.ts
import { asText } from '@prismicio/client';

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

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

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

	return {
		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 function entries() {
	return [{}];
}
  1. Inside the [lang=lang] folder add a folder called [uid]
  2. Inside this folder add a filed called +page.svelte
<script>
	import { SliceZone } from '@prismicio/svelte';

	import { components } from '$lib/slices';

	export let data;
</script>

<SliceZone slices={data.page.data.slices} {components} />
  1. Add another file called +page.server.ts
import { asText } from '@prismicio/client';

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

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

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

	return {
		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 };
	});
}
  1. Update the +page.server.ts files outside the [lang=lang] folder to use the use the code shown above.
  2. In the routes folder update the +layout.svelte file with this code:
<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>

<h1>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} />
  1. Update the src/lib/prismicio.ts file with this code:
import * as prismic from '@prismicio/client';

import { enableAutoPreviews } from '@prismicio/svelte/kit';

import sm from '../../slicemachine.config.json';

/**

* The project's Prismic repository name.

*/

export const repositoryName = import.meta.env.VITE_PRISMIC_ENVIRONMENT || sm.repositoryName;

/**

* A list of Route Resolver objects that define how a document's `url` field is resolved.

*

* {@link https://prismic.io/docs/route-resolver#route-resolver}

*

* @type {prismic.ClientConfig["routes"]}

*/

// TODO: Update the routes array to match your project's route structure.

const routes = [

{ type: 'page', path: '/', uid: 'home' },

{ type: 'page', path: '/fr-fr', lang: 'fr-fr', uid: 'accueil' },

{ type: 'page', path: '/:uid' },

{ type: 'page', path: '/fr-fr/:uid', lang: 'fr-fr' }

];

/**

* Creates a Prismic client for the project's repository. The client is used to

* query content from the Prismic API.

*

* @param {import('@prismicio/svelte/kit').CreateClientConfig} config - Configuration for the Prismic client.

*/

export const createClient = ({ cookies, ...config } = {}) => {

const client = prismic.createClient(sm.apiEndpoint || repositoryName, {

routes,

...config

});

enableAutoPreviews({ client, cookies });

return client;

};

That should be everything, no need to add i18n :slight_smile:

1 Like

Hey it worked, thanks!

Oh, I get this error message when I use npm run build though:

Error: Missing parameter 'lang' in route /[[preview=preview]]/[lang=lang]

and

Property 'lang' is missing in type '{}' but required in type 'RouteParams'.ts(2741)

Type '{ uid: string; }[]' is not assignable to type 'RouteParams[]'. Property 'lang' is missing in type '{ uid: string; }' but required in type 'RouteParams'.ts(2322)

in VSCode.

When I use npm run dev everything works fine, I'm just having issues deploying...

I'm not sure what the issue could be; I'm not really up to scratch with Svelte. I'm going to reach out to my team for help.

Can you send me a Github link to your project?

In the meantime, if you can ask the Svelte Community as well to see if they have any ideas?

P.S. I removed some of our previous replies for future user readability.

I wonder in src/routes/[[preview=preview]]/[lang=lang]/+page.server.ts if you update:

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

to

    const page = await client.getByUID('page', 'home', {
		lang: params.lang || 'en-us'
	});

and in src/routes/[[preview=preview]]/[lang=lang]/[uid]/+page.server.ts update:

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

to

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

Maybe this will stop the builder error?

Thanks again,

Here's my GitHub project: ily-aiz/ilyaiz-240823-sveltekit-01 (github.com)

The build is failing with the following error:
Error: The entries export from /[[preview=preview]]/[lang=lang] generated entry /en-us, which was matched by /[[preview=preview]]/[uid] - see the handleEntryGeneratorMismatchoption in https://kit.svelte.dev/docs/configuration#prerender for more info.

I tried making the changes you suggested to no avail.

Maybe it's because we have 2 routes which are the same? In dev it might be fine but in development this isn't allowed?

maybe we need to say the /[[preview=preview]]/[uid] route that en-us (master local) is not a valid uid for it, so it should be skipped.

Creating src/params/uid.ts:

export function match(param) {
	return param !== "en-us"
}

And renaming src/routes/[[preview=preview]]/[uid] to src/routes/[[preview=preview]]/[uid=uid] could help(?)

Here's an updated version of your project that seems to be working: Ily-aiz - Ilyaiz 240823 Sveltekit 01 - StackBlitz, we updated the entries function in the lang folder to also return a lang property for routes to be created properly.

1 Like

Thanks for the help.

The StackBlitz example you gave breaks, it doesn't switch between languages...

Hi there, I stumbled upon this discussion due to documentation search for multi-lang using SvelteKit. I experienced the same error and after some troubleshooting got it working so npm run build runs successfully.

The setup up until this point is great. Adjusting the entries() function to reflect the lang params did it for me. So to stay in the bounds of this case I refer to the +page.server.ts file @Phil shared.

Update for entries() function:

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

	const pages = await client.getAllByType('page', { lang: "fr-fr" });

	return pages.map((page) => {
		return { lang: "fr-fr", uid: page.uid };
	});
}

Cheers!

1 Like

Thanks for sharing @jonasherdegen :slight_smile: