
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeLooking 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:
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 },
},
};
}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,
};
}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
};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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store