Skip to main content

Interpolation

localize-react uses literal {{double-mustache}} tokens for substitutions.

const messages = { en: { hello: 'Hi {{name}}, you have {{count}} new mail.' } };

translate('hello', { name: 'Alex', count: 3 });
// → "Hi Alex, you have 3 new mail."

What's a valid token?

The pattern is /\{\{([^{}]+)\}\}/g — anything between {{ and }} that doesn't itself contain a brace.

InputToken?
{{name}}
{{ name }}✅ (key is name — note the spaces)
{{a.b.c}}✅ (key is the literal string a.b.c)
{{{a}}}Only {{a}} matches. The outer braces stay.
{name}

Prefer simple, unspaced keys: {{name}}, {{count}}, {{total}}.

Values

values is a Record<string, string | number>. Numbers are coerced via String() at render time. Anything else is a type error.

translate('cart.summary', { count: 3 }); // ok
translate('cart.summary', { count: '3' }); // ok
translate('cart.summary', { count: true }); // ❌ type error
translate('cart.summary', { count: null }); // ❌ type error

That keeps the rendered output predictable.

Regex-meta safety

Interpolation uses String.prototype.replaceAll(token, value) — a literal replacement, not new RegExp(token).replace(...). So values containing regex meta-characters ($&, $1, etc.) render as-is, with no surprise expansion:

translate('out', { x: '$&' }, '{{x}}');
// → "$&" (not the entire matched substring)

Missing values

If a {{token}} appears in the resolved string but no matching key is in values, the token is kept verbatim and a console.warn is logged:

[LOCALIZE-REACT] Looks like template is being used, but no value passed for {{name}}

That's intentional — silent identity replacement masks bugs.

Memoization caveat

The internal cache key includes JSON.stringify(values). If your values object has stable shape and ordering, cache hits will be common. If you pass freshly-allocated values with random ordering on every render, you'll miss the cache (but it stays correct — never wrong, just slower).