HTML tags in i18next translation files in React HTML tags in i18next translation files in React reactjs reactjs

HTML tags in i18next translation files in React


Don't put the HTML tags in the translation. It's a bad idea anyway. Separation of concerns guys will be all whiny about it.

Use the <Trans> component if react-i18next https://react.i18next.com/latest/trans-component

Do like so:

// Component.js<Trans>Welcome, <strong>User!</strong>, here's your <strong>broom</strong></Trans>

And the corresponding translation file:

// your locales/starwars_en.js filetranslations: {  "Welcome, <1>User!</1>, here's your <3>broom</3>": "Welcome, <1>young padawan!</1>, here's your <3>light saber</3>",}

These numbers <1> and <3> will strike you as random but wait for it:

Trans.children = [  'Welcome, ',                        // index 0  '<strong>User!</strong>'            // index 1  ', please don't be ',               // index 2  '<strong>weak</strong>',            // index 3  ' unread messages. ',               // index 4]

SIDE NOTE (Can be considered a hack but saves tons of time): The guys at react.i18next.com, don't have this in their docs, but you can use the base language as a key (English in this case). It saves you time, not to double translate like they showed in their docs and I quote:

// Component fileimport React from 'react';import { Trans } from 'react-i18next'function MyComponent({ person, messages }) {  const { name } = person;  const count = messages.length;  return (    <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>  );}
// translation file"userMessagesUnread": "Hello <1>{{name}}</1>, you have {{count}} unread message. <5>Go to message</5>.","userMessagesUnread_plural": "Hello <1>{{name}}</1>, you have {{count}} unread messages.  <5>Go to messages</5>.",

Anyway "Kudos!" to the i18next team! You are awesome, guys!

Here - go nuts!


not a problem of react-i18next - you just can't add html into a react element. react will safe you from xss vulnerability and escape the content:

more detail and possible solution: https://facebook.github.io/react/tips/dangerously-set-inner-html.html

but be aware if you put user content there not escaped you open your site to xss attacks.

more secure reading the react-i18next readme: https://github.com/i18next/react-i18next#interpolate-component

which makes you split content

so the "best" solution - at least what we do - is using markdown in the translations and use eg: https://github.com/acdlite/react-remarkable to convert that to formatted content.


Since react-i18next@11.6.0, you can use tags inside your translation string and replace it with component prop in Trans component or t property from useTranslation hook:

https://react.i18next.com/latest/trans-component#alternative-usage-which-lists-the-components-v-11-6-0

Example of usage:

<Trans  i18nKey="myKey" // optional -> fallbacks to defaults if not provided  defaults="hello <italic>beautiful</italic> <bold>{{what}}</bold>" // optional defaultValue  values={{ what: 'world'}}  components={{ italic: <i />, bold: <strong /> }}/>