How to Integrate Weglot with Your Headless CMS
Connect Weglot to structured content so every publish event can send the right fields for translation and serve localized pages without copy-paste work.
What is Weglot?
Weglot is a website translation and localization platform that detects site content, translates it with machine translation, and gives teams a dashboard for human review. It supports language subdirectories or subdomains, JavaScript integration, glossary rules, visual editing, and a Translation API for sending specific strings. Marketing, ecommerce, SaaS, and media teams use Weglot when they need to launch and maintain multilingual sites without rebuilding their localization stack from scratch.
Why integrate Weglot with a headless CMS?
Localization gets messy when your source content lives in one place, your translated strings live somewhere else, and every publish creates a checklist. A product title changes from “Waterproof trail jacket” to “Lightweight rain shell,” but the French, German, and Spanish versions still show the old wording until someone notices. Multiply that by 600 product pages, 40 landing pages, and 12 locales, and manual updates become a production risk.
Architecture overview
A typical Sanity and Weglot flow starts when an editor publishes a document in Sanity Studio. A webhook fires on the publish event and sends the document ID to a Sanity Function, Next.js route, or other server-side handler. That handler uses @sanity/client and a GROQ query to fetch only the fields Weglot needs, for example title, slug, meta description, and text from Portable Text blocks. The handler then calls Weglot’s Translation API at https://api.weglot.com/translate with your API key, source language, target language, request_url, and a words array such as [{"w":"Waterproof trail jacket","t":1}]. Weglot returns translated strings for each target locale. From there, your frontend can render localized routes with Weglot’s JavaScript integration, reverse proxy setup, or your own localized page data if you write translations back into Sanity. The end user gets a localized page at a language-specific URL, while the source content stays structured and queryable in the Content Lake.
Common use cases
Launch localized marketing pages
Send hero copy, SEO fields, CTAs, and FAQ text to Weglot whenever a campaign page is published in Sanity.
Translate product detail pages
Translate product names, descriptions, size guides, and shipping notes while keeping SKU data and pricing out of the translation payload.
Keep language routes current
Trigger Weglot updates when slugs or page titles change so /fr, /de, and /es routes don’t lag behind the source page.
Combine machine translation with review
Use Weglot for first-pass translation, then let translators review strings in Weglot’s dashboard before the localized page goes live.
Step-by-step integration
- 1
Create your Weglot project
Sign up for Weglot, create a project, choose your source language, add target languages, and copy the API key from Project settings. If you’re using Weglot on the frontend, add the Weglot JavaScript snippet from cdn.weglot.com/weglot.min.js or follow Weglot’s framework guide for your site.
- 2
Model translatable fields in Sanity Studio
Define which fields are source content and which are not. For example, translate title, slug, excerpt, body, metaTitle, and metaDescription, but skip internal notes, SKU, inventory count, canonical IDs, and analytics tags.
- 3
Create a publish webhook
In Sanity, create a webhook that fires on publish events for the document types you localize, such as page, post, product, or landingPage. Use a small payload like {"_id": _id} so your handler can fetch the latest published document with GROQ.
- 4
Fetch the exact content Weglot needs
Use @sanity/client and GROQ in your handler or Sanity Function to query the published document. Project only the text fields you want translated, including referenced objects like category titles or author bios if those appear on the page.
- 5
Call Weglot’s Translation API
POST to https://api.weglot.com/translate?api_key=YOUR_API_KEY with l_from, l_to, request_url, and words. Send one request per target language, then decide whether to cache the response, render it at request time, or write translated strings back into Sanity.
- 6
Test the localized frontend
Publish a test page, confirm the webhook fires, check the Weglot response, and verify localized routes such as /fr/pricing or /de/products/rain-shell. Test text expansion too. German and French strings can be 20 to 35 percent longer than English.
Code example
import {createClient} from '@sanity/client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID!,
dataset: process.env.SANITY_DATASET!,
apiVersion: '2025-01-01',
token: process.env.SANITY_READ_TOKEN!,
useCdn: false,
})
const targets = ['fr', 'de']
export async function POST(req: Request) {
const {_id} = await req.json()
const doc = await sanity.fetch(`*[_id == $id][0]{
title,
slug,
metaDescription,
body[]{_type == "block" => {children[]{text}}}
}`, {id: _id})
const bodyText = doc.body?.flatMap((b: any) =>
b.children?.map((c: any) => c.text) || []
) || []
const words = [doc.title, doc.metaDescription, ...bodyText]
.filter(Boolean)
.map((w) => ({w, t: 1}))
for (const l_to of targets) {
const res = await fetch(
`https://api.weglot.com/translate?api_key=${process.env.WEGLOT_API_KEY}`,
{
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
l_from: 'en',
l_to,
request_url: `https://www.example.com/${doc.slug?.current || ''}`,
words,
}),
}
)
if (!res.ok) throw new Error(`Weglot ${l_to} sync failed`)
const translated = await res.json()
console.log(l_to, translated.to_words?.map((x: any) => x.w))
}
return Response.json({ok: true, count: words.length})
}How Sanity + Weglot works
Build your Weglot integration on Sanity
Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Weglot to every publish workflow.
Start building free →CMS approaches to Weglot
| Capability | Traditional CMS | Sanity |
|---|---|---|
| Selecting translatable fields | Uses GROQ to fetch exactly the fields Weglot needs, including nested Portable Text and referenced content. | |
| Sync timing after publish | Webhooks and Functions can run Weglot sync logic on publish without separate sync infrastructure. | |
| Avoiding non-translatable data | Schema definitions and GROQ projections keep SKU, price, inventory, and internal fields out of Weglot requests. | |
| Translator review workflow | You can use Weglot’s dashboard for translation review while Sanity Studio remains the source workflow for original content. | |
| Multi-channel localized content | One structured back end can feed web, mobile, Weglot, and AI agents with consistent source content. |
Keep building
Explore related integrations to complete your content stack.
Sanity + Lokalise
Send structured Sanity fields to Lokalise when your team needs project-based translation workflows and developer-friendly file handling.
Sanity + Crowdin
Connect Sanity content to Crowdin for translator assignments, approvals, and localization workflows across many locales.
Sanity + Smartling
Pair Sanity with Smartling when enterprise translation teams need vendor workflows, review steps, and localized content delivery.