5

My React app uses next-i18next package. I'd like to put some React component inside my interpolation:

import React from 'react';
import { useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

export default function Review({ text, author }) {
  const { t } = useTranslation('reviews');

  return (
    <article>
      <p>{text}</p>
      <footer>
        {t('footer', { author: <a href={author.url}>{author.name}</a> })}
      </footer>
    </article>
  );
}

export const getStaticProps = async ({ locale }) => ({
  props: {
    ...await serverSideTranslations(locale, ['reviews']),
  }
});

And reviews.json:

{
    "footer": "By {{author}}, all rights reserved"
}

Trying to use JSX element to fill the interpolation doesn't work as expected. The result I'm getting is:

By [object Object], all rights reserved

I also tried with unescaped interpolation with By {{- author}}, all rights reserved, but it ends up being the same result.

Can I use JSX element to fill my interpolation?

Robo Robok
  • 21,132
  • 17
  • 68
  • 126

1 Answers1

6

You can't use t function in order to inject jsx.

There is a special Trans component for this, you should use it.

import React from 'react';
import { useTranslation, Trans } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

export default function Review({ text, author }) {
  const { t } = useTranslation('reviews');

  return (
    <article>
      <p>{text}</p>
      <footer>
        <Trans
          i18nKey="footer"
          t={t}
          values={{ author }}
          components={{ authorLink: <a href={author.url}>placeholder</a> }}
        />
      </footer>
    </article>
  );
}

export const getStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ['reviews'])),
  },
});

When in your translation file you will have:

{
  "footer": "My footer text <authorLink>{{author.name}}</authorLink>"
}
felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • Thanks. Is there a way to get rid of the tag from my translation file? Why would I want the translation key to know that's a tag? That's why I didn't want to use the Trans component. Translate files should only have raw placeholders, not the hints of the type of the content. – Robo Robok Mar 25 '21 at 09:44
  • This is how react-i18next works with jsx, there is other option, instead of passing an object to `components` pass an array, and still use <0>0>, <1>1> inside translation file – felixmosh Mar 25 '21 at 09:55
  • Think of this, it must be part of the translations, since in some languages you need to wrap more text with inside the link, (the part of the link may be different in different languages) – felixmosh Mar 25 '21 at 09:56
  • What do you mean? What would I put instead of `{{author.name}}` in some languages? – Robo Robok Mar 25 '21 at 11:58
  • Maybe in some languages, there is some special prefix for author names – felixmosh Mar 25 '21 at 14:25
  • I don't understand what you're saying. What prefix? What does it have to do with the tags? I'm talking about the necessity of putting pseudo-html to my translation keys. Every other translation tool uses pure placeholders. If I want to put HTML there, I'd do it as a translation VALUE, without letting the key know about it. I still don't understand why next-i18next wants me to put my translation implementation hint in the key. – Robo Robok Mar 25 '21 at 14:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/230390/discussion-between-robo-robok-and-felixmosh). – Robo Robok Mar 25 '21 at 22:04
  • Just answered you on chat. – Robo Robok Mar 31 '21 at 07:51
  • I've answered your question there – felixmosh Mar 31 '21 at 08:54