Switching between languages in Next.js with Sanity multilingual content

4 replies
Last updated: Oct 13, 2021
Hi everybody. I have set up a landing page that could have content of two languages, norwegian and english. I'm able to query the content of the language I wanted, but I don't know how to switch between languages on the front end (I'm using Next JS). Any suggestions how to solve it? Thanks in advanced. Here is my code:

import React from "react";
import Link from "next/link";
import { Image, Text } from "@chakra-ui/react";
import { BrandTitle, ScreenContainer } from "src/components";
import { groq } from "next-sanity";
import { getClient } from "lib/sanity.server";

const postQuery = groq`
*[_type =='landingPage' && _lang == $lang ]{
    titlePartOne,
    titlePartTwo,
    availableLanguage,
    textContent,
    _lang,
    "image": mainImage.asset->url,
    "caption": mainImage.caption,
}
`;

const language = "no"; //switch value. en_GB for english

export default function Home({ data }) {
  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>
      <Link href="#">{availableLanguage}</Link>
    </ScreenContainer>
  );
}

export async function getStaticProps({ preview = false }) {
  const site = await getClient(preview).fetch(postQuery, {
    lang: language,
  });
  return {
    props: {
      preview,
      data: { site },
    },
  };
}
AI Update

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 thread
4 replies
Hi. I'm looking to change the language value by clicking a button. Sending the value on the client side to the
getStaticProps
Is there any example projects on how to switch between languages by clicking a button?
Hi. I'm looking to change the language value by clicking a button. Sending the value on the client side to the
getStaticProps
Is there any example projects on how to switch between languages by clicking a button?
Hi again. I just figure out that I forgot to define locales in the
next.config.js file
. Thanks for your response.
Glad you got it sorted out!

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.

Was this answer helpful?