You know, sometimes our first feelings let us down because the world around us is not so simple. I was going to stop with Google Translate customization under NextJS. This article reveals an approach to translate any content freely without pain via Google Translate on a NextJS-based project. But a couple of occasions became a game changer.
First, I found one essential improvement regarding language configuration. Second, my colleague Bruno Silva provided me with valuable code improvements. I decided to make a new series by analyzing the factors above. I recommend reading the previous series if you want to understand my following thoughts.
Let's get started.
The central part of the previous solution is public/assets/scripts/lang-config.js contains custom languages settings
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", }; The solution above is legal, but it doesn't look like a NextJS-pure. I found a more elegant way to define global data through NextJS config. Let's add env section to next.config.js and remove public/assets/scripts/lang-config.js 
/** @type {import('next').NextConfig} */ const nextConfig = {   reactStrictMode: true,   env: {     GOOGLE_TRANSLATION_CONFIG: JSON.stringify({       languages: [         { title: "English", name: "en" },         { title: "Deutsch", name: "de" },         { title: "Español", name: "es" },         { title: "Français", name: "fr" },       ],       defaultLanguage: "en",     }),   }, };  module.exports = nextConfig; I also changed public/assets/scripts/translation.js the following way because pageLanguage parameter is not mandatory. 
function TranslateInit() {   new google.translate.TranslateElement(); } According to Bruno's proposal, I encapsulated most of the logic into a custom hook, src/hooks/useLanguageSwitcher.ts.
import { useEffect, useState } from "react"; import { parseCookies, setCookie } from "nookies"; import { NextPageContext } from "next";  export const COOKIE_NAME = "googtrans";  export interface LanguageDescriptor {   name: string;   title: string; }  export interface LanguageConfig {   languages: LanguageDescriptor[];   defaultLanguage: string; }  export type UseLanguageSwitcherResult = {   currentLanguage: string;   switchLanguage: (lang: string) => () => void;   languageConfig: LanguageConfig | undefined; };  export type UseLanguageSwitcherOptions = {   context?: NextPageContext; };  export const getLanguageConfig = (): LanguageConfig | undefined => {   let cfg: LanguageConfig | undefined;    if (process.env.GOOGLE_TRANSLATION_CONFIG) {     try {       cfg = JSON.parse(process.env.GOOGLE_TRANSLATION_CONFIG ?? "{}");     } catch (e) {}   }    return cfg; };  export const useLanguageSwitcher = ({   context, }: UseLanguageSwitcherOptions = {}): UseLanguageSwitcherResult => {   const [currentLanguage, setCurrentLanguage] = useState<string>("");    useEffect(() => {     const cfg = getLanguageConfig();     const cookies = parseCookies(context);     const existingLanguageCookieValue = cookies[COOKIE_NAME];      let languageValue = "";     if (existingLanguageCookieValue) {       const sp = existingLanguageCookieValue.split("/");       if (sp.length > 2) {         languageValue = sp[2];       }     }     if (cfg && !languageValue) {       languageValue = cfg.defaultLanguage;     }     setCurrentLanguage(languageValue);   }, []);    const switchLanguage = (lang: string) => () => {     setCookie(context, COOKIE_NAME, "/auto/" + lang);     window.location.reload();   };    return {     currentLanguage,     switchLanguage,     languageConfig: getLanguageConfig(),   }; };  export default useLanguageSwitcher; Important note. process.env.GOOGLE_TRANSLATION_CONFIG allows us to get GOOGLE_TRANSLATION_CONFIG variable from the above mentioned NextJS config.
A couple of final stitches.
src/components/lang-switcher.tsx
import { NextPageContext } from "next"; import useLanguageSwitcher, {   LanguageDescriptor, } from "@/hooks/useLanguageSwitcher"; import React from "react";  export type LanguageSwitcherProps = {   context?: NextPageContext; };  export const LanguageSwitcher = ({ context }: LanguageSwitcherProps = {}) => {   const { currentLanguage, switchLanguage, languageConfig } =     useLanguageSwitcher({ context });    if (!languageConfig) {     return null;   }    return (     <div className="text-center notranslate">       {languageConfig.languages.map((ld: LanguageDescriptor, i: number) => (         <React.Fragment key={`l_s_${ld}`}>           {currentLanguage === ld.name ||           (currentLanguage === "auto" &&             languageConfig.defaultLanguage === ld.name) ? (             <span className="mx-3 text-orange-300">{ld.title}</span>           ) : (             <a               onClick={switchLanguage(ld.name)}               className="mx-3 text-blue-300 cursor-pointer hover:underline"             >               {ld.title}             </a>           )}         </React.Fragment>       ))}     </div>   ); };  export default LanguageSwitcher; useLanguageSwitcher looks elegant 🙂
src/pages/_document.tsx
import { Html, Head, Main, NextScript } from "next/document"; import Script from "next/script";  export default function Document() {   return (     <Html>       <Head>         <Script           src="/assets/scripts/translation.js"           strategy="beforeInteractive"         />         {process.env.GOOGLE_TRANSLATION_CONFIG && (           <Script             src="//translate.google.com/translate_a/element.js?cb=TranslateInit"             strategy="afterInteractive"           />         )}       </Head>       <body>         <Main />         <NextScript />       </body>     </Html>   ); } We don't even physically include the translation engine if the config is missing.
You can find the final solution here.
 
                    