multilingual / cms

Translation Workflows That Don't Break Your CMS

Most translation workflows treat content like a document, while a headless CMS treats it as structured data. The mismatch breaks formatting and lets content drift. Here are the documented ways a CMS-to-TMS integration fails, and what to check in yours.

Open Markdown version

A translator sends back a batch of content and the page falls apart. The French CTA button wraps onto two lines. The Italian hero headline runs past the space the design gave it and pushes the layout out of shape. Three pages show pricing that was already replaced, because someone translated from a version that no longer exists.

It is tempting to blame the translator. The real problem sits one level down, in how the CMS stores and hands off content. A translation cycle run through spreadsheets, email threads, and copy-paste keeps producing the same formatting and sync bugs no matter who does the translating, because the workflow was never designed around the way the CMS actually stores and delivers text. The shape of the problem is architectural, and no amount of extra tooling fully papers over it.

Companies keep buying tools to fix this. The translation management systems market grew from USD 2.4 billion in 2025 and is forecast to reach USD 4.93 billion by 2032, a compound annual growth rate of 10.82 percent, according to Research and Markets. A TMS is a genuinely useful workspace. It only solves the handoff problem when the CMS underneath is structured to feed it cleanly, which is where most setups fall short.

Why do translation workflows break CMS content?

The root cause is almost always a mismatch between how the CMS stores content and how translation handles it. That mismatch shows up in four predictable ways.

Translators work without seeing the page. In most workflows, content gets exported from the CMS into a spreadsheet or a document, and the translator sees raw text stripped of layout and character limits, with no way to tell whether a string is a headline, a button, or a caption. The translation reads correctly and still breaks the design, because a phrase that fits the English space runs longer once translated. Nobody catches it until the page is live.

Rich-text blobs resist clean extraction. Many CMS platforms and page builders store content as HTML blobs, where a single field holds headings, paragraphs, bold text, links, and embedded media together. Pulling translatable text out of that blob without losing formatting is fragile work. Every round trip through a translation tool risks stripping inline styles, breaking link targets, or corrupting an embedded component. This is one reason editor experience matters more than most teams expect. When the CMS stores content as separate typed fields instead of one blob, the extraction problem disappears.

Manual handoffs open sync gaps. Content gets exported, emailed to an agency, and returned days later to be pasted back in. In those days the source can change, and the person importing the translations often does not know which version was translated. Fields get mismatched. Updates overwrite each other. The German page ends up showing last month’s pricing while the English page has already moved on.

Text expansion breaks fixed layouts. Translated strings rarely come back the length they went out. The expansion rates W3C publishes, taken from IBM’s guidelines for designing global software, run at 200 to 300 percent of the original for source strings of up to ten characters, and settle at around 130 percent once the source runs past seventy. The shorter the string, the worse the ratio gets, which is why button labels and navigation items break before body copy does. A frontend built around fixed widths surfaces a new set of layout bugs with every language you add.

What does a broken translation workflow actually cost?

The direct cost is developer and editor time. After every translation round, someone re-aligns layouts, fixes formatting, and hunts down strings that landed in the wrong field. On a site with five languages and a normal publishing cadence, that is hours a week nobody budgeted for.

The indirect cost is larger. Market launches slip because the translation cycle runs long. Content drifts out of sync between languages because updating it is painful enough that people put it off. Pages meant to go live together across markets end up days or weeks apart.

CSA Research surveyed more than 8.000 consumers across 29 countries for the 2020 edition of its “Can’t Read, Won’t Buy” study and found that 76 percent of them prefer to buy where the product information is in their own language, and 40 percent said they will never buy from a website in another language. Every week a market sits without current local-language content is a week of demand you cannot convert. The case for multilingual content is settled. The workflow is what holds most teams back.

What does a translation workflow that works look like?

A working translation workflow has three layers: the CMS as the source of content, a TMS as the workspace where translation happens, and the CMS again as the destination. Content moves between them over APIs, rather than as email attachments and copy-paste.

The CMS pushes fields, not pages. When an editor finishes a page in the source language, the CMS fires a webhook that sends the translatable fields to the TMS. It sends the individual fields, each keyed by its own identifier: the headline, the body text, the CTA label, the meta description. Because every field travels with its identity, the translation can find its way back to the exact field and locale it came from when it returns. An export-and-import button cannot do this reliably, because a flat file has no stable field identity to match against on the way back.

