Internationalization (i18n)

MDB integration with i18n for React

This article will teach you how to integrate i18n with your project. You can start using directional classes with the latest Bootstrap 5.

Lets see how to integrate internationalization (i18n) with MDB 5 across our layout, components, and utilities.

Live preview

Prerequisites

Before starting the project make sure to install the following utilities:


Creating a new project

First, we need to create a new Vite project.

Step 1

Init the project and choose vue framework. You can add a name for your project as we did in example below

        
            
      npx create-react-app my-react-app
    
        
    

Step 2

Navigate to app's directory.

        
            
        cd my-react-app
    
        
    

Step 3

Setup MDB.

        
            
      npm i mdb-react-ui-kit
    
        
    

Font Awesome

Install Font Awesome.

        
            
        npm i @fortawesome/fontawesome-free
      
        
    

Step 4

Add the following lines in your index.js file before the App.js file import:

        
            
      import 'mdb-react-ui-kit/dist/css/mdb.min.css';
      import "@fortawesome/fontawesome-free/css/all.min.css";
    
        
    

Step 5

Import Font Awesome and Roboto font. Add the following lines in public/index.html file inside head section:

        
            
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet" />
        <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,900&display=swap" rel="stylesheet" />
    
        
    

Step 6

Launch the application.

        
            
      npm start
    
        
    

Installation

Once we have managed to launch our project, we have to add i18next and react-i18next package.

Step 1

Navigate to your project and in your terminal run:

        
            
      npm install react-i18next i18next --save
    
        
    

Step 2

Create locales folder inside your src and create new json files with translations

        
            
    {
      "language": "English",
      "date": "Date",
      "question": "Please select a language",
      "search": "Search",
      "news1": "Some news",
      "news2": "Another news",
      "profile": "My profile",
      "profileSettings": "Settings",
      "profileLogout": "Logout",
      "accordion1": "Item - One",
      "accordion2": "Item - Two",
      "accordion3": "Item - Three",
      "accordionTxt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae magna lacus. Fusce pretium urna id tellus ornare sagittis. Sed ac sagittis nibh, nec vehicula dolor. Cras et posuere mi",
      "maskText": "Can you see me?",
      "slide1Label": "First slide label",
      "slide2Label": "Second slide label",
      "slide3Label": "Third slide label",
      "slide1Description": "English - Nulla vitae elit libero, a pharetra augue mollis interdum.",
      "slide2Description": "English - Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
      "slide3Description": "English - Praesent commodo cursus magna, vel scelerisque nisl consectetur."
    }
    
        
    
        
            
    {
      "language": "Polski",
      "date": "Data",
      "question": "Prosze wybrać język",
      "search": "Wyszukaj",
      "news1": "Wiadomości",
      "news2": "Inne wiadomości",
      "profile": "Mój profil",
      "profileSettings": "Ustawienia",
      "profileLogout": "Wyloguj",
      "accordion1": "Przedmiot - Jeden",
      "accordion2": "Przedmiot - Dwa",
      "accordion3": "Przedmiot - Trzy",
      "accordionTxt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae magna lacus. Fusce pretium urna id tellus ornare sagittis. Sed ac sagittis nibh, nec vehicula dolor. Cras et posuere mi",
      "maskText": "Czy mnie widzisz?",
      "slide1Label": "Etykieta pierwszego slajdu",
      "slide2Label": "Etykieta drugiego slajdu",
      "slide3Label": "Etykieta trzeciego slajdu",
      "slide1Description": "Polski - Nulla vitae elit libero, a pharetra augue mollis interdum.",
      "slide2Description": "Polski - Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
      "slide3Description": "Polski - Praesent commodo cursus magna, vel scelerisque nisl consectetur."
    }
    
        
    
        
            
    {
      "language": "日本語",
      "date": "日にち",
      "question": "言語を選択してください",
      "search": "サーチ",
      "news1": "ニュース",
      "news2": "別のニュース",
      "profile": "プロフィール",
      "profileSettings": "セッティング",
      "profileLogout": "ログアウト",
      "accordion1": "アイテム - 1",
      "accordion2": "アイテム - 2",
      "accordion3": "アイテム - 3",
      "accordionTxt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae magna lacus. Fusce pretium urna id tellus ornare sagittis. Sed ac sagittis nibh, nec vehicula dolor. Cras et posuere mi",
      "maskText": "私がみえますか?",
      "slide1Label": "1 枚目のスライド ラベル",
      "slide2Label": "2 番目のスライド ラベル",
      "slide3Label": "3 番目のスライド ラベル",
      "slide1Description": "日本語 - Nulla vitae elit libero, a pharetra augue mollis interdum.",
      "slide2Description": "日本語 - Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
      "slide3Description": "日本語 - Praesent commodo cursus magna, vel scelerisque nisl consectetur."
    }
    
        
    
        
            
    {
      "language": "Deutsch",
      "date": "Datum",
      "question": "Bitte wähle eine Sprache",
      "search": "Suchen",
      "news1": "Nachrichten",
      "news2": "Andere Nachrichten",
      "profile": "Mein Profil",
      "profileSettings": "Einstellungen",
      "profileLogout": "Ausloggen",
      "accordion1": "Post - Ein",
      "accordion2": "Post - Zwei",
      "accordion3": "Post - Drei",
      "accordionTxt": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae magna lacus. Fusce pretium urna id tellus ornare sagittis. Sed ac sagittis nibh, nec vehicula dolor. Cras et posuere mi",
      "maskText": "Können Sie mich sehen?",
      "slide1Label": "Etikett des ersten Objektträgers",
      "slide2Label": "Etikett des zweiten Objektträgers",
      "slide3Label": "Etikett des dritten Objektträgers",
      "slide1Description": "Deutsch - Nulla vitae elit libero, a pharetra augue mollis interdum.",
      "slide2Description": "Deutsch - Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
      "slide3Description": "Deutsch - Praesent commodo cursus magna, vel scelerisque nisl consectetur."
    }
    
        
    

