feat: add Google Translate integration#2079
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds Google Translate functionality to the Docusaurus documentation site by integrating the Google Translate widget into the navbar. The implementation includes external script loading, a custom plugin for initialization callback, and an HTML navbar item with an onclick handler.
Key Changes:
- Added Google Translate external script along with GitHub buttons and Font Awesome scripts
- Implemented a lightweight Docusaurus plugin that injects an empty
googleTranslateElementInitcallback function - Added a custom HTML navbar item featuring a translate icon with inline onclick handler to initialize the translation widget
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| type: 'html', | ||
| position: 'right', | ||
| value: | ||
| '<div id="google_translate_element" style="display:inline-block"></div><a class="navbar__link false" href="#" onclick="new google.translate.TranslateElement({pageLanguage: \'en\', includedLanguages: \'af,sq,am,en,fa,ar,ps,ja,zh-CN,hy,az,eu,be,bn,bs,bg,ca,ceb,ny,zh-TW,co,hr,cs,da,nl,eo,et,tl,fi,fr,fy,gl,ka,de,el,gu,ht,ha,haw,iw,hi,hmn,hu,is,ig,id,ga,it,jw,kn,kk,km,ko,ku,ky,lo,la,lv,lt,lb,mk,mg,ms,ml,mt,mi,mr,mn,my,ne,no,pl,pt,pa,ro,ru,sm,gd,sr,st,sn,sd,si,sk,sl,so,es,su,sw,sv,tg,ta,te,th,tr,uk,ur,uz,vi,cy,xh,yi,yo,zu\'}, \'google_translate_element\'); return false;"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="vertical-align: text-bottom"><path fill="currentColor" d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></svg></a>', |
There was a problem hiding this comment.
Using inline styles (style="display:inline-block" and style="vertical-align: text-bottom") is not a best practice in modern web development and makes styling inconsistent and harder to maintain.
Consider:
- Moving these styles to a CSS/SCSS file
- Using CSS classes instead of inline styles
- Following the existing styling patterns in the Docusaurus theme
| 'https://buttons.github.io/buttons.js', | ||
| 'https://use.fontawesome.com/221fd444f5.js', | ||
| 'https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit', |
There was a problem hiding this comment.
[nitpick] Loading external scripts without Subresource Integrity (SRI) hashes could pose a security risk if the third-party sources are compromised. While this is common practice for well-known CDNs like GitHub buttons and Font Awesome, consider adding SRI hashes for additional security or using a Content Security Policy (CSP) to restrict script sources.
This is particularly relevant for production deployments.
| { | ||
| tagName: 'script', | ||
| innerHTML: ` | ||
| function googleTranslateElementInit() {} |
There was a problem hiding this comment.
The googleTranslateElementInit function is defined as an empty function but never actually initializes the Google Translate element. This means the translate widget won't work automatically on page load. The initialization logic is currently only in the onclick handler of the navbar link.
Consider implementing the function to actually initialize the translate element, or if you want the widget to only appear on click, you may not need this callback function at all (and can remove the ?cb=googleTranslateElementInit parameter from the script URL).
| function googleTranslateElementInit() {} | |
| function googleTranslateElementInit() { | |
| new google.translate.TranslateElement({ | |
| pageLanguage: 'en', | |
| includedLanguages: 'en,es', | |
| layout: google.translate.TranslateElement.InlineLayout.SIMPLE | |
| }, 'google_translate_element'); | |
| } |
| type: 'html', | ||
| position: 'right', | ||
| value: | ||
| '<div id="google_translate_element" style="display:inline-block"></div><a class="navbar__link false" href="#" onclick="new google.translate.TranslateElement({pageLanguage: \'en\', includedLanguages: \'af,sq,am,en,fa,ar,ps,ja,zh-CN,hy,az,eu,be,bn,bs,bg,ca,ceb,ny,zh-TW,co,hr,cs,da,nl,eo,et,tl,fi,fr,fy,gl,ka,de,el,gu,ht,ha,haw,iw,hi,hmn,hu,is,ig,id,ga,it,jw,kn,kk,km,ko,ku,ky,lo,la,lv,lt,lb,mk,mg,ms,ml,mt,mi,mr,mn,my,ne,no,pl,pt,pa,ro,ru,sm,gd,sr,st,sn,sd,si,sk,sl,so,es,su,sw,sv,tg,ta,te,th,tr,uk,ur,uz,vi,cy,xh,yi,yo,zu\'}, \'google_translate_element\'); return false;"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="vertical-align: text-bottom"><path fill="currentColor" d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></svg></a>', |
There was a problem hiding this comment.
This inline HTML is extremely long and difficult to maintain. The onclick handler contains a hardcoded list of 100+ language codes, making it fragile and hard to update.
Consider:
- Moving this logic to a separate JavaScript file or React component
- Storing the language list in a configuration variable
- Using a more maintainable approach with proper event handlers instead of inline onclick
Example refactor:
const TRANSLATE_LANGUAGES = 'af,sq,am,en,fa,ar,...';
// Then reference this in a cleaner HTML structure or component| type: 'html', | ||
| position: 'right', | ||
| value: | ||
| '<div id="google_translate_element" style="display:inline-block"></div><a class="navbar__link false" href="#" onclick="new google.translate.TranslateElement({pageLanguage: \'en\', includedLanguages: \'af,sq,am,en,fa,ar,ps,ja,zh-CN,hy,az,eu,be,bn,bs,bg,ca,ceb,ny,zh-TW,co,hr,cs,da,nl,eo,et,tl,fi,fr,fy,gl,ka,de,el,gu,ht,ha,haw,iw,hi,hmn,hu,is,ig,id,ga,it,jw,kn,kk,km,ko,ku,ky,lo,la,lv,lt,lb,mk,mg,ms,ml,mt,mi,mr,mn,my,ne,no,pl,pt,pa,ro,ru,sm,gd,sr,st,sn,sd,si,sk,sl,so,es,su,sw,sv,tg,ta,te,th,tr,uk,ur,uz,vi,cy,xh,yi,yo,zu\'}, \'google_translate_element\'); return false;"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="vertical-align: text-bottom"><path fill="currentColor" d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></svg></a>', |
There was a problem hiding this comment.
The class attribute contains "navbar__link false" which includes a literal "false" string. This appears to be a mistake - it looks like this should either be a conditional class or just "navbar__link".
If you're not using a conditional here, remove the "false" string:
<a class="navbar__link" href="#" ...>| type: 'html', | ||
| position: 'right', | ||
| value: | ||
| '<div id="google_translate_element" style="display:inline-block"></div><a class="navbar__link false" href="#" onclick="new google.translate.TranslateElement({pageLanguage: \'en\', includedLanguages: \'af,sq,am,en,fa,ar,ps,ja,zh-CN,hy,az,eu,be,bn,bs,bg,ca,ceb,ny,zh-TW,co,hr,cs,da,nl,eo,et,tl,fi,fr,fy,gl,ka,de,el,gu,ht,ha,haw,iw,hi,hmn,hu,is,ig,id,ga,it,jw,kn,kk,km,ko,ku,ky,lo,la,lv,lt,lb,mk,mg,ms,ml,mt,mi,mr,mn,my,ne,no,pl,pt,pa,ro,ru,sm,gd,sr,st,sn,sd,si,sk,sl,so,es,su,sw,sv,tg,ta,te,th,tr,uk,ur,uz,vi,cy,xh,yi,yo,zu\'}, \'google_translate_element\'); return false;"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="vertical-align: text-bottom"><path fill="currentColor" d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></svg></a>', |
There was a problem hiding this comment.
The translate link is missing essential accessibility attributes. The link has no accessible label for screen readers to announce what the button does.
Add an aria-label attribute:
<a class="navbar__link" href="#" aria-label="Translate page" onclick="...">| type: 'html', | ||
| position: 'right', | ||
| value: | ||
| '<div id="google_translate_element" style="display:inline-block"></div><a class="navbar__link false" href="#" onclick="new google.translate.TranslateElement({pageLanguage: \'en\', includedLanguages: \'af,sq,am,en,fa,ar,ps,ja,zh-CN,hy,az,eu,be,bn,bs,bg,ca,ceb,ny,zh-TW,co,hr,cs,da,nl,eo,et,tl,fi,fr,fy,gl,ka,de,el,gu,ht,ha,haw,iw,hi,hmn,hu,is,ig,id,ga,it,jw,kn,kk,km,ko,ku,ky,lo,la,lv,lt,lb,mk,mg,ms,ml,mt,mi,mr,mn,my,ne,no,pl,pt,pa,ro,ru,sm,gd,sr,st,sn,sd,si,sk,sl,so,es,su,sw,sv,tg,ta,te,th,tr,uk,ur,uz,vi,cy,xh,yi,yo,zu\'}, \'google_translate_element\'); return false;"><svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="vertical-align: text-bottom"><path fill="currentColor" d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"></path></svg></a>', |
There was a problem hiding this comment.
The onclick handler creates a new TranslateElement instance every time the link is clicked, which could lead to multiple widgets being initialized and potential memory leaks or unexpected behavior.
Consider tracking whether the element has already been initialized:
onclick="if (!window.googleTranslateInitialized) { new google.translate.TranslateElement({...}, 'google_translate_element'); window.googleTranslateInitialized = true; } return false;"|
Closing in favor of #2097 |


This PR adds a Google Translate widget to the navbar, allowing users to translate the documentation into various languages.
Changes:
Verification: