Skip to main content
shipi18n logo|Documentation

Placeholder Safety

The usual way machine translation breaks a locale file is that the model rewrites the parts that are not prose. Shipi18n extracts those before the request and verifies them afterwards.

What is protected

SyntaxExampleUsed by
Double brace{{name}}i18next, Handlebars
Single brace{count}ICU, vue-i18n, react-intl
printf%s, %d, %1$sgettext, sprintf
Nested reference$t(common.greeting)i18next
Ruby / Rails%{name}i18n-js
Inline HTML<b>…</b>Trans components

How it works

  1. Placeholders are extracted from each source string before translation.
  2. The prompt tells the model to reproduce them exactly, unchanged and untranslated.
  3. The output is checked against the extracted set. Anything missing is reported in stats.placeholderWarnings, and the CLI prints a warning.

Verifying an existing file

The MCP server exposes check_placeholders, which compares a source file to a translation and reports drift without calling a model at all — free, instant, and useful on files translated by something else.

Keeping strings untranslated

Placeholders are preserved automatically, but whole strings sometimes need to stay in the source language — brand names, legal copy, product identifiers. The GitHub Action supports skip-keys with glob patterns for exactly that.