Arkian logo
Start free
Menu
← All articles

Translation Placeholders: Small Teams Catch Broken Tokens in CI

Translation Placeholders: Small Teams Catch Broken Tokens in CI

Engineer reviewing translated message placeholders

Placeholders in translations are non-translatable variables or markup that the app fills in at runtime, so you must never translate or alter the token itself. Translators may move a placeholder to fit target-language grammar, but only the surrounding words change. Use a standardized format such as MessageFormat 2 or ICU to avoid mixed syntaxes and reduce runtime errors caused by mismatched plural categories or incorrectly ordered variables, as MessageFormat guidance explains.


TL;DR:

  • Keep every placeholder and markup token character for character; translators may move supported tokens to fit grammar, but must never alter their contents.
  • Use named or numbered placeholders and plural aware selectors, rather than hand built singular and plural strings, to preserve argument mapping across languages.
  • Run token comparison checks in CI on translation changes, then test rendered locales with zero, one, and large counts to catch runtime formatting errors.
  • Adopt MessageFormat 2 or ICU to standardize variable declarations, plural rules, and locale aware date and time formatting across platforms, reducing syntax mismatches.

Arkian
Keep Localization Workflows Organized
Arkian automates multilingual scripts, voice outputs, validation, and packaging, helping small teams organize localization without complex translation management systems.

Table of Contents

What are placeholders and why do they matter in localization?

A placeholder marks a spot where your code inserts a value after the string is loaded. The translator sees Welcome back, {name}, and the app swaps in “Dana” when it renders. The text around the token gets translated; the token does not.

Typical uses include:

  • People and objects: usernames, product names, account labels.
  • Dates and times: values formatted by the runtime for the user’s locale.
  • Counts: item totals that also drive plural forms.
  • Links and markup: wrappers that turn part of a sentence into a link or bold text.
  • Formatted numbers: prices, percentages, file sizes.

When a translation corrupts a token, the damage is visible. A renamed variable can raise a runtime exception, a missing one drops data from the screen, and a mangled tag breaks the layout or shows raw code to users. Because these failures only appear after the string is loaded in a specific language, they often slip past review.

Which placeholder syntaxes will you run into?

Projects rarely use one style, so developers and translators should be able to recognize each family on sight.

  • Printf-style: %s, %d and numbered forms like %1$s. Numbered tokens matter because they let a translator reorder arguments without breaking the mapping to values.
  • Named placeholders: {name}, {$name} and %(name)s. Names signal what content is expected, which is why many localization guides describe developers naming variables for clarity.
  • Tag-style and double-brace: {{strong}}text{{/strong}} and HTML or XML-like tags that wrap translatable words.
  • Template-engine forms: <%= student_name %> and similar server-side tokens.
  • Project-specific tokens: custom markers your own build step expands.

The Open edX translator guide lists common placeholder forms such as {student_name}, %(student_name)s and <%= student_name %>, and gives one shared rule for all of them: leave them exactly as written.

How do placeholders differ from formatting tags?

A placeholder is functional: it stands for data or behavior. A formatting tag is presentational: it wraps text to style or link it. Both must survive translation, but they behave differently around the words they touch.

A quick test: if removing the token changes what data appears, it is a placeholder. If removing it only changes how text looks, it is markup. In Click {{link}}here{{/link}} to continue, the paired tokens are non-translatable wrappers, while “here” is translatable text that sits between them. The wrappers stay character for character; the words inside get translated.

Some tags enclose only formatting with no words to translate, such as a line break or icon. Treat those as fully locked.

To keep translators from damaging structure, we recommend a few workflow habits:

  • Show tokens as protected, non-editable chips in the translator editor where your tooling allows it.
  • Warn on save when a token present in the source is missing from the target. Translation platforms commonly require the exact same tag or placeholder in the translation and surface the list of placeholders to the translator.
  • Never split a paired tag so that one half lands in a different clause without the other.

How do you handle reordering, plurals, and moved placeholders?

Languages order subjects, objects and greetings differently, so a translation may need to move a token. That is allowed. In MessageFormat 2, the placeholder {$name} is non-translatable but may be moved, as long as the braces and function names stay correct.