Step 3

Prepare i18n.js file:

        
            
      import i18n from "i18next";
      import { initReactI18next } from "react-i18next";

      import en from "./locales/en.json";
      import pl from "./locales/pl.json";
      import ja from "./locales/ja.json";
      import de from "./locales/de.json";

      i18n
        // 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: en,
            },
            pl: {
              translation: pl,
            },
            ja: {
              translation: ja,
            },
            de: {
              translation: de,
            },
          },
        });

      export default i18n;
    
        
    

Step 4

Let's import that file somewhere in our index.js file:

        
            
      import React from 'react';
      import { createRoot } from 'react-dom/client';
      import './index.css';
      import App from './App';
      import 'mdb-react-ui-kit/dist/css/mdb.min.css';

      // import i18n (needs to be bundled ;))
      import './i18n';

      const root = createRoot(document.getElementById('root'))
      root.render(
        <React.StrictMode>
          <App />
        </React.StrictMode>
      );
    
        
    

Adding new content

After we go through all the previous steps, we can start developing our application. Let's change the content of App.js so that we can check if the app is working properly.

You can try some example we have prepared for you. Just copy the code below.

        
            
        import "./App.css";
        import { useTranslation } from "react-i18next";
        import {
          MDBContainer,
          MDBNavbar,
          MDBDropdownMenu,
          MDBDropdownItem,
          MDBInput,
          MDBIcon,
          MDBDropdown,
          MDBDropdownToggle,
          MDBBadge,
          MDBCol,
          MDBFooter,
          MDBRow,
          MDBCarouselItem,
          MDBCarousel,
          MDBAccordion,
          MDBAccordionItem,
        } from "mdb-react-ui-kit";
        import { useState } from "react";
        
        function App() {
          const { t, i18n } = useTranslation();
          const [pickedLanguage, setPickedLanguage] = useState("united-kingdom");
        
          return (
            <div className="App">
              <MDBNavbar light expand="lg" bgColor="light">
                <MDBContainer fluid>
                  <form className="d-none d-md-flex input-group w-auto my-auto">
                    <MDBInput label={t("search")} />
                    <span className="input-group-text border-0">
                      <MDBIcon icon="search" />
                    </span>
                  </form>
        
                  <div className="navbar-nav ms-auto d-flex flex-row">
                    <MDBDropdown>
                      <MDBDropdownToggle
                        style={{ cursor: "pointer" }}
                        tag="a"
                        className="nav-link"
                      >
                        <MDBIcon icon="bell" />
                        <MDBBadge notification color="danger" pill>
                          1
                        </MDBBadge>
                      </MDBDropdownToggle>
                      <MDBDropdownMenu>
                        <MDBDropdownItem link>Action</MDBDropdownItem>
                        <MDBDropdownItem link>Another action</MDBDropdownItem>
                        <MDBDropdownItem link>Something else here</MDBDropdownItem>
                      </MDBDropdownMenu>
                    </MDBDropdown>
                    <MDBDropdown>
                      <MDBDropdownToggle
                        style={{ cursor: "pointer" }}
                        tag="a"
                        className="nav-link"
                      >
                        <i className={`flag flag-${pickedLanguage} mx-auto`}></i>
                      </MDBDropdownToggle>
                      <MDBDropdownMenu>
                        <MDBDropdownItem
                          onClick={() => {
                            i18n.changeLanguage("en");
                            setPickedLanguage("united-kingdom");
                          }}
                          link
                          href="#"
                        >
                          <i className="flag-united-kingdom flag"></i>English
                        </MDBDropdownItem>
                        <MDBDropdownItem
                          onClick={() => {
                            i18n.changeLanguage("pl");
                            setPickedLanguage("poland");
                          }}
                          link
                          href="#"
                        >
                          <i className="flag flag-poland"></i>Polski
                        </MDBDropdownItem>
                        <MDBDropdownItem
                          onClick={() => {
                            i18n.changeLanguage("ja");
                            setPickedLanguage("japan");
                          }}
                          link
                          href="#"
                        >
                          <i className="flag flag-japan"></i>日本語
                        </MDBDropdownItem>
                        <MDBDropdownItem
                          onClick={() => {
                            i18n.changeLanguage("de");
                            setPickedLanguage("germany");
                          }}
                          link
                          href="#"
                        >
                          <i className="flag flag-germany"></i>Deutsch
                        </MDBDropdownItem>
                      </MDBDropdownMenu>
                    </MDBDropdown>
        
                    <MDBDropdown>
                      <MDBDropdownToggle
                        style={{ cursor: "pointer" }}
                        tag="a"
                        className="nav-link"
                      >
                        <img
                          src="https://mdbootstrap.com/img/new/avatars/2.jpg"
                          className="rounded-circle"
                          height="22"
                          alt=""
                          loading="lazy"
                        />
                      </MDBDropdownToggle>
                      <MDBDropdownMenu>
                        <MDBDropdownItem link>{t("profile")}</MDBDropdownItem>
                        <MDBDropdownItem link>{t("profileSettings")}</MDBDropdownItem>
                        <MDBDropdownItem link>{t("profileLogout")}</MDBDropdownItem>
                      </MDBDropdownMenu>
                    </MDBDropdown>
                  </div>
                </MDBContainer>
              </MDBNavbar>
        
              <MDBContainer>
                <MDBRow>
                  <MDBCol lg="6" className="mx-auto my-5">
                    <MDBCarousel showIndicators showControls fade>
                      <MDBCarouselItem
                        className="w-100 d-block"
                        itemId={1}
                        src="https://mdbootstrap.com/img/Photos/Slides/img%20(15).jpg"
                        alt="..."
                      >
                        <h5>{t("slide1Label")}</h5>
                        <p>{t("slide1Description")}</p>
                      </MDBCarouselItem>
        
                      <MDBCarouselItem
                        className="w-100 d-block"
                        itemId={2}
                        src="https://mdbootstrap.com/img/Photos/Slides/img%20(22).jpg"
                        alt="..."
                      >
                        <h5>{t("slide2Label")}</h5>
                        <p>{t("slide2Description")}</p>
                      </MDBCarouselItem>
        
                      <MDBCarouselItem
                        className="w-100 d-block"
                        itemId={3}
                        src="https://mdbootstrap.com/img/Photos/Slides/img%20(23).jpg"
                        alt="..."
                      >
                        <h5>{t("slide3Label")}</h5>
                        <p>{t("slide3Description")}</p>
                      </MDBCarouselItem>
                    </MDBCarousel>
                  </MDBCol>
                </MDBRow>
        
                <MDBRow className="mb-5">
                  <MDBCol lg="6" className="mb-4 mb-lg-0">
                    <section className="mx-auto d-flex align-items-center">
                      <div className="bg-image">
                        <img
                          src="https://mdbootstrap.com/img/new/standard/city/053.webp"
                          className="w-100"
                          alt="Sample"
                        />
                        <div
                          className="mask"
                          style={{ backgroundColor: "rgba(0, 0, 0, 0.6" }}
                        >
                          <div className="d-flex justify-content-center align-items-center h-100">
                            <p className="text-white mb-0">{t("maskText")}</p>
                          </div>
                        </div>
                      </div>
                    </section>
                  </MDBCol>
                  <MDBCol lg="6" className="mb-4 mb-lg-0">
                    <MDBAccordion initialActive={1}>
                      <MDBAccordionItem collapseId={1} headerTitle={t("accordion1")}>
                        {t("accordionTxt")}
                      </MDBAccordionItem>
                      <MDBAccordionItem collapseId={2} headerTitle={t("accordion2")}>
                        {t("accordionTxt")}
                      </MDBAccordionItem>
                      <MDBAccordionItem collapseId={3} headerTitle={t("accordion3")}>
                        {t("accordionTxt")}
                      </MDBAccordionItem>
                    </MDBAccordion>
                  </MDBCol>
                </MDBRow>
              </MDBContainer>
        
              <MDBFooter>
                <div
                  className="text-center p-3"
                  style={{ backgroundColor: "rgba(0, 0, 0, 0.2" }}
                >
                  © 2022 Copyright:
                  <a className="text-dark" href="https://mdbootstrap.com/">
                    MDBootstrap.com
                  </a>
                </div>
              </MDBFooter>
            </div>
          );
        }
        
        export default App;
      
        
    

More about i18n

For more information, see react i18n github page. There you can read about other options, bundle optimizations etc.


Frontend features

MDB UI KIT:

To create the project we used our ui kit, with which we can build basic views very quickly.

Views and Layouts:

In this project we used App.js file, created by cra in which we placed our React code. We have successfully integrated i18n into the MDB package and can use the appropriate translations based on provided json files.