Search code examples
reactjsi18nextreact-intlreact-i18next

react-i18next and replacing placeholder keys with components


Previously I was using react-intl and was able to set placeholders for items which would be replaced with components, e.g. {br} with <br />.

I'm currently getting errors when using react-i18next and i18next-icu where I'm trying to do:

// Using Intl format (via i18next-icu)
{
  "test": "Replace with a{br}line-break. {button}"
}
t("test", { br: <br />, button: <button>Click me!</button> });
// Outputted translated text
Replace with a[object Object]line-break. [object Object]

Is it actually possible to do this using i18next/i18next-icu ? If not, what would be another method to insert components into the translated string?


Solution

  • You need to configure react i18next like this in your i18n.js to support basic tags:

    import i18n from "i18next";
    import LanguageDetector from "i18next-browser-languagedetector";
    import { initReactI18next } from "react-i18next";
    
    i18n
        .use(LanguageDetector)
        .use(initReactI18next)
        .init({
            fallbackLng: "en",
            react: {
                // https://react.i18next.com/latest/trans-component#trans-props
                transSupportBasicHtmlNodes: true,
                transKeepBasicHtmlNodesFor: ["br", "strong", "b", "i"],
            }
        });
    
    export default i18n;
    

    Then you can as @jamuhl said use the component like this:

    const keyInTranslationJsonFile=`My text that can be <b>{{boldPlaceholder}}</b>`;
    <Trans i18nKey={keyInTranslationJsonFile}>{{boldPlaceholder: "bold"}}</Trans>
    

    I just noticed that it's not possible to alert a Trans component. As far as I know you cannot make something bold with the t() function or use any tags. But you can still use normal placeholders at least.

    Like this:

    const keyInTranslationJsonFile=`You've selected the max of {{selectLimit}} elements`;
    alert(
        t(keyInTranslationJsonFile, {
            selectLimit: selectLimit,
        })
    );