react-i18next: interpolation of link in HTML tag in the middle of the text react-i18next: interpolation of link in HTML tag in the middle of the text reactjs reactjs

react-i18next: interpolation of link in HTML tag in the middle of the text


With react-i18next v4.4.0 we introduced a new component Trans:

<Trans i18nKey="optionalKey">See the <Link to="/more">description</Link> below.</Trans>

The json would be: See the <1>description</1> below.

or even more complex:

<Trans i18nKey="userMessagesUnread" count={count}>Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.</Trans>

The new feature is documented here: https://react.i18next.com/latest/trans-component


This is the common problem of react-intl and react-i18next - both libs have very limited support of inline components and rich-text formatting inside translations (I've already described it here with more details).

If you're still at the beginning of your project, you might want to consider different i18n library - js-lingui (disclaimer: I'm the author). It's the first (and so far the only) library with full support for inline components.

You simply write:

<Trans>See the <Link to="/more">description</Link> below.</Trans>

and your translators will work with message See the <0>description</0> below.

The only price is you need to use extra babel plugin, which makes it possible.


<Interpolate i18nKey="my-label" useDangerouslySetInnerHTML link={url} /> was added a few weeks ago and does allow inserting such translations containing html fragments - just be aware this is dangerous if url comes from userinput and contains malicious code (xss attack)

As i see this was added last year: https://github.com/i18next/react-i18next/pull/195/files

But this will wrap per default a span around every part before/after {{link}} so that might not be what you need...but the solution is rather simple - do not use interpolate component but regular interpolation on the t function:

<div dangerouslySetInnerHTML={t('my-label', { link: yourURL }} />