Translation & Localization8 min read

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.

Published April 29, 2026
01Overview

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.


02The case for integration

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.


03Architecture

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.


04Use cases

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.


05Implementation

Step-by-step integration

  1. 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. 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. 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. 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. 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. 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.


06Code

Code example

typescriptapp/api/weglot-sync/route.ts
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})
}

07Why Sanity

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 →

08Comparison

CMS approaches to Weglot

CapabilityTraditional CMSSanity
Selecting translatable fieldsUses GROQ to fetch exactly the fields Weglot needs, including nested Portable Text and referenced content.
Sync timing after publishWebhooks and Functions can run Weglot sync logic on publish without separate sync infrastructure.
Avoiding non-translatable dataSchema definitions and GROQ projections keep SKU, price, inventory, and internal fields out of Weglot requests.
Translator review workflowYou can use Weglot’s dashboard for translation review while Sanity Studio remains the source workflow for original content.
Multi-channel localized contentOne structured back end can feed web, mobile, Weglot, and AI agents with consistent source content.

09Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with Weglot and 200+ other tools.