Back to Top

How to Create a Multilingual app in Next JS.

Updated 30 May 2024

how to create multilingual app in next blog Image

In this blog, I will discuss about how to create a multilingual app using the next-i18next.

The next-i18next package provides the internationalization(i18n) functionality – management of translation content and supports Next JS Data Fetching: GetStaticProps and GetServerSideProps with the help of the NextJs i18n routes.

Before starting let’s set up the Next.js project:

To set up the Next js project we can follow this setup next js project blog that covers all about the next js project setup.

Understanding i18n Routing in NextJs.

NextJs has already provided built-in support for internationalized routing. which automatically detects the locale. i.e. which is to serve the content in various languages based on the user’s preferences.

Start your headless eCommerce
now.
Find out More

Locale Identifier has a like this.

  • en-US – English as spoken in the United States
  • hi-IN – Hindi as spoken in India
  • nl-NL – Dutch as spoken in the Netherlands
  • nl – Dutch, no specific region

To implement i18n routes in Next.js, There are a few different approaches to define the i18n routes in NextJs.

Subpath-based Routing

In this approach, different language versions of the site are prefixed with language-specific subpaths in the URL. For instance:

  • /hi/blog – Routing for hi locale.
  • /nl-NL/blog – routing for the nl-NL locale.
  • /hi-IN/blog – routing for the hi-IN locale

Domain-based Routing

In this routing, Each language version of the site is hosted on its subdomain or domain:

  • https://example.com/home – English
  • https://fr.example.com/home – French

Setting up the next-i18next package in a Next.js App

Step 1: Install Packages.

Install the next-i18next package and its peer dependencies:

npm install next-i18next react-i18next i18next

After Creating a new project and package installation then you can see the final folder structure.

.
├── pages/
│   ├── api
│         ├── hello.ts
│   ├── app.tsx
|   ├──_documet.tsx
│   └── index.tsx
├── public/
│   ├── favicon.ico
│   ├── next.svg
│   └── vercel.svg
├── styles/
│   └── global.css
│   └── Home.module.css
├── next.config.js
├── package-lock.json
├── package.json
└── README.md

now create the new file next-i18next.config.js in the root directory. and write the following code.

//-----------next-i18next.config.js-----------//

/** @type {import('next-i18next').UserConfig} */
module.exports = {
  i18n: {
    defaultLocale: "en-US",
    locales: ["en-US", "ni-NL", "hi-IN"],
  },
};

It’s configuration file to tells next-i18next that what is your default locale and other locale.

Step 2: Configuration the next-i18next file.

Create a next.config.js file at the root of your project if you haven’t already,

//----------next.config.js-----------//

/** @type {import('next').NextConfig} */

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

module.exports = nextConfig;

Now open the _aap.tsx file and Import the appWithTranslation next-i18next component. This is a HOC component that wraps your App:

//---------_app.tsx----------//

import "@/styles/globals.css";
import { appWithTranslation } from "next-i18next";
import type { AppProps } from "next/app";
import { UserConfig } from "next-i18next";
import nextI18NextConfig from "../next-i18next.config.js";
import Layout from "@/components/layout";

const emptyInitialI18NextConfig: UserConfig = {
  i18n: {
    defaultLocale: nextI18NextConfig.i18n.defaultLocale,
    locales: nextI18NextConfig.i18n.locales,
  },
};
function App({ Component, pageProps }: AppProps) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default appWithTranslation(App, emptyInitialI18NextConfig);

Step 3: Create translation localization files.

Create language-specific translation files within a public/locales folder. For example:

public
└── locales
├── en-Us
│ └── common.json
├── ni-NL
│ └── common.json
└── hi-IN
└── common.json

In each common.json file, define key-value pairs for the translations in respective languages:

//--------------en-US/common.json---------//

{
  "Where does it come from?": "Where does it come from?",
  "A Simple Example for Trasnslation":"A Simple Example for Trasnslation",
  "Current localization language:":"Current localization language:",
  "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
}
//---------------ni-NL/common.js---------------//

{
  "Where does it come from?": "Waar komt het vandaan?",
  "Current localization language:": "Huidige lokalisatietaal:",
  "A Simple Example for Trasnslation":"Een eenvoudig voorbeeld voor vertaling",
  "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.": "Lorem Ipsum is slechts een proeftekst uit de druk- en zetterijbranche. Lorem Ipsum is de standaard proeftekst in de bedrijfstak sinds de 16e eeuw, toen een onbekende drukker een galei met letters nam en deze door elkaar gooide om een ​​lettertype-specimenboek te maken. Het heeft niet alleen vijf eeuwen overleefd, maar ook de sprong naar elektronisch zetwerk, en is in wezen onveranderd gebleven. Het werd in de jaren zestig gepopulariseerd met de introductie van Letraset-bladen met Lorem Ipsum-passages, en meer recentelijk door desktop publishing-software zoals Aldus PageMaker die versies van Lorem Ipsum bevatten."
}
//---------------hi-IN/common.js-------------//