Follow these steps to keep moves and plurals safe:

  1. Prefer named or numbered tokens. Numbered placeholders such as %1$s can help translators reorder arguments while preserving their mapping to values, as localization guidance describes.
  2. Keep each token intact. Move the whole token, never its punctuation, spacing or capitalization.
  3. Use plural-aware constructs. Do not write “{count} item” and “{count} items” as hand-built variants around a number. Use selectors so each language gets its own plural categories. MessageFormat 2 supports pluralization using ECMA-402 Intl.PluralRules to match the correct forms.
  4. Test both orders. A name-first English line ({name} sent you a message) may become greeting-first in another language (Message from {name}). Both are valid when the token is untouched.
  5. Check the zero, one and many cases with real counts, since some languages have more plural categories than English.

How do you prepare strings and validate placeholders before release?

Good validation starts before translation. Declare every variable and give translators the context they need, then automate the checks so no one has to catch errors by eye.

  • Declare variables and add notes. For each string, list its placeholders, what each one holds, and an example value.
  • Run a placeholder-presence check in CI. Extract the token list from the source and from each translation, then fail the build when the sets differ. Our walkthrough of a CI-ready batch translation workflow shows how to keep plurals and placeholders intact at scale. If you also automate other release checks, this partner guide on CI/CD automation covers the pipeline side.
  • Smoke-test at runtime. Render each locale with representative data, including counts of 0, 1 and large numbers, to catch formatting and plural-rule mismatches that static checks miss.
  • Expose a visible placeholder list in the translator interface so people see what must be preserved.
  • Check ICU-specific pitfalls. Our ICU message format checks cover what to verify before shipping.

Pro Tip: Run the token-comparison check on the pull request that adds the translation, not on the release branch, so a broken placeholder is fixed while the context is still fresh.

Why do MessageFormat 2, ICU, and CLDR reduce placeholder errors?

Ad-hoc placeholders grow messy: one file mixes %s, {name} and custom tags, and each needs its own handling. MessageFormat 2 addresses this by separating translatable message text from functional declarations. Inputs and variables are declared explicitly, for example .input {$count :number}, so translators can reorder placeholders while the functional parts stay untouched.

It also supports pluralization and date and time formatting that adapt to the target locale, which reduces the need for hard-coded or hacked placeholder strings. The Quick Start guide describes placeholders in curly braces, with functions prefixed by : to format values, and recommends markup tags and selectors so the application controls rendering while translations focus on wording.

MessageFormat 2 supports pluralization and date and time formatting that adapt to the target locale, reducing the need for hard-coded strings.

The practical payoff is consistency. Migrating to a standardized format gives your team one way to handle placeholders, variables and plurals across platforms. It eliminates many runtime errors caused by mismatched plural categories or incorrectly ordered variables, and it gives validation tools a single syntax to parse.

Why do MessageFormat 2, ICU, and CLDR reduce placeholder errors? — overview diagram

What is our checklist before shipping a localized build?

Our view: most placeholder bugs are process bugs, not translator mistakes. The checklist we use is short. Declare every variable, enforce token checks in CI, test with sample runtime data, and attach translator notes to anything ambiguous. For new projects, start on a standardized message format; for existing ones, migrate the strings that carry counts and gender first, since those fail most visibly. Our own batch translation practice supports localization production before anyone reviews wording.

— Arkian

How do we keep your placeholders intact and package validated language files?

We built our platform for small teams that want localization without repository access or a full translation management system. We deliver structured language packages ready to review and release.

Arkian

Next step: check our plans and pricing and start with the localization strings service.

FAQ

What is an example of a placeholder?

In Hello, {name}!, the token {name} is a placeholder. The app replaces it with a real value, such as a username, when the string is displayed. A translator changes “Hello” but leaves {name} exactly as written.

What does “placeholder” mean in translation?

A placeholder is a token that stands in for a value or markup inserted at runtime. It is not translatable text. Translator guidance says to not translate or alter placeholders, while allowing them to be reordered for grammar.

Can I move a placeholder in a translation?

Yes, when the format supports it. Named and numbered tokens can be repositioned to match the target language, as long as the token itself, including its braces, punctuation and spacing, stays unchanged.

How do I check that translations kept their placeholders?

Compare the token list from the source string with each translated string and fail the build on any difference. Follow that with a runtime test using sample data, so plural and formatting mismatches also surface before release.

Sources