NextJS Internationalization using Google Translator

mohammadfaisal

Mohammad Faisal

Posted on August 26, 2024

NextJS Internationalization using Google Translator

How to internationalize a NextJS website?

  • Setup a CMS or use i18n
  • Connect each piece of text with a key in the translation file.
  • Translate each piece of text.

But all of these take a huge amount of time.

Today I will show you the fastest way to add internationalization in a NextJS website.

In 10 minutes you are going to have a fully translated website using the power of Google Translate.

** Here is the demo and here is the github project **

Let’s begin!

Step 1: Create a new project

Creating a new NextJS project is simple. Just run

npx create-next-app@latest
Enter fullscreen mode Exit fullscreen mode

On your local machine create a basic NextJS project.

Also, we need to install a dependency named nookies . This will be used for cookie management.

yarn add nookies
Enter fullscreen mode Exit fullscreen mode

You are done with dependencies.

Step 2: Configure the public folder

Create 2 files under the public/assets directory.

a. lang-config.js

Create the following file in public/assets/lang-config.js

window.__GOOGLE_TRANSLATION_CONFIG__ = {
    languages: [
        { title: 'English', name: 'en' },
        { title: 'Deutsch', name: 'de' },
        { title: 'Español', name: 'es' },
        { title: 'Français', name: 'fr' },
    ],
    defaultLanguage: 'en',
};
Enter fullscreen mode Exit fullscreen mode

This file defines the available languages and the default language.

You can add whatever language is supported by Google Translate here.

b. translation.js

Create another file in public/assets/translation.js

function TranslateInit() {
    if (!window.__GOOGLE_TRANSLATION_CONFIG__) {
        return;
    }
    new google.translate.TranslateElement({
        pageLanguage: window.__GOOGLE_TRANSLATION_CONFIG__.defaultLanguage,
    });
}
Enter fullscreen mode Exit fullscreen mode

This file checks for the configuration and initializes the Google translator on the site.

Step 3: Import scripts

Now it’s time to import these scripts into the project.

Head over to the

  • root layout.tsx file (if you are using app router)

  • or _document.tsx file (if you are using pages router)

And use NextJS’s Script tag to include these scripts.

return (
  <html lang="en">
      <Script src="/assets/lang-config.js" strategy="beforeInteractive" />
      <Script src="/assets/translation.js" strategy="beforeInteractive" />
      <Script src="//translate.google.com/translate_a/element.js?cb=TranslateInit" strategy="afterInteractive" />
      <body className={inter.className}>
          <div id="google_translate_element"></div>
          {children}
      </body>
  </html>
);
Enter fullscreen mode Exit fullscreen mode

Let’s understand what’s going on here.

The first 2 Script tags are loading the config and initialization. We used strategy beforeInteractive to ensure that they are available from the get-go of the site.

The third script is the script that does the actual translation for us. This can be loaded after the hydration so we used strategy afterInteractive here.

Step 4: Create the language switcher

Now comes the most important component.

Create a new component named language-switcher.tsx and add the following code.