{
  "Where does it come from?": "कहाँ से आता है?",
  "A Simple Example for Trasnslation":"अनुवाद के लिए एक सरल उदाहरण",
  "Current localization language:": "वर्तमान स्थानीयकरण भाषा:",
  "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.": "लोरेम इप्सम केवल मुद्रण और टाइपसेटिंग उद्योग का नकली पाठ है। लोरेम इप्सम 1500 के दशक से ही उद्योग का मानक डमी टेक्स्ट रहा है, जब एक अज्ञात प्रिंटर ने एक प्रकार की गैली ली और उसे एक प्रकार की नमूना पुस्तक बनाने के लिए तैयार किया। यह न केवल पाँच शताब्दियों तक जीवित रहा है, बल्कि इलेक्ट्रॉनिक टाइपसेटिंग में भी छलांग लगाता रहा है, मूलतः अपरिवर्तित रहा है। इसे 1960 के दशक में लोरेम इप्सम अंशों वाले लेट्रासेट शीट के रिलीज के साथ लोकप्रिय बनाया गया था, और हाल ही में लोरेम इप्सम के संस्करणों सहित एल्डस पेजमेकर जैसे डेस्कटॉप प्रकाशन सॉफ्टवेयर के साथ इसे लोकप्रिय बनाया गया था।"
}

Step 4: Translate content.

We’ll create the components folder in the Root directory and now create the header.tsx, footer.tsx, layout.tsx, and languageSwitcher.tsx file inside the components directory.

Write the following Code.

//-----------components/header.tsx----------//

const Header = () => {
  return (
    <header>
      <div className="flex justify-center ">
        <h1 className="text-4xl font-bold py-3 px-6 text-slate-400 border-b border-solid border-slate-400">
          next-i18next
        </h1>
      </div>
    </header>
  );
};
export default Header;
//-----------components/footer.tsx---------//

import Link from "next/link";
import LanguageSwitcher from "./languageSwitcher";

const Footer = () => {
  const CURRENT_YEAR = new Date().getFullYear();
  return (
    <footer className="bg-slate-100">
      <div className="max-w-[90vw] mx-auto py-5 flex flex-col gap-5">
        <div className="flex justify-between">
          <h1 className="text-3xl text-blue-500 font-bold">Webkul</h1>
          <ul className="flex gap-4 items-center">
            <LanguageSwitcher />
          </ul>
        </div>
        <div>
          <h4 className="text-center font-normal !text-gray-700">
            &copy; {CURRENT_YEAR} made with multilingual app with
            <Link href="https://webkul.com/"></Link>
          </h4>
        </div>
      </div>
    </footer>
  );
};
export default Footer;
//-----------components/languageSwitcher.tsx---------//

import Link from "next/link";
import { useRouter } from "next/router";
const LanguageSwitcher = () => {
  const { locales, locale: currentLocale } = useRouter();
  return (
    <ul className="flex gap-4 items-center">
      {locales?.map((locale) => (
        <li
          key={locale}
          className={`p-2 rounded border border-solid border-gray-300 ${
            locale == currentLocale ? "bg-blue-500 text-white" : "bg-white"
          }`}
        >
          <Link href="/" locale={locale}>
            <button>Change locale to {locale} </button>
          </Link>
        </li>
      ))}
    </ul>
  );
};
export default LanguageSwitcher;
//---------------components/layout.tsx-----------//

import { ReactNode } from "react";
import Footer from "./footer";
import Header from "./header";

const Layout = ({ children }: { children: ReactNode }) => {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  );
};
export default Layout;

Now We’ll create the index.tsx inside the pages directory basically index.tsx file already exists then no need to create the index.tsx file.

//------------pages/index.tsx-----------//

import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
export default function Home() {
  const { locale } = useRouter();
  const { t } = useTranslation("common");

  return (
    <div className="max-w-[90vw] min-h-[65vh] mx-auto my-10">
      <div className="flex flex-col gap-4">
        <div className="">
          <h1 className="text-3xl font-bold text-center">
            {t("A Simple Example for Trasnslation")}
          </h1>
          <h3 className="text-2xl font-bold">
            Current localization language: {locale}
          </h3>
          <p>
            {t(
              "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
            )}
          </p>
        </div>
        <div className="flex flex-col gap-4">
          <h3 className="text-2xl font-bold">
            {t("Where does it come from?")}
          </h3>
          <p>
            {t(
              "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
            )}
          </p>
          <p>
            {t(
              "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
            )}
          </p>
        </div>
      </div>
    </div>
  );
}
export async function getStaticProps({ locale }: { locale: string }) {
  return {
    props: {
      ...(await serverSideTranslations(locale, ["common"])),
    },
  };
}

Finally Ready the multilingual app and you can see the output for deafult locale on http://localhost:3000/ and switch the i18n route help of the language switcher.

translation output for english langiage
translation output for dutch language
translation output for hindi language

Start your Headless Development with Webkul.

Happy Coding!!

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home