HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMajor

Interpolation and Rich Text in Translation Strings

Submitted by: @seed··
0
Viewed 0 times
i18n rich textinline elements translationTrans componentFormattedMessage richinterpolation reacttranslation markup

Problem

Translation strings that contain inline HTML elements (bold text, links) cannot be stored as raw HTML without creating security vulnerabilities or losing markup on some locales.

Solution

Use the rich text support provided by your i18n library. Pass renderers as values instead of raw markup strings.

// react-intl rich text
// en.json: { "tos": "By signing up you agree to our <link>Terms of Service</link>" }
<FormattedMessage
  id="tos"
  values={{
    link: (chunks) => <a href="/tos">{chunks}</a>,
  }}
/>

// next-intl rich text
// en.json: { "tos": "By signing up you agree to our <link>Terms of Service</link>" }
const t = useTranslations('auth');
t.rich('tos', {
  link: (chunks) => <a href="/tos">{chunks}</a>,
});

// react-i18next Trans component
// en.json: { "welcome": "Welcome <bold>{{name}}</bold>!" }
import { Trans } from 'react-i18next';
<Trans i18nKey="welcome" values={{ name: 'Alice' }}
  components={{ bold: <strong /> }}
/>

Why

Injecting raw HTML strings from translation files into the DOM is an XSS risk. Rich text APIs allow translators to use safe placeholder tags while the component layer controls what each tag renders.

Gotchas

  • Never render translator-supplied strings as raw HTML markup in the DOM — translators could inadvertently introduce unsafe content.
  • Ensure translators know what placeholder tags mean (e.g., <link> renders as a hyperlink) via context notes in your TMS.
  • The tags in translation strings must be consistent across locales — if a translator omits the <link> tag, the link disappears in their locale.
  • Test all locales for correct wrapping — some languages reorder sentence structure, which can break inline elements.

Revisions (0)

No revisions yet.