'use client';
    import { useEffect, useState } from 'react';
    import { parseCookies, setCookie } from 'nookies';

    // The following cookie name is important because it's Google-predefined for the translation engine purpose
    const COOKIE_NAME = 'googtrans';

    // We should know a predefined nickname of a language and provide its title (the name for displaying)
    interface LanguageDescriptor {
        name: string;
        title: string;
    }

    // Types for JS-based declarations in public/assets/scripts/lang-config.js
    declare global {
        namespace globalThis {
            var __GOOGLE_TRANSLATION_CONFIG__: {
                languages: LanguageDescriptor[];
                defaultLanguage: string;
            };
        }
    }

    const LanguageSwitcher = () => {
        const [currentLanguage, setCurrentLanguage] = useState<string>();
        const [languageConfig, setLanguageConfig] = useState<any>();

        // Initialize translation engine
        useEffect(() => {
            // 1. Read the cookie
            const cookies = parseCookies();
            const existingLanguageCookieValue = cookies[COOKIE_NAME];

            let languageValue;
            if (existingLanguageCookieValue) {
                // 2. If the cookie is defined, extract a language nickname from there.
                const sp = existingLanguageCookieValue.split('/');
                if (sp.length > 2) {
                    languageValue = sp[2];
                }
            }
            // 3. If __GOOGLE_TRANSLATION_CONFIG__ is defined and we still not decided about languageValue - use default one
            if (global.__GOOGLE_TRANSLATION_CONFIG__ && !languageValue) {
                languageValue = global.__GOOGLE_TRANSLATION_CONFIG__.defaultLanguage;
            }
            if (languageValue) {
                // 4. Set the current language if we have a related decision.
                setCurrentLanguage(languageValue);
            }
            // 5. Set the language config.
            if (global.__GOOGLE_TRANSLATION_CONFIG__) {
                setLanguageConfig(global.__GOOGLE_TRANSLATION_CONFIG__);
            }
        }, []);

        // Don't display anything if current language information is unavailable.
        if (!currentLanguage || !languageConfig) {
            return null;
        }

        // The following function switches the current language
        const switchLanguage = (lang: string) => () => {
            // We just need to set the related cookie and reload the page
            // "/auto/" prefix is Google's definition as far as a cookie name
            setCookie(null, COOKIE_NAME, '/auto/' + lang);
            window.location.reload();
        };

        return (
            <div className="text-center notranslate">
                {languageConfig.languages.map((ld: LanguageDescriptor, i: number) => (
                    <>
                        {currentLanguage === ld.name ||
                        (currentLanguage === 'auto' && languageConfig.defaultLanguage === ld) ? (
                            <span key={`l_s_${ld}`} className="mx-3 text-orange-300">
                                {ld.title}
                            </span>
                        ) : (
                            <a
                                key={`l_s_${ld}`}
                                onClick={switchLanguage(ld.name)}
                                className="mx-3 text-blue-300 cursor-pointer hover:underline"
                            >
                                {ld.title}
                            </a>
                        )}
                    </>
                ))}
            </div>
        );
    };

    export { LanguageSwitcher, COOKIE_NAME };
Enter fullscreen mode Exit fullscreen mode

The code is pretty self-explanatory. But let me give you an overview.

This has to be a client component as we are using useEffect and useState .

First, we read the cookies

const COOKIE_NAME = 'googtrans';

const cookies = parseCookies();
const existingLanguageCookieValue = cookies[COOKIE_NAME];
Enter fullscreen mode Exit fullscreen mode

The cookies tell us which language is selected. If nothing is found we take the default language.

if (global.__GOOGLE_TRANSLATION_CONFIG__ && !languageValue) {
    languageValue = global.__GOOGLE_TRANSLATION_CONFIG__.defaultLanguage;
}
Enter fullscreen mode Exit fullscreen mode

Otherwise

if (languageValue) {
   setCurrentLanguage(languageValue);
}
Enter fullscreen mode Exit fullscreen mode

Then we set the current global config.

if (global.__GOOGLE_TRANSLATION_CONFIG__) {
   setLanguageConfig(global.__GOOGLE_TRANSLATION_CONFIG__);
}
Enter fullscreen mode Exit fullscreen mode

Finally, we have a function to switch the language. This is again as simple as setting the cookie name.

const switchLanguage = (lang: string) => () => {
    setCookie(null, COOKIE_NAME, '/auto/' + lang);
    window.location.reload();
};
Enter fullscreen mode Exit fullscreen mode

That’s basically it. You have freedom about the language you want to use.

Step 5: Use it

Now the only thing to do is add this component somewhere. I am adding it to the page.tsx file.

import { LanguageSwitcher } from '@/components/language-switcher';

export default function Home() {
  return (
      <main className="flex">
          <LanguageSwitcher />
          <div>
              {`Add some text here to test`}
          </div>
      </main>
  );
} 
Enter fullscreen mode Exit fullscreen mode

Then if you run the application

yarn dev
Enter fullscreen mode Exit fullscreen mode

You should see the following.

translator with google translation tab

Beautiful! You can switch between the buttons to see how the translations work!

But there is a bar at the top. Which is not beautiful. We can easily remove it using a little CSS trick.

Add the following to your globals.css file

    .skiptranslate {
        display: none !important;
    }
Enter fullscreen mode Exit fullscreen mode

And voila!

translator without google translation tab

And now you have a working language switcher that can support over 200 languages.

All you have to do is add a new language to the lang-config.js file under the public/assets folder.

Final thoughts

This is by far the fastest way to translate a website.

But…

You have less control over the content as Google Translate will do all the work.

Also probably not good for SEO optimization.

But completely fine for informational websites or landing pages.

Hope you have a wonderful day ahead!

Github Repo: https://github.com/Mohammad-Faisal/nextjs-internationalization-with-google-translate
Live demo: https://nextjs-internationalization-with-google-translate.vercel.app/

💖 💪 🙅 🚩
mohammadfaisal
Mohammad Faisal

Posted on August 26, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related