Translators work in an environment built for the job. Inside the TMS, each string carries context notes, a character limit, and a preview of where it appears. Translators reuse translation memory (previously approved segments), pull from glossaries of agreed terminology, and start from machine-translation suggestions. It is a workspace built for translation.

AI drafts, a human edits. My position on this one is simple: let AI do the first pass and have a human edit it. The model produces a draft in seconds and a native-speaking editor decides what ships. That is the same split we run in our own content pipelines and in the agentic marketing automation work we do for clients, where the machine goes first and a person checks the output after every significant step and again at the end. DeepL frames its own high-stakes work the same way, calling machine translation post-editing the preferred model and describing a human-in-the-loop approach for regulated content.

Translations return to the correct field automatically. When a string is approved in the TMS, it flows back through the API into the exact field and locale it belongs to. The French headline lands in the French headline field rather than beside the Italian body text. Nothing is imported by hand and nothing has to be reconciled afterward. The editor sees an updated translation status against each field and publishes once the locale is complete.

Each role stays in one tool. Editors stay in the CMS, translators and reviewers stay in the TMS, and developers stay out of routine translation cycles entirely. Everyone works where their job was meant to be done.

How does structured content make translation safer?

Every step above depends on one thing: the CMS storing content as structured data rather than as rendered pages. This is the point where CMS architecture decides whether translation is a routine content operation or a recurring source of bugs.

Field-level translation removes what breaks. When each piece of content has its own typed field, there is nothing to corrupt. A headline field holds a headline. A CTA field holds a button label. The translator works one field at a time, with no HTML tags to mangle and no inline styles or embedded components to overwrite by accident.

Component structure stays language-independent. In a headless CMS, pages are assembled from reusable components: hero sections, feature lists, pricing tables. That structure is defined once and does not change per language; only the text inside it does. A French pricing table has the same layout as the German one. The columns hold their place, the styling holds, and the design stays consistent across markets without anyone checking each page by hand.

The frontend absorbs text expansion. A frontend that renders structured content from an API can be built for variable-length text from the start. Flexible layouts, responsive typography, and real overflow handling mean a longer German headline flexes the hero section instead of breaking it. The box grows to fit the text it is given.

Translating inside a page builder works the opposite way. There, content and layout are welded together, so changing the text changes the layout. In a structured architecture the two are separate concerns, and translation touches one without disturbing the other.

What should you look for in a CMS-TMS integration?

Integrations are not all the same. Some are real API-driven workflows, and others are an export-import button with a nicer label. This is what separates them:

Capability Manual workflow Basic plugin API-driven integration
Content extraction Copy-paste or file export One-click export to file Automatic via webhook
Translation context None (raw text in spreadsheet) Limited (file with field names) Full (preview, character limits, notes)
Return of translations Manual import and field matching One-click import Automatic into correct fields
Sync on source update Manual re-export Manual re-export Automatic detection of changed fields
Translation status visibility External tracking (spreadsheet) Basic status in CMS Real-time status per field per language
Glossary and TM support None Depends on TMS Full integration
Risk of formatting loss High Medium Low

The API-driven column is what headless platforms like DatoCMS and Storyblok are designed to support, because they expose their content field by field over an API that translation tools plug into. Crowdin publishes its own connectors for both, and each one syncs in both directions and can pick up source changes and returning translations on a schedule (Crowdin Store). They are paid apps in the Crowdin Store rather than something bundled with the CMS, which is worth knowing before you budget for the setup.

If your current CMS makes you export content as XML or CSV, send the files out, and import them back, you are working at the manual end of this table. That workflow breaks your content again every time you add a language or publish more often.

Why does an API integration keep breaking your translation workflow?

Most of what breaks sits in the plumbing between the two systems rather than in the translation. A webhook delivery fails and nothing re-sends it. A locale code is spelled one way in the CMS and another in the TMS. A rate limit cuts a bulk write in half. Every one of those is documented vendor behaviour, which means you can go and check your own setup against it this afternoon.

Here is what the usual symptoms turn out to be.

