Multi-language URL structure: /fr/page-name instead of /page-name-fr

3 replies
Last updated: Jan 28, 2026
Hi!I was wondering for multi-language - Is there a way where I can make the URL
domain.com/fr/page-name ? Currently we our translations is pretty much like a new page/post/etc and the name would be something like Page Name Fr which makes the URL, domain.com/page-name-fr Thanks for any insight!
AI Update

I totally understand your challenge! You want cleaner URLs with the language code as a directory (like /fr/page-name) instead of appending it to the slug (like /page-name-fr). This is definitely achievable with Sanity, and it's actually a common pattern for multilingual sites.

The key is understanding that Sanity stores your content, but your frontend application (like Next.js, Nuxt, or whatever you're using) determines the actual URL structure. Here's how to approach this:

The Solution: Handle URLs in Your Frontend

When using document-level internationalization (which sounds like what you're doing), each language version is a separate document. You'll want to:

  1. Use the same slug across translations - Instead of naming your French page "Page Name Fr" with slug page-name-fr, just use page-name for both the English and French versions. Store the language as a separate field (like language: 'fr' or language: 'en').

  2. Structure your frontend routes - Set up your routing to include the language code in the path. For example, in Next.js, you'd create a file structure like pages/[lang]/[slug].js or use the built-in i18n routing.

  3. Query by language and slug - When someone visits /fr/page-name, your frontend extracts both the language (fr) and slug (page-name), then queries Sanity for the document matching both criteria:

*[_type == "page" && slug.current == $slug && language == $lang][0]

Implementation Example

Your document structure would look like:

  • English page: { title: "Page Name", slug: "page-name", language: "en" }
  • French page: { title: "Nom de la page", slug: "page-name", language: "fr" }

Notice both use the same slug, but different language codes. Your frontend routing handles the /fr/ or /en/ prefix, while Sanity just stores the base slug.

This approach gives you the clean URL structure you want (domain.com/fr/page-name) while keeping your content organized in Sanity. The @sanity/document-internationalization plugin can help manage these relationships and make it easier for editors to navigate between translations in the Studio.

This is similar to how WordPress plugins like Polylang and WPML handle the "same slug across languages" feature - the CMS allows duplicate slugs differentiated by language, and the frontend routing adds the language directory prefix. For more details on document-level localization, check out Sanity's localization documentation!

Show original thread
3 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.

Was this answer helpful?