NextJS Google Translate Widget

Viewed 1687

I have a NextJS application and I want to add Google auto translate widget to my app.

So made a function like this:

function googleTranslateElementInit() {
    if (!window['google']) {
        console.log('script added');
        var script = document.createElement('SCRIPT');
        script.src =
            '//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit';
        document.getElementsByTagName('HEAD')[0].appendChild(script);
    }

    setTimeout(() => {
        console.log('translation loaded');
        new window.google.translate.TranslateElement(
            {
                pageLanguage: 'tr',
                includedLanguages: 'ar,en,es,jv,ko,pt,ru,zh-CN,tr',
                //layout: google.translate.TranslateElement.InlineLayout.SIMPLE,
                //autoDisplay: false,
            },
            'google_translate_element'
        );
    }, 500);
}

And I call this function in useEffect(), it loads but when I route to another page it disappers. When I checked the console I saw translation loaded so setTimeout scope called every time even when I route to another page but translation widget is not appear, only appear when I refresh the page.

How can I solve this?

2 Answers

Thanks to the SILENT's answer: Google no longer support this widget.

So I'm going to configure next-i18next which is a i18n (lightweight translation module with dynamic json storage) for NextJS.

Also, I think the problem with this widget was Google's JS code is attach that widget to DOM itself so it's not attached to VirtualDOM, thats why when I route in app, React checked VirtualDOM and update DOM itself so the widget disappear because it's not on VirtualDOM. (That's just a guess)

Edit: after further testing I found that this code might still be unstable. Be careful if using it in production.


Use the code below inside your custom app and do not forget to put <div id="google_translate_element" /> inside your page or component. Based on this and this answers.

import { useEffect } from 'react'
import { useRouter } from 'next/router'

const MyApp = ({ Component, pageProps }) => {
  const { isFallback, events } = useRouter()

  const googleTranslateElementInit = () => {
    new window.google.translate.TranslateElement({ pageLanguage: 'en' }, 'google_translate_element')
  }

  useEffect(() => {
    const id = 'google-translate-script'

    const addScript = () => {
      const s = document.createElement('script')
      s.setAttribute('src', '//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit')
      s.setAttribute('id', id)
      const q = document.getElementById(id)
      if (!q) {
        document.body.appendChild(s)
        window.googleTranslateElementInit = googleTranslateElementInit
      }
    }

    const removeScript = () => {
      const q = document.getElementById(id)
      if (q) q.remove()
      const w = document.getElementById('google_translate_element')
      if (w) w.innerHTML = ''
    }

    isFallback || addScript()

    events.on('routeChangeStart', removeScript)
    events.on('routeChangeComplete', addScript)

    return () => {
      events.off('routeChangeStart', removeScript)
      events.off('routeChangeComplete', addScript)
    }
  }, [])

  return <Component {...pageProps} />
}

export default MyApp
Related