Sanity CMS multilingual support with next-intl in the Next.js App Router is one of those setups where each piece works fine in isolation but the wiring between them is fiddly. This post documents exactly how I connect the two on production projects: schema design, GROQ query patterns per locale, and the slug uniqueness trap that bites every team at least once.
What each tool is actually responsible for
Before touching code, get the responsibilities straight. Sanity's document internationalisation plugin handles content storage — it creates one document per locale with a shared _id prefix (e.g. page.en, page.fr). next-intl handles routing and message delivery — locale segments in the URL, useTranslations, and the [locale] dynamic segment. Neither tool knows about the other by default. Your job is the bridge layer.
Schema design for translated fields
Install the plugin first:






