Back to Partners
Guide

Preserving Formats and Placeholders in Translation API Workflows

Preserving formats and placeholders in translation API workflows: protecting ICU MessageFormat tokens, HTML tags, and Markdown structure through pre-processing, protected segments, and post-translation validation.

Preserving Formats and Placeholders in Translation API Workflows

Broken translations rarely fail at the language level. They fail at the structural level: a curly brace gets swallowed, an HTML tag is reordered, a numeric placeholder like {0} is localized into Ù  and the template engine crashes. When you push strings through a translation API, every ICU MessageFormat token, every <span> tag, and every Markdown link must survive the round trip intact. This article walks through the concrete techniques, tag-handling modes, non-translatable markers, segmentation strategies, and automated validation, that keep your translated output structurally identical to the source. If your team has ever shipped a release where translated strings broke the UI, the problem was almost certainly a format-preservation gap in your API workflow.

If your localization pipeline spans text, software, websites, and more, explore how Ollang handles format preservation end to end.

Why Placeholder Corruption Is the Most Common Translation Bug

Placeholder corruption is disproportionately destructive because it is invisible until runtime. A missing closing </b> tag produces malformed HTML that silently breaks layout. A reordered ICU argument like {count, plural, one {# item} other {# items}} can cause a crash in libraries such as FormatJS or Android's MessageFormat. A JSON key accidentally translated turns a structured payload into garbage.

The root cause is straightforward: translation engines treat input as natural language text. Placeholders, tags, and tokens are not natural language. Without explicit instructions, a model or translation memory has no reason to preserve %s, {{username}}, or [link text](https://ollang.com/book-a-demo) verbatim. The translation API must be told what is translatable and what is not.

Common failure modes include:

  • Brace reordering: {1} and {0} swap positions, producing "Hello Smith, John" instead of "Hello John Smith."
  • Numeric token localization: {0} becomes {Ù } in Arabic or {০} in Bengali, breaking interpolation.
  • HTML stripping or nesting errors: <a href="..."> gets dropped or its attributes are translated.
  • Markdown mangling: [Click here](https://example.com) becomes [Cliquez ici] (https://example.com) with a space before the parenthesis, breaking the link.

These are not edge cases. According to the Unicode CLDR project, ICU MessageFormat is used in the majority of modern internationalization frameworks, meaning placeholder integrity is a universal concern.

Anatomy of Translatable Strings: ICU, HTML, Markdown, and JSON Tokens

ICU MessageFormat Patterns

ICU MessageFormat strings encode pluralization, gender selection, and argument substitution directly inside the string. A typical pattern looks like this:

You have {count, plural, one {# new message} other {# new messages}}.

The nested braces, the plural keyword, and the # symbol are all structural. If any of them are altered, the ICU parser throws an error. When sending these strings to a translation API, the entire pattern must be parsed before segmentation so that the translator or model sees "new message" and "new messages" as the translatable segments, while {count, plural, ...} remains locked.

HTML and XML Tags

HTML and XML tags carry two risks: the tag itself can be translated (turning <strong> into <fuerte>) and the tag can be repositioned incorrectly. In right-to-left languages, the logical order of inline tags may need to change, but the nesting hierarchy must not. A <b> opened before an <i> must still close in the correct order.

Markdown Syntax

Markdown is deceptively fragile. Emphasis markers (**bold**), link syntax ([text](https://ollang.com/book-a-demo)), and code fences all rely on exact character sequences. A translated string that introduces a space between ] and ( breaks the link. Translated text inside backticks should generally not be translated at all, since it usually represents code.

JSON Structural Tokens

When translating JSON files directly, keys must never be translated, only values. Nested structures, arrays, and escape sequences (\", \n) must be preserved. Sending a raw JSON file to a translation API without first extracting translatable values is a recipe for structural corruption.

Configuring Tag-Handling Modes in Translation APIs

Most mature translation APIs offer a tag-handling parameter that instructs the engine how to treat markup. The specifics vary by provider, but the concept is consistent: you declare the format of your input so the engine can protect non-translatable structures.

How tagHandling Works Across Providers

A typical API request with tag handling enabled looks like this:

{
"text": ["<p>Welcome, <b>{username}</b>!</p>"],
"source_lang": "EN",
"target_lang": "DE",
"tag_handling": "html"
}

When tag_handling is set to html or xml, the API parses the input as markup, identifies tags, and ensures they appear in the output with correct nesting and attributes. Some APIs further allow you to specify tags whose content should not be translated at all, useful for <code>, <pre>, or custom components like <Trans>.

ProviderTag-Handling ParameterSupported FormatsNon-Translatable Marking
OllangFormat-aware pipeline with built-in tag and placeholder preservation across text, HTML, XML, Markdown, JSON, and ICU patternsHTML, XML, Markdown, JSON, ICU, XLIFFAutomatic detection plus configurable non-translatable rules
DeepLtag_handling (html, xml)HTML, XMLignoreTags parameter
Google Cloud TranslationmimeType (text/html, text/plain)HTML, plain textManual pre/post-processing
Amazon TranslateContentType (text/html, text/plain)HTML, plain textCustom terminology

Ollang's approach differs from point-solution APIs because it operates as a full execution layer: format detection, placeholder locking, translation, and quality review happen in a single pipeline rather than requiring engineers to bolt together pre-processors, API calls, and post-processors manually. For teams managing localization across software strings, website content, legal documents, and multimedia, this eliminates an entire class of integration bugs. Ollang centralizes API-first controls, QA checks, and review steps so engineering teams have a single integration point instead of brittle glue between tools.

Marking Non-Translatables and Inline Code

Beyond tag handling, you need a mechanism to mark arbitrary tokens as non-translatable. Common approaches include:

  • Wrapping in <span translate="no">: Works when the API supports HTML tag handling. The engine will preserve the content verbatim.
  • Using placeholder tokens: Replace {username} with a unique token like __PLACEHOLDER_1__ before sending, then restore it after. This is crude but reliable when the API lacks native placeholder support.
  • API-level terminology or glossary entries: Some APIs let you upload a glossary where a source term maps to itself in all target languages, effectively locking it.

A pre-processing step in Python might look like:

import re

PLACEHOLDER_PATTERN = re.compile(r'\{[a-zA-Z_]\w*\}')

def protect_placeholders(text):
mapping = {}
def replace(match):
token = f"__PH{len(mapping)}__"
mapping[token] = match.group(0)
return token
protected = PLACEHOLDER_PATTERN.sub(replace, text)
return protected, mapping

def restore_placeholders(translated, mapping):
for token, original in mapping.items():
translated = translated.replace(token, original)
return translated

This pattern works with any API, regardless of its native placeholder support. The tradeoff is that the replacement tokens themselves can occasionally be mangled by the translation engine, so choosing distinctive tokens (e.g., using Unicode private-use characters) reduces that risk.

Segmentation Strategies That Protect Structural Integrity

Avoiding Splits Inside Placeholders

Translation APIs and TMS platforms typically segment strings at sentence boundaries. The problem arises when a placeholder spans what the segmenter interprets as a sentence break. For example:

Please visit {link_start}our help center{link_end}. We're here to help.

A naive segmenter splits at the period, producing two segments, one containing {link_start} without its matching {link_end}. The result is broken markup in the translated output.

To prevent this:

  • Pre-segment manually before sending to the API. Split at safe boundaries and send each segment as a separate string in a batch request.
  • Use XLIFF or similar interchange formats that encode inline elements as <ph> or <x/> tags, which segmentation engines are designed to respect.
  • Configure segmentation rules in your TMS or API to recognize your placeholder patterns as non-breakable tokens.

Batching Strings Without Losing Context

When you batch hundreds of strings in a single API call, context loss is a real concern. A string like {count} items might be translated differently depending on whether count refers to cart items or search results. Batch requests should include context metadata where the API supports it:

{
"texts": [
{"text": "{count} items", "context": "shopping cart summary"},
{"text": "{count} items", "context": "search results count"}
]
}

Not all APIs support context fields, but those that do produce measurably better translations for ambiguous short strings.

Ready to see Ollang in action?

Talk to our team about your localization goals and see how the Ollang platform fits your workflow.

Book a Demo

Validating Outputs: Lint Rules, Schema Checks, and Round-Trip Testing

Automated Lint Rules for Placeholder Integrity

After every API response, run automated checks before the translated strings enter your build:

  • Placeholder count match: The number of {...} tokens in the source must equal the number in the target.
  • Tag nesting validation: Parse the output as HTML/XML and confirm well-formedness.
  • ICU pattern parsing: Run the translated string through an ICU MessageFormat parser. If it throws, the translation is structurally broken.
  • Regex-based checks: Verify that known patterns (URLs, email addresses, numeric format specifiers) survived unchanged.

A minimal lint check in JavaScript:

function validatePlaceholders(source, target) {
const extract = (str) => (str.match(/\{[^}]+\}/g) || []).sort();
const srcPh = extract(source);
const tgtPh = extract(target);
if (srcPh.length !== tgtPh.length) return false;
return srcPh.every((ph, i) => ph === tgtPh[i]);
}

Schema Validation for JSON Translations

If your translated output is a JSON file (e.g., i18n/de.json), validate it against the same schema as your source file. The schema should enforce:

  • Identical key sets (no missing or extra keys).
  • Value types match (strings remain strings, not objects).
  • No translated keys.

Tools like ajv can validate JSON schemas in CI, catching structural drift before it reaches production.

Round-Trip Testing with XLIFF and Bilingual Diffs

XLIFF (XML Localization Interchange File Format) is the industry-standard format for round-trip translation workflows. By exporting your strings to XLIFF, sending them through the API, and re-importing, you can diff the source and target segments structurally.

A round-trip test workflow:

  1. Export source strings to XLIFF 2.0.
  2. Send XLIFF to the translation API (or extract <source> segments, translate, and re-insert as <target>).
  3. Validate the returned XLIFF against the OASIS XLIFF 2.0 specification.
  4. Diff <source> and <target> inline elements: every <ph>, <pc>, and <mrk> in the source must have a corresponding element in the target.
  5. Re-import and render. Visually inspect a sample of screens.

This process catches issues that string-level lint rules miss, such as segment reordering that breaks cross-references.

If you want to see how Ollang automates round-trip validation and quality review across your entire localization pipeline, schedule a walkthrough with the team.

Detecting and Repairing Common Failure Modes

Braces Reordered or Duplicated

When positional placeholders like {0} and {1} are reordered, the fix depends on whether reordering is legitimate. In many languages, word order differs from English, so {1}, {0} may be correct. The check should verify that the set of placeholders is identical, not the order:

import re

def placeholders_match(source, target):
src_set = set(re.findall(r'\{\d+\}', source))
tgt_set = set(re.findall(r'\{\d+\}', target))
return src_set == tgt_set

If a placeholder is duplicated or missing, flag the string for re-translation or manual review.

Numeric Tokens Localized

Some translation engines convert ASCII digits inside placeholders to locale-specific digits. {0} becomes {Ù } in Arabic contexts. This is almost always wrong, the placeholder is a programming construct, not a displayed number. The fix is to:

  1. Mark placeholders as non-translatable before sending.
  2. Post-process the output to normalize digits inside braces back to ASCII.

import re, unicodedata

def normalize_placeholder_digits(text):
def to_ascii(match):
inner = match.group(1)
normalized = ''.join(
str(unicodedata.digit(c)) if unicodedata.category(c) == 'Nd' else c
for c in inner
)
return '{' + normalized + '}'
return re.sub(r'\{([^}]+)\}', to_ascii, text)

HTML Stripped or Attributes Translated

When an API strips HTML or translates attribute values (e.g., turning alt="logo" into alt="logotipo"), the repair strategy depends on severity:

  • Stripped tags: Re-inject tags by aligning the translated plain text against the source structure. This is fragile and best avoided by using proper tag handling in the first place.
  • Translated attributes: Post-process with an HTML parser to restore original attribute values from the source string.

The most reliable prevention is sending strings with tag_handling enabled and explicitly listing which tags and attributes are non-translatable.

Building Format Preservation into CI/CD Pipelines

Format preservation should not depend on manual review. Integrate checks into your CI/CD pipeline:

  1. Pre-commit hooks: Validate that source strings conform to expected patterns (balanced braces, valid ICU syntax, well-formed HTML).
  2. Post-translation CI step: Run lint rules and schema checks on every translated file after API calls complete.
  3. Visual regression tests: Render translated UI components and compare screenshots against baseline. Tools like Percy or Chromatic catch layout breaks caused by tag corruption.
  4. Automated re-translation triggers: If a string fails validation, automatically re-send it to the API with stricter non-translatable markers, or route it to human review.

A GitHub Actions step might look like:

- name: Validate translations
run: |
node scripts/validate-placeholders.js src/i18n/en.json src/i18n/de.json
node scripts/validate-html-tags.js src/i18n/de.json

This catches regressions before they merge, turning format preservation from a reactive fix into a proactive guarantee.

FAQ

What is the safest way to handle ICU MessageFormat strings in a translation API?

Parse the ICU pattern before sending it to the API. Extract only the translatable text segments (the human-readable parts inside plural, select, and selectordinal branches) and send those individually. Reassemble the full pattern after translation. This prevents the API from ever seeing, or modifying, the structural syntax. If your API supports ICU natively, verify with round-trip tests that nested patterns with multiple arguments survive intact.

How do I prevent a translation API from translating JSON keys?

Never send raw JSON files to a translation API. Instead, extract the translatable values into a flat list or an XLIFF file, translate those, and re-insert them into the original JSON structure. If you must send JSON directly, use an API that supports key-path-based extraction, and validate the output schema against the source to confirm no keys were altered.

Can I rely on the translation API's tag handling, or should I pre-process?

Both. Use the API's native tag handling as your first line of defense, it is optimized for the engine's behavior and reduces round-trip complexity. But always run post-processing validation. No API guarantees perfect tag preservation in every language pair and edge case. A defense-in-depth approach, API-level protection plus automated lint checks, catches the failures that either layer alone would miss. Ollang combines API-level protection with automated lint checks and built-in review steps to provide that defense-in-depth as part of the execution layer.

How do I test that placeholders survive translation across all target languages?

Implement round-trip testing using XLIFF files. Export your source strings, translate them into every target language, and programmatically verify that every placeholder in the source appears in the target. Run this as part of your CI pipeline on every translation update. Pay special attention to languages with different numeral systems (Arabic, Bengali, Thai) and right-to-left scripts, where placeholder corruption is most common.

Ship Translations That Never Break Your UI

Format preservation is not a nice-to-have, it is the difference between a localized product that works and one that crashes in production. By configuring tag-handling modes, protecting placeholders with non-translatable markers, segmenting carefully, and validating every API response with automated lint rules and round-trip tests, your team can eliminate the entire category of structural translation bugs.

Ollang's localization execution layer handles format detection, placeholder locking, translation, and quality review in a single integrated pipeline, across text, software, websites, video, audio, and legal documents. That end-to-end coverage removes brittle glue code and lets engineering teams integrate once while operations scales across content types and languages.

Ready to see Ollang in action?

Talk to our team about your localization goals and see how the Ollang platform fits your workflow.

Book a Demo

Get Started with Format-Safe Localization

See how an execution-layer approach hardens your pipeline against structural failures and UI breakage.

Book a Demo

Published on August 13, 2026