Switching between languages in Next.js with Sanity multilingual content
Looking at your code, you're already halfway there! You're successfully querying content by language, but you need to make the language parameter dynamic based on user selection. Here's how to implement language switching in Next.js with Sanity:
Using Next.js Internationalized Routing
The cleanest approach is to use Next.js built-in internationalization routing. Configure it in your next.config.js:
module.exports = {
i18n: {
locales: ['en-GB', 'no'],
defaultLocale: 'no',
},
}Then update your page component to use the locale from Next.js router:
import { useRouter } from 'next/router';
export default function Home({ data }) {
const router = useRouter();
const { locale, locales } = router;
const {
availableLanguage,
image,
caption,
textContent,
} = data?.site[0];
const { titlePartOne, titlePartTwo } = data?.site[1];
return (
<ScreenContainer>
<BrandTitle titlePartOne={titlePartOne} titlePartTwo={titlePartTwo} />
<Image src={image} alt={caption} />
<Text>{textContent}</Text>
{/* Language switcher */}
{locales.map((loc) => (
<Link key={loc} href={router.asPath} locale={loc}>
{loc === 'no' ? 'Norsk' : 'English'}
</Link>
))}
</ScreenContainer>
);
}
export async function getStaticProps({ preview = false, locale }) {
const site = await getClient(preview).fetch(postQuery, {
lang: locale, // Use the locale from Next.js context
});
return {
props: {
preview,
data: { site },
},
};
}Alternative: URL Parameter Approach
If you prefer not to use Next.js i18n routing, you can use query parameters or dynamic routes:
// pages/[lang]/index.js or using query params
import { useRouter } from 'next/router';
export default function Home({ data }) {
const router = useRouter();
const switchLanguage = (newLang) => {
router.push(`/${newLang}`);
};
return (
<ScreenContainer>
{/* Your content */}
<button onClick={() => switchLanguage('en-GB')}>English</button>
<button onClick={() => switchLanguage('no')}>Norsk</button>
</ScreenContainer>
);
}
export async function getStaticProps({ params }) {
const lang = params?.lang || 'no';
const site = await getClient().fetch(postQuery, { lang });
return {
props: {
data: { site },
},
};
}
export async function getStaticPaths() {
return {
paths: [
{ params: { lang: 'no' } },
{ params: { lang: 'en-GB' } },
],
fallback: false,
};
}Important Notes
The Sanity documentation on localization shows that you're using a document-level approach (separate documents per language with _lang field), which is a solid pattern. Just make sure your GROQ query matches your actual field name - if you're using the document internationalization plugin, the field might be __i18n_lang instead of _lang.
Also, consider adding revalidate to your getStaticProps return value for Incremental Static Regeneration so content updates appear without rebuilding:
return {
props: { data: { site } },
revalidate: 60, // Revalidate every 60 seconds
};Show original thread4 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.