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
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
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',
};
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,
});
}
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>
);
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 };
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];
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;
}
Otherwise
if (languageValue) {
setCurrentLanguage(languageValue);
}
Then we set the current global config.
if (global.__GOOGLE_TRANSLATION_CONFIG__) {
setLanguageConfig(global.__GOOGLE_TRANSLATION_CONFIG__);
}
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();
};
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>
);
}
Then if you run the application
yarn dev
You should see the following.
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;
}
And voila!
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/