i18next React – links inside translations

December 22, 2022
Last update: May 29, 2025
3 min read
1666
0
0
i18next React – links inside translations

CHALLENGE: add dynamic translation to links in React

SOLUTION: use the LinkText component and the Trans Component from the i18next library

This article has been reviewed and updated in August 2024 to make it up to date.

react-i18next is probably the most popular NPM package for translating a React application. It’s downloaded over 1 million times every week. I18next as internationalization-framework is really a complete solution for making a multi-language app: it can detect user language, cache translations, add post-processing (sprinf support) or load files on demand.

Problem with i18next translation

As awesome as it is, it does not provide an easy way for translating phrases with variables inside. Let’s say we have a Privacy Policy text with two url values inside the text. The naive approach will be to hardcode urls for pages in every available json translation file.

The documentation doesn’t really provide a better solution. There is something like replacement tags, but the suggestion is to use the React Developer Tool to inspect an element and find out what node number is assigned to the word ( https://react.i18next.com/latest/trans-component#how-to-get-the-correct-translation-string ). In this article, we will describe how to do it better / easier.

React-i18next use variables in translations

We have a privacy policy text that is displayed in the registration form. It includes 2 external links. We would like to pass those as variables to the main translation. This way, we will maintain a separation between i18n link constants and different translations of texts.

I agree to the Privacy Policy and Terms and Conditions

This solution provides a universal way to pass dynamic variables to internationalized strings. Your code will be cleaner and more readable.

See also  WordPress customization - CREATE IT OUTSIDE THE BOX

Trans and LinkText component

Pure component LinkText uses props.children to put a text node label between opening and closing A Link tag. You can also pass other arguments, like: title or rel=”nofollow”.

Here is the entire trick to have a translation that uses predefined variables passed to the Trans component:

<Trans
    i18nKey="gdpr_policy_links"
    components={{
        link1: <LinkText to={link1} title="My link1" />,
        link2: <LinkText to={link2} title="Another link" />
    }}
/>

and the definition of the LinkText component:

export const LinkText = (props) => {
    return (
        <a href={props.to || '#'} target="_blank" title={props.title || ''}>
            {props.children}
        </a>
    );
};
Preview

Now, let’s start from the beginning and let’s prepare a fully working example. The first step is to install the following dependency:

npm install react-i18next

Import i18n config:

// index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './i18n/config';
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Add a standard config file:

// src/i18n/config.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
    fallbackLng: 'en',
    lng: 'en',
    resources: {
        en: {
            translations: require('./locales/en/translations.json')
        },
    },
    ns: ['translations'],
    defaultNS: 'translations'
});
i18n.languages = ['en'];
export default i18n;

Add a json file with the translation to: src/i18n/locales/en/translations.json

{
  "gdpr_policy_links": "I agree to <link1>Privacy Policy</link1> and <link2>Terms and Conditions</link2>",
  "gdpr_required_msg": "Please accept Privacy Policy"
}

The Main app with the Register Form and predefined links:

// src/App.jsx
import React from 'react';
import './App.css';
import {RegisterForm} from "./RegisterForm";
const LINK1 = 'https://www.example1.com';
const LINK2 = 'https://www.example2.com';
function App() {
    return (
        <div className="App">
            <RegisterForm link1={LINK1} link2={LINK2} />
        </div>
    );
}
export default App;

Here is an example of how to display translations using i18next. For advanced translations with a link, we’re using the Trans component that is provided by react-i18next:

// RegisterForm.jsx
import React from 'react';
import {Trans, useTranslation} from 'react-i18next'
import {LinkText} from './LinkText';
export const RegisterForm = (props) => {
    const {link1, link2} = props;
    const {t} = useTranslation();
    return (
       <>
            <h3>Standard translation</h3>
            {t('gdpr_required_msg')}
            <h3>Translation with variables</h3>
            <Trans
                i18nKey="gdpr_policy_links"
                components={{
                    link1: <LinkText to={link1} title="My link1" />,
                    link2: <LinkText to={link2} title="Another link" />
                }}
            />
        </>
    );
}

The last piece of the puzzle will be the LinkText component to apply links in the translation text:

// LinkText.jsx
import React from 'react';
export const LinkText = (props) => {
    return (
        <a href={props.to || '#'} target="_blank" title={props.title || ''}>
            {props.children}
        </a>
    );
};
Animated preview

That’s it for today’s tutorial. Make sure to follow us for other tips and guidelines and don’t forget to sign up for our newsletter.

See also  Google Analytics 4 vs Universal Analytics – what’s new?

Do you need someone to implement this i18next solution for you? You may need help from our experienced developers – check our software outsourcing and custom web development pages!

Support – Tips and Tricks
All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

Contact us