Internationalization with ReactJS and i18n
Tags: react, javascript, i18n, webdev
Published: 2022-07-01 23:02:49

There are a lot of languages around the world, any person should be able to understand the content of our page, the aim of internationalization is to remove the barriers to localizing or deploying an application internationally. 

## Solution
Use React i18next https://www.i18next.com/ and https://github.com/isaachinman/next-i18next to add internationalization to your React applications.


## Recipe

### For NextJS

1. Initialize your NextJS  project see https://nextjs.org/docs/getting-started documentation

2. Install the i18n package, this time as recommendation use "next-i18next"

    #### Using npm
    ```
      # npm
      $ npm install next-i18next
    ```

    #### Using yarn
    ```
      # yarn
      $ yarn add next-i18next
    ```
3. Create the next-i18next configuration file as "next-i18next.config.js" in the main folder, it might contain the locale configuration matching the one added in the next config file.
    
    ```js
    module.exports = {
      i18n: {
        locales: ["en", "es"],
        defaultLocale: "en", // default locale will fallback to 'en'
      },
    };
    ```

You need to specify the routes that next will allow, this time only English and Spanish are going to be used.

4. Configure the next config file "next.config.js", next has it own route specified in the locale value, as we already configured it in the next-i18next config file we 
only need to import it.

    ```js
    const { i18n } = require("./next-i18next.config.js");
    const nextConfig = {
      reactStrictMode: true,
      i18n,
    };

    module.exports = nextConfig;
    ```

    > for changing the language open the link referring to /en or /es
    
5. Add the wrapper component "appWithTranslation" into the app file, it allows us to use the `t` (translate) function in our components via hooks. 

    ```js
    import { appWithTranslation } from "next-i18next";

    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />;
    }

    export default appWithTranslation(MyApp);
    ```


6. Create the translation files, by default, `next-i18next` expects your translations to be organized as such:

    ```
    .
    └── public    
        └── locales
            ├── en
            |   └── common.json
            └── es
                └── common.json
    ```

    see the public > locales > en > common.js file

    ```json
    {
      "title": "i18n NextJS project",
      "spanish": "Spanish",
      "english": "English"
    }
    ```

    see the public > locales > es > common.js file

    ```json
    {
      "title": "Proyecto i18n NextJS",
      "spanish": "Español",
      "english": "Ingles"
    }
    ```

7. Then we add "serverSideTranslation" to [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) or [getServerSideProps](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) (depending on your case) in our page-level components. In this case we will use the "serverSideTranslation" one.

    ```js
    import { serverSideTranslations } from "next-i18next/serverSideTranslations";

    export async function getStaticProps({ locale }) {
      return {
        props: {
          ...(await serverSideTranslations(locale, ["common"])), //['common', 'other'] if more files are needed
          // Will be passed to the page component as props
        },
      };
    }
    ```

    >This code need to be added in every file using the translations.
   
5. Start using the translations by first importing the next-i18next package in the desired component

    ```js
    import { useTranslation } from "next-i18next";
    ```
    Then create the const inside the respective component where the text will be translated
    ```js
    const { t } = useTranslation("common");
    ```
    And this is how the translation is being used
    ```jsx
    {t("title")}
    ```

    see a sample Home file:

    ```jsx
    import Head from "next/head";
    import styles from "../styles/Home.module.css";

    import { serverSideTranslations } from "next-i18next/serverSideTranslations";
    import { useTranslation } from "next-i18next";

    const Home = () => {
      const { t } = useTranslation("common");
      return (
        <div className={styles.container}>
          <Head>
            <title>i18n NextJS project</title>
            <meta name="description" content="Generated by create next app" />
            <link rel="icon" href="/favicon.ico" />
          </Head>

          <main className={styles.main}>
            <h1 className={styles.title}>{t("title")}</h1>

            <div className={styles.grid}>
              <a href="/en" className={styles.card}>
                <p>{t("english")}</p>
              </a>

              <a href="/es" className={styles.card}>
                <p>{t("spanish")}</p>
              </a>
            </div>
          </main>
        </div>
      );
    };

    export async function getStaticProps({ locale }) {
      return {
        props: {
          ...(await serverSideTranslations(locale, ["common"])),
          // Will be passed to the page component as props
        },
      };
    }

    export default Home;
    ```

Feel free to check this [codesanbox.io project](https://codesandbox.io/s/next-i18next-project-nhxdd3)
  
### For React.js

1. Create your react project 

2. Install the i18n required packages
    #### Using npm
    ```
      # npm
      $ npm install i18next --save
      $ npm install react-i18next i18next --save
      npm install i18next-browser-languagedetector
    ```

    #### Using yarn
    ```
      # yarn
      $ yarn add i18next
      $ yarn add react-i18next
      $ yarn add i18next-browser-languagedetector
    ```

2. Create the translation file, it contains the languages and configuration, recommend to create a folder called "i18n" and inside a JS file called "i18n.js"

    ```js
    import i18n from "i18next";
    import { initReactI18next } from "react-i18next";
    import LanguageDetector from "i18next-browser-languagedetector";

    i18n
      // detect user language
      // learn more: https://github.com/i18next/i18next-browser-languageDetector
      .use(LanguageDetector)
      // pass the i18n instance to react-i18next.
      .use(initReactI18next)
      // init i18next
      // for all options read: https://www.i18next.com/overview/configuration-options
      .init({
        debug: true,
        fallbackLng: "en",
        interpolation: {
          escapeValue: false, // not needed for react as it escapes by default
        },
        resources: {
          en: {
            translation: {
              title: "i18n React project",
              english: "English",
              spanish: "Spanish",
            },
          },
          es: {
            translation: {
              title: "Proyecto i18n en React",
              english: "Ingles",
              spanish: "Español",
            },
          },
        },
      });

    export default i18n;
    
    ```

4. Import the i18n.js file to the index.js file
    ```js
    import "./i18n/i18n";
    ```
   
5. Start using the translations by first importing the react-i18next package in the desired component
    ```js
    import { useTranslation } from 'react-i18next'
    ```
    Then create the const inside the respective component where the text will be translated
    ```js
     const { t } = useTranslation()
    ```
    And this is how the translation is being used

    ```jsx
      {t(title)}
    ```

6. Finally Configure the changelanguage function at app.js component

    First get thi18n element from useTranslation

    ```js
    const { t, i18n } = useTranslation(); // we used the t before
    ```

    now we can change the language bt using the changelanguage function:

    ```js
    <button onClick={() => i18n.changeLanguage("en")} className="App-link">
      {t("english")}
    </button>
    <button onClick={() => i18n.changeLanguage("es")} className="App-link">
      {t("spanish")}
    </button>
    ```

Feel free to check this [codesanbox.io project](https://codesandbox.io/s/i18n-react-5t3vxk)