Translation & Localization8 min read

How to Integrate Phrase with Your Headless CMS

Connect Phrase to your headless CMS so published source content becomes translation-ready keys, approved translations return to your content model, and every locale ships from the same structured source.

Published April 29, 2026
01 β€” Overview

What is Phrase?

Phrase is a translation and localization platform for product, marketing, documentation, and engineering teams. It includes tools such as Phrase Strings and Phrase TMS for translation memory, terminology, machine translation, review workflows, and API-based localization pipelines. Teams use Phrase when they need repeatable translation workflows across websites, apps, help centers, and product UI.


02 β€” The case for integration

Why integrate Phrase with a headless CMS?

A launch with 40 landing pages, 12 locales, and 3 review steps gets messy fast when source content lives in one place and translation work happens somewhere else. Editors export copy, translators work from spreadsheets or ZIP files, developers copy translated text back into fields, and nobody is fully sure which locale is current.

Connecting Phrase to a headless CMS changes that handoff. Source fields can be sent to Phrase as structured translation keys, translators can work with Phrase translation memory and terminology, and approved translations can come back into locale-specific fields or documents. With Sanity's AI Content Operating System, content in the Content Lake is structured JSON, so you can send Phrase exactly the fields that need translation instead of scraping HTML or parsing page blobs.

The trade-off is that you need to decide your localization model up front. Field-level locales, document-level locales, and Phrase key naming all affect your sync logic. Once that's mapped, real-time webhooks and Functions let you trigger translation syncs on publish events instead of running nightly exports or asking editors to remember another manual step.


03 β€” Architecture

Architecture overview

A typical Sanity and Phrase integration starts when an editor publishes source content in Sanity Studio. A Sanity webhook, filtered to specific document types such as article, product, or landingPage, fires on the publish event. The webhook can call a Sanity Function or your own endpoint. That handler uses @sanity/client to fetch the published document from the Content Lake with a GROQ projection. For example, it can select title, excerpt, body blocks, SEO fields, and referenced category names while skipping internal notes, analytics IDs, and non-translatable values. The handler then converts those fields into a Phrase-compatible JSON payload, usually with stable keys such as article.my-post.title or product.sku-123.description. Next, the handler calls the Phrase Strings API. For many workflows, that means POST /v2/projects/{project_id}/uploads with multipart form data, including file, file_format, locale_id, update_translations, and tags. Phrase creates or updates translation keys in the project, applies translation memory and terminology rules during translation, and lets localization teams review target locales in their normal Phrase workflow. When translations are ready, you have two common options. Phrase can call back to your endpoint with a webhook, then your code downloads the translated file from Phrase and patches localized fields in Sanity. Or your frontend can use a scheduled sync that writes approved translations into the Content Lake before release. The end user never sees the handoff. They request /de/products/running-shoe, your frontend queries the localized Sanity document, and the page renders the approved German content.


04 β€” Use cases

Common use cases

🌍

Multi-locale product launches

Send product names, descriptions, feature bullets, and SEO copy to Phrase when a source product is published, then write approved translations back before launch.

🧩

Phrase key sync from structured content

Map Sanity fields to stable Phrase Strings keys so translators work with context instead of loose spreadsheet rows.

βœ…

Translation QA before release

Use Phrase review, terminology, and quality checks before localized landing pages are included in a Sanity Content Release.

πŸ“š

Localized documentation updates

Trigger Phrase uploads only when source documentation fields change, so translators don't rework unchanged code samples, metadata, or references.


05 β€” Implementation

Step-by-step integration

  1. 1

    Set up Phrase

    Create a Phrase project, add your source locale and target locales, create an API access token, and note the project ID and source locale ID. Install the packages you'll need with npm install @sanity/client phrase-js, or call the Phrase REST API directly from your webhook handler.

  2. 2

    Model localized content in Sanity Studio

    Choose field-level localization, document-level localization, or a hybrid model. Add stable identifiers such as slug.current, sku, or translationKey so your Phrase keys don't change when editors rewrite titles.

  3. 3

    Create the trigger

    Add a Sanity webhook filtered to publish events for the document types you want to translate. For server-side processing without a separate service, point the webhook at a Sanity Function.

  4. 4

    Fetch only translatable fields with GROQ

    Use a GROQ projection to select fields Phrase needs, including referenced labels when useful. Skip fields such as image asset IDs, feature flags, internal notes, and timestamps.

  5. 5

    Push source content to Phrase

    Convert the GROQ result into simple JSON or another Phrase-supported file format, then call the Phrase Uploads API with file_format, locale_id, update_translations, and tags like sanity or product.

  6. 6

    Test the frontend path

    Publish one source document, confirm the upload appears in Phrase, complete one target locale, sync the approved translation back to Sanity, and query the localized content in your frontend by locale.



07 β€” Why Sanity

How Sanity + Phrase works

Build your Phrase integration on Sanity

Sanity gives you the structured content foundation, real-time event system, and flexible APIs to connect Phrase with your localization workflow.

Start building free β†’

08 β€” Comparison

CMS approaches to Phrase

CapabilityTraditional CMSSanity
Source content handoff to PhraseOften exports whole pages or HTML, so translators may receive layout markup mixed with copy.GROQ projects typed fields from the Content Lake into stable Phrase keys, including referenced content when needed.
Sync timingTranslation exports are often manual or scheduled, which can miss late edits before launch.Webhooks and Functions can run the Phrase upload when specific document types are published.
Locale modelingLocale structure is usually tied to pages, which can make field reuse across channels harder.Schema-as-code lets you model field-level locales, document-level locales, or both, then build the Sanity Studio UI editors need.
Translator contextContext may be limited to exported page titles, screenshots, or notes added by hand.GROQ can send surrounding fields, reference labels, slugs, and content type tags to Phrase in one payload.
Publishing approved translationsEditors often paste translated copy back into pages, which creates room for copy errors.Phrase callbacks can patch localized fields, and Content Releases can group translated updates for review before publish.

09 β€” Next 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 Phrase and 200+ other tools.