> For the complete documentation index, see [llms.txt](https://developers.weglot.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.weglot.com/frameworks-and-ai/react/guides/sanity.md).

# Sanity

Translate your Sanity website built with Next.js with Weglot.

Make your Sanity + Next.js website multilingual with the Weglot React package. Text written in your code is translated when your website is built, and content coming from Sanity is translated server-side when the page renders. Languages and translations are managed in your Weglot 2.0 project.

## 1. Set up the package

Follow [Getting started](/frameworks-and-ai/react/getting-started.md) in the folder that contains your Next.js website (often `frontend` in Sanity starters). Point `sourceRoot` to the folder that contains all your pages and components, for example `./app`.

Text written in your code is now translated. Content coming from Sanity needs one more step.

## 2. Translate Sanity content

Translate the fields you fetch from Sanity with the [dynamic content functions](/frameworks-and-ai/react/dynamic-content.md). Portable Text is translated as HTML: convert it with `@portabletext/to-html` first. Optional fields can be empty, so pass `?? ""` for them.

```bash
npm install @portabletext/to-html
```

```tsx
// app/posts/[slug]/page.tsx
import { tDynamicAll, tDynamicHtml } from "@weglot/translate-react/dynamic";
import { toHTML } from "@portabletext/to-html";
import { client } from "@/sanity/client";

export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await client.fetch(POST_QUERY, { slug });

  const [[title, excerpt], body] = await Promise.all([
    tDynamicAll([post.title ?? "", post.excerpt ?? ""]),
    tDynamicHtml(toHTML(post.body ?? [])),
  ]);

  return (
    <article>
      <h1>{title}</h1>
      <p>{excerpt}</p>
      <div dangerouslySetInnerHTML={{ __html: body }} />
    </article>
  );
}
```

{% hint style="warning" %}
If you render Portable Text with `@portabletext/react` and custom components, rendering the translated HTML replaces them. Keep the components that matter in your HTML serializers.
{% endhint %}

Translate SEO fields in `generateMetadata` the same way:

```tsx
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await client.fetch(POST_QUERY, { slug });
  const [title, description] = await tDynamicAll([post.seo?.title ?? "", post.seo?.description ?? ""]);
  return { title, description };
}
```

## 3. Check the shared fields

Content that appears on every page is easy to miss. Make sure these fields go through `tDynamic`, `tDynamicAll` or `tDynamicHtml`:

* navigation and footer;
* buttons and calls to action;
* page headers;
* SEO fields and image alt texts.

## 4. Skip translation in draft mode

With Visual Editing, Sanity encodes invisible characters in the strings of draft content. Translating them would break click-to-edit and send your drafts to Weglot. Serve the source text in draft mode:

```tsx
import { draftMode } from "next/headers";

const { isEnabled } = await draftMode();
const [title, excerpt] = isEnabled
  ? [post.title, post.excerpt]
  : await tDynamicAll([post.title ?? "", post.excerpt ?? ""]);
```

## Next steps

* [Add a language switcher](/frameworks-and-ai/react/use-cases.md#add-a-language-switcher).
* [Exclude content from translation](/frameworks-and-ai/react/use-cases.md#exclude-content-from-translation), such as your brand name.
* If you cache Sanity data yourself, read [When the source text is returned](/frameworks-and-ai/react/dynamic-content.md#when-the-source-text-is-returned).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers.weglot.com/frameworks-and-ai/react/guides/sanity.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