What you see What is usually happening Where to look
A page never showed up in the TMS The delivery failed and nothing re-sent it. Storyblok states that its webhooks do not retry on failure, and Crowdin sends each queued event once and does not send it again after a timeout or an error The webhook delivery log in the CMS, and whether anything reconciles misses
Deliveries fail under load while the endpoint looks healthy DatoCMS allows 2 seconds to connect and 8 seconds in total, then marks the call failed and retries up to seven times on a widening schedule Your endpoint’s response time, and whether it acknowledges before it works
Translations come back into the wrong locale, or into none The identifiers do not match on the return trip. Storyblok’s field-level translation needs underscores, es_co rather than es-co, and a space can have been configured with the hyphen form The CMS locale list against the locale codes the TMS holds
Some locales updated and the rest did not No vendor here documents an atomic multi-record write. DatoCMS caps a bulk operation at 200 records and publishes nothing about what happens when one of them fails Whether your integration can resume a partial run without re-sending it all
A bulk return of translations stalls or drops entries Rate limits. The DatoCMS Content Management API allows 60 requests every 3 seconds; the Storyblok Management API allows 3 per second on Starter and 6 on Growth and above The 429 responses in your integration’s logs
The translation is accurate and describes an older page The source moved while the job was open, and nothing recorded which version went out The version or timestamp your integration stores when it opens a job
Bold, a link target, or an embedded component disappears Rich text is a structured tree rather than markup. DatoCMS ships separate converters in each direction for HTML and markdown, and a Storyblok blok node has no HTML equivalent to convert into Whether your pipeline sends the rich-text JSON or a flattened string
The CMS shows the translation, the live page shows the old text Draft and published are different reads. DatoCMS returns published records unless you send X-Include-Drafts: true, and the Storyblok version parameter defaults to published Which version each side of the integration asks for

Two of these surprise teams who have the rest of the setup right, so they are worth pulling out.

Publishing one locale can publish all of them. Storyblok publishes every language version of a story at the same time by default, unless Individual Translation Publishing is switched on (Storyblok). A returning French translation can therefore push an unfinished German draft live alongside it, and the German page changes without anyone asking for it.

Adding a locale can invalidate records you already had. DatoCMS enforces field validations across every locale once the locale exists, so records created before that point get marked invalid (DatoCMS). The write that fails on the return trip is then failing validation on a locale nobody has translated yet, which looks nothing like a translation problem from the outside.

What to check in your own setup

  1. Open the webhook delivery log in your CMS and count the failures over the past month. If the number is above zero and nothing re-sends them, you have content that was silently never translated.
  2. Time your TMS endpoint’s response. Crowdin’s own guidance is to respond first, process afterwards, and use the API to catch up on anything the service missed while it was unavailable. DatoCMS gives you 8 seconds in total, so synchronous work inside the handler will cost you deliveries on latency alone.
  3. Put the CMS locale list next to the locale codes the TMS holds and compare them character by character, hyphens and underscores included.
  4. Search your integration’s logs for 429 responses, then work out your peak write rate against the published limit for your plan.
  5. Check what your integration records when it opens a job. Without the source version stored, it cannot tell you whether a returning translation is still current.
  6. Take one page that has a link, a bold run and an embedded component, send it through a full round trip, and compare the rich-text JSON before and after.
  7. Ask which version each side reads. Editors work on drafts, and both DatoCMS and Storyblok hand out published content by default.

Most of that is reading a settings screen and a log file, which anyone with CMS access can do in an afternoon.

Where should you start?

If your team runs translation through spreadsheets and email, the constraint is the workflow, and the workflow is shaped by the CMS architecture beneath it.

Start by looking at how your current setup stores and hands off multilingual content. Our guide to managing multilingual content at scale covers the CMS-level patterns, and if translation quality keeps slipping past review, the content QA pipeline you run before you ship shows how to catch parity and per-locale problems before they reach production. If you are planning to expand into new markets, we wrote a practical guide to launching a website in a new market without rebuilding everything.

For a clear read on your specific setup, a headless audit maps the gaps in your current architecture and what moving to field-level translation would take. If you already know you need a new foundation, our headless website service builds multilingual-ready architectures from the start, where adding a language stays an editorial job.

Essential Code is your Fractional Marketing Engineer: a small senior team that joins your marketing team and builds what your marketing plan needs.

How the service worksNot sure yet? Start with an auditOr email us directly