I've recently started working on our website, which is built using Next JS and TypeScript (specifically, Next 13.5.6). I followed this tutorial to set it up: https://www.youtube.com/watch?v=nfZu56KsK_Q
My current challenge is to implement internationalization with Prismic, so we can smoothly handle both English and French languages on our website. However, I've scoured YouTube and community forums, but I can't seem to find any tutorials or guidance on this specific topic.
That's why I'm reaching out here – I'm wondering if there's anyone who knows how to tackle this and might be interested in helping me out.
I already read this doc a few days ago, but since the project uses typescript (and because I'm a beginner/noob aha) I can't find a way to adapt it to my code :/
In your code I see that your are using the new Next.js App router.
Therefore the current Prismic Next.js internationalization documentation is outdated.
I believe that the following blog post might help you out.
Hello, I'm new to the world of php and I'm discovering the power of React/NextJs/Prismic. I followed the Next.js Full Website Tutorial Course which is just incredible. Thanks Alex Trost :)
I then internalized my POC. It works well for "classic" slice. But on the other hand, I'm having trouble with language switching in a slice with "content relationship" like the Testimonials slice.
How can I switch languages? For now, I'm passing it in raw.
Just pay attention to the context={{lang: lang }} bit on the slice zone, you should be able to keep your page component the same beyond that! Also add this to any other SliceZones your project might have, if that applies.
So then your Testimonials component would look more like this:
const Testimonials = async ({ slice, lang }: TestimonialsProps): Promise<JSX.Element> => {
const client = createClient();
// Now getting lang from the page as a prop
const testimonials = await Promise.all(
slice.items.map((item) =>{
if(
isFilled.contentRelationship(item.testimonial) && item.testimonial.uid
){
return client.getByUID("testimonial",item.testimonial.uid, { lang })
}
} )
)
return ();
};
export default Testimonials;
Let me know if that works or if you have other questions!
Hello Alex,
Firstly, delighted to meet you. Your video is so clear and so simple that it makes one want to work with NextJs / Tailwind and especially Prismic after watching it :)
Great job :)
Next, I tested your code and the language switching in context. However, I have the feeling that my context is not being passed into TestimonialsProps.
My page is a bit different from your example because I'm passing the UID in Params. So the params include UID and lang.
type Params = { uid: string; lang: string };
// My [uid]/page.tsx
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { SliceZone } from '@prismicio/react';
import * as prismic from '@prismicio/client';
import { createClient } from '@/prismicio';
import { components } from '@/slices';
import { getLocales } from '@/utils/getLocales';
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
import Header from "@/components/Header";
import Footer from "@/components/Footer";
type Params = { uid: string; lang: string };
export default async function Page({ params }: { params: Params }) {
const client = createClient();
const lang = params.lang;
const page = await client.getByUID('page', params.uid, {
lang: lang,
})
.catch(() => notFound());
const locales = await getLocales(page, client);
return (
<>
<LanguageSwitcher locales={locales} />
<Header lang={lang} locales={locales} />
<SliceZone slices={page.data.slices} components={components} context={{ lang: lang }}/>
<Footer lang={lang} />
</>
);
}
And this is my Testimonial Slice
import {Content, isFilled} from "@prismicio/client";
import {JSXMapSerializer, PrismicRichText, SliceComponentProps} from "@prismicio/react";
import Bounded from "@/components/Bounded";
import Heading from "@/components/Heading";
import {createClient} from "@/prismicio";
import {PrismicNextImage} from "@prismicio/next";
/**
* Props for `Testimonials`.
*/
export type TestimonialsProps = SliceComponentProps<Content.TestimonialsSlice>;
const Testimonials = async ({ slice, lang }: TestimonialsProps): Promise<JSX.Element> => {
const client = createClient();
const testimonials = await Promise.all(
slice.items.map((item) =>{
if(
isFilled.contentRelationship(item.testimonial) && item.testimonial.uid
){
return client.getByUID("testimonial",item.testimonial.uid, { lang })
}
} )
)
return ();
};
I don't understand what I'm doing wrong.
I think I need to change export type TestimonialsProps
export type TestimonialsProps = SliceComponentProps<Content.TestimonialsSlice>;
You'll notice the // @ts-ignore - That's just to get your page working for now, but I'll ask my colleague @angeloashmore to advise on how best to update that value.
Hey! Here's a simple way to type the context prop:
Create a shared SliceContext type somewhere in your project. Something like src/types.ts works. The type should contain the data you pass to <SliceZone>'s context prop.
// src/types.ts
export type SliceContext = {
lang: string
}
Use that type in your slice prop types:
// src/slices/Testimonials/index.tsx
import { SliceContext } from "@/types";
export type TestimonialsProps = SliceComponentProps<Content.TestimonialsSlice, SliceContext>;
// ...
Now, the context prop passed to the slice component is typed as SliceContext!