Localizely logo
  • Home
  • Getting started
  • How it works
  • Pricing
  • FAQ
Sign up

I18n questions · React

How do I pass variables into an i18next translation? 

Mark the variable with double curly braces in the resource and pass the value in the second argument of t; dot notation reaches into objects:

{
  "welcome": "Hello {{name}}",
  "author": "Written by {{author.name}}"
}
const { t } = useTranslation();

t('welcome', { name: 'Ana' });            // Hello Ana
t('author', { author: { name: 'Ana' } }); // Written by Ana

By default i18next HTML-escapes every interpolated value (escapeValue: true) to prevent XSS where the result is injected with innerHTML. React already escapes what it renders, so with react-i18next turn this off in init; otherwise a value such as Tom & Jerry shows up as Tom & Jerry:

i18n.use(initReactI18next).init({
  interpolation: { escapeValue: false },
});

If you keep escaping on, {{- name}} disables it for a single placeholder. With escaping off, never pass unchecked user input into nesting options; the interpolation docs explain that injection path.

Nesting reuses another key inside a string with $t(key), which is handy for product names and glossary terms:

{
  "product": "Acme Notes",
  "signIn": "Sign in to $t(product)"
}

Do not format numbers and dates before passing them. Since i18next 21.3 the built-in formatters based on Intl do it per language, with options in parentheses or in formatParams:

{
  "total": "Total {{amount, currency(EUR)}}",
  "updated": "Updated on {{date, datetime}}",
  "rating": "{{score, number(maximumFractionDigits: 1)}} out of 5"
}
t('total', { amount: 1234.5 });              // de: Total 1.234,50 €
t('updated', { date: new Date(2026, 9, 9) }); // de: Updated on 9.10.2026

relativetime and list exist as well. Custom formats are registered with i18n.services.formatter.add(name, fn) after init; the old interpolation.format callback was removed in i18next 26.

Plurals are driven by a variable too: pass count and provide one key per CLDR plural category using the JSON v4 suffixes:

{
  "inbox_one": "You have {{count}} new message",
  "inbox_other": "You have {{count}} new messages"
}

t('inbox', { count: 3 }) selects the form through Intl.PluralRules, which i18next requires since v24 (React Native on Hermes needs a polyfill). Languages such as Arabic, Russian or Polish also need _zero, _two, _few or _many; Language plural rules lists the categories per language. compatibilityJSON: 'v3', which kept old _plural keys working, is gone since v24.

Interpolation only produces strings. To put a link or <strong> into the sentence you need the Trans component instead; How to add HTML tags to a localization message in React? covers rich text in messages. The react-intl counterpart, ICU {name} placeholders with formatMessage, is in How to use dynamic strings in a localization message in React?.

Published Oct 9, 2026 · Markdown version

Related React internationalization questions:

React internationalization tutorial:

Learn about internationalization in React
Localizely logo
About
Free tools
Boring stuff
  • Privacy Policy
  • Terms of Service
  • Cookie Policy
Newsletter
Copyrights 2026 © Localizely