I am trying to add a google translate element to my Gatsby website. In essence, I am trying to get the following code to work in Gatsby:
<div id="google_translate_element"></div>
<script type="text/javascript">
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
}
</script>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
I am relatively new to Gatsby and would like to know the proper (or at least a working) way of achieving this.
const Footer = () => {
useEffect(() => {
const script = document.createElement("script")
script.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"
script.async = true
document.body.appendChild(script)
googleTranslateElementInit(() => {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element')
})
return () => {
document.body.removeChild(script)
}
}, [])
return <div id="google_translate_element"></div>
}
This did not work, due to googleTranslateElementInit
and google
being undefined.
<script
to the <Helmet>
component<Helmet>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
<script type="text/javascript">
{googleTranslateElementInit(() => {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element')
})}
</script>
</Helmet>
Which produced the same error as (1)
<body>
tag of html.js
<body {...props.bodyAttributes}>
<script
dangerouslySetInnerHTML={{
__html: `
function googleTranslateElementInit() {
new google.translate.TranslateElement({pageLanguage: 'en'}, 'google_translate_element');
}
`
}}
/>
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
This worked the first time I loaded the website. After refreshing it, the button was gone. It only appeared the first time I loaded the page after starting the development server. I also tried to make a production build with same results.
I have been stuck with this for a long time and I would greatly appreciate any advice.
It looks like you are not using a React-based approach, so your translate script will always lack scope (it will load asynchronously or it will never load-on-demand). My suggestion is to use a react dependency, such as react-google-translate
, in addition the clean will be much cleaner.
Once you set your environment (environment variables and so on), you just need to:
import React, { useState, useEffect } from 'react'
import { useLazyTranslate } from 'react-google-translate'
const Example = () => {
const [text] = useState('test');
const [language] = useState('zh-CN');
const [translate, { data, loading }] = useLazyTranslate({
language
})
useEffect(() => {
if (text) {
translate(text, language);
}
}, [translate, text])
render() {
return (
<div>{loading ? 'Loading...' : data}</div>
)
}
}
As you can see, there are some custom hooks exposed (useLazyTranslate
) that allow you to use the translation on-demand, ensuring that the library is properly loaded.