This is an automated email from the ASF dual-hosted git repository.

lidongdai pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/seatunnel-website.git


The following commit(s) were added to refs/heads/main by this push:
     new 29663d185fa6 [Fix] Fix Google Translate functionality for non-default 
languages (#429)
29663d185fa6 is described below

commit 29663d185fa6edbaccec41e4d4f69dd36bbfa2ee
Author: zoo-code <[email protected]>
AuthorDate: Sun Feb 15 10:06:17 2026 +0900

    [Fix] Fix Google Translate functionality for non-default languages (#429)
---
 docusaurus.config.js                               |   7 +
 src/css/custom.css                                 |  32 +++++
 src/pages/home/index.jsx                           |   6 +-
 src/theme/Logo/index.js                            |  60 +++++++++
 src/theme/Navbar/Logo/index.js                     |  11 ++
 .../NavbarItem/LocaleDropdownNavbarItem/index.js   | 142 +++++++++++++++------
 static/js/google_translate_init.js                 |   3 +-
 7 files changed, 219 insertions(+), 42 deletions(-)

diff --git a/docusaurus.config.js b/docusaurus.config.js
index cf3aea8743da..94c2fabcf0e8 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -119,6 +119,13 @@ const config = {
         `,
     },
   ],
+  scripts: [
+    '/js/google_translate_init.js',  // Load synchronously first
+    {
+      src: 
'https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit',
+      async: true,
+    },
+  ],
   presets: [
     [
       "classic",
diff --git a/src/css/custom.css b/src/css/custom.css
index 2d0a692bc4e3..1d61e357b5ae 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -66,4 +66,36 @@ html {
 
 html[data-theme='dark']  img {
   filter: brightness(.8) contrast(1.2)
+}
+
+/* Hide Google Translate banner and fix body positioning */
+.goog-te-banner-frame {
+  display: none !important;
+}
+
+body {
+  top: 0 !important;
+}
+
+.skiptranslate {
+  display: none !important;
+}
+
+body > .skiptranslate {
+  display: none !important;
+}
+
+/* Hide Google Translate branding at the bottom */
+#goog-gt-tt, .goog-te-balloon-frame {
+  display: none !important;
+}
+
+/* Ensure page isn't pushed down by Google Translate */
+html body {
+  position: static !important;
+}
+
+/* Prevent Google Translate from translating specific elements */
+.notranslate {
+  translate: no;
 }
\ No newline at end of file
diff --git a/src/pages/home/index.jsx b/src/pages/home/index.jsx
index 86ed765fc0e1..3160b79a613d 100644
--- a/src/pages/home/index.jsx
+++ b/src/pages/home/index.jsx
@@ -74,7 +74,7 @@ export default function () {
                 <div className="block">
 
                     <div className="banner text_center">
-                        <h1 className="main_title"><span 
className="apache">Apache</span> <span
+                        <h1 className="main_title notranslate" 
translate="no"><span className="apache">Apache</span> <span
                             className="seatunnel">SeaTunnel</span>
                         </h1>
 
@@ -86,14 +86,14 @@ export default function () {
                             <a href={systemConfiguration.github.projectUrl} 
target="_blank"
                             className="corner_button link_btn blue" 
onMouseOver={() => changeFlag(1)} onMouseOut={() => changeFlag(2)}>
                                 <img className="button_icon github1" 
src={useBaseUrl('/home/icons/github' + flag + '.svg')} alt="github"/>
-                                <span>GitHub</span>
+                                <span className="notranslate">GitHub</span>
                             </a>
                             <a href="https://s.apache.org/seatunnel-slack";
                             target="_blank"
                             className="corner_button link_btn blue"
                             >
                                 <img className="button_icon" 
src={useBaseUrl('/home/icons/slack.svg')} alt="slack"/>
-                                <span>Slack</span>
+                                <span className="notranslate">Slack</span>
                             </a>
                         </div>
                     </div>
diff --git a/src/theme/Logo/index.js b/src/theme/Logo/index.js
new file mode 100644
index 000000000000..06c4f57e9760
--- /dev/null
+++ b/src/theme/Logo/index.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import Link from '@docusaurus/Link';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import {useThemeConfig} from '@docusaurus/theme-common';
+import ThemedImage from '@theme/ThemedImage';
+function LogoThemedImage({logo, alt, imageClassName}) {
+  const sources = {
+    light: useBaseUrl(logo.src),
+    dark: useBaseUrl(logo.srcDark || logo.src),
+  };
+  const themedImage = (
+    <ThemedImage
+      className={logo.className}
+      sources={sources}
+      height={logo.height}
+      width={logo.width}
+      alt={alt}
+      style={logo.style}
+    />
+  );
+  // Is this extra div really necessary?
+  // introduced in https://github.com/facebook/docusaurus/pull/5666
+  return imageClassName ? (
+    <div className={imageClassName}>{themedImage}</div>
+  ) : (
+    themedImage
+  );
+}
+export default function Logo(props) {
+  const {
+    siteConfig: {title},
+  } = useDocusaurusContext();
+  const {
+    navbar: {title: navbarTitle, logo},
+  } = useThemeConfig();
+  const {imageClassName, titleClassName, ...propsRest} = props;
+  const logoLink = useBaseUrl(logo?.href || '/');
+  // If visible title is shown, fallback alt text should be
+  // an empty string to mark the logo as decorative.
+  const fallbackAlt = navbarTitle ? '' : title;
+  // Use logo alt text if provided (including empty string),
+  // and provide a sensible fallback otherwise.
+  const alt = logo?.alt ?? fallbackAlt;
+  return (
+    <Link
+      to={logoLink}
+      {...propsRest}
+      {...(logo?.target && {target: logo.target})}>
+      {logo && (
+        <LogoThemedImage
+          logo={logo}
+          alt={alt}
+          imageClassName={imageClassName}
+        />
+      )}
+      {navbarTitle != null && <b className={titleClassName} 
translate="no">{navbarTitle}</b>}
+    </Link>
+  );
+}
diff --git a/src/theme/Navbar/Logo/index.js b/src/theme/Navbar/Logo/index.js
new file mode 100644
index 000000000000..f0fa51ffad3f
--- /dev/null
+++ b/src/theme/Navbar/Logo/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import Logo from '@theme/Logo';
+export default function NavbarLogo() {
+  return (
+    <Logo
+      className="navbar__brand"
+      imageClassName="navbar__logo"
+      titleClassName="navbar__title text--truncate"
+    />
+  );
+}
diff --git a/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js 
b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js
index 9add6b242ccb..929d4d3c1f99 100644
--- a/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js
+++ b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.js
@@ -34,36 +34,85 @@ export default function LocaleDropdownNavbarItem({
     const alternatePageUtils = useAlternatePageUtils();
     const { search, hash } = useLocation();
 
-    // Clear Google Translate cookie if we are on a native locale page
-    React.useEffect(() => {
-        if (currentLocale === 'en' || currentLocale === 'zh-CN') {
-            const clearCookie = (name) => {
-                document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 
UTC; path=/;';
-                document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 
UTC; path=/seatunnel-website;';
-                document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 
UTC; domain=.' + document.domain + '; path=/;';
-            };
-            clearCookie('googtrans');
-            const frame = document.querySelector('.goog-te-banner-frame');
-            if (frame) {
-                frame.style.display = 'none';
+    // Helper function to get current Google Translate language code from 
cookie
+    const getGoogleTranslateLangCode = () => {
+        if (typeof document === 'undefined') return null;
+        const cookie = document.cookie.split('; ').find(row => 
row.startsWith('googtrans='));
+        if (cookie) {
+            const match = cookie.match(/googtrans=\/[^\/]+\/([^;]+)/);
+            return match ? match[1] : null;
+        }
+        return null;
+    };
+
+    // Helper function to get language label from cookie
+    const getLanguageLabelFromCookie = () => {
+        const langCode = getGoogleTranslateLangCode();
+        if (langCode) {
+            const googleLang = GOOGLE_LANGUAGES.find(lang => lang.code === 
langCode);
+            if (googleLang) {
+                return googleLang.label;
             }
         }
-    }, [currentLocale]);
+        return localeConfigs[currentLocale]?.label || 'English';
+    };
 
-    // Detect if we're on a versioned documentation page
-    const currentPath = typeof window !== 'undefined' ? 
window.location.pathname : '';
-    const versionMatch = currentPath.match(/^\/docs\/([^/]+)\//);
-    const isVersionedDoc = versionMatch && versionMatch[1] !== '';
+    // State to track current language label
+    const [currentLangLabel, setCurrentLangLabel] = 
React.useState(getLanguageLabelFromCookie());
+
+    // Update language label based on Google Translate cookie
+    React.useEffect(() => {
+        const updateLabel = () => {
+            setCurrentLangLabel(getLanguageLabelFromCookie());
+        };
+
+        // Initial update
+        updateLabel();
+
+        // Listen for storage events (from other tabs/windows)
+        window.addEventListener('storage', updateLabel);
+
+        return () => {
+            window.removeEventListener('storage', updateLabel);
+        };
+    }, [currentLocale, localeConfigs]);
+
+    // Hide Google Translate banner frame if present
+    React.useEffect(() => {
+        const frame = document.querySelector('.goog-te-banner-frame');
+        if (frame) {
+            frame.style.display = 'none';
+        }
+    }, []);
 
     // Helper function to trigger Google Translate programmatically
     const handleGoogleTranslate = (langCode) => {
-        const select = document.querySelector('.goog-te-combo');
-        if (select) {
-            select.value = langCode;
-            select.dispatchEvent(new Event('change'));
+        // Set Google Translate cookie
+        const cookieValue = '/en/' + langCode;
+
+        // Set cookie without domain for localhost compatibility
+        document.cookie = 'googtrans=' + cookieValue + '; path=/';
+
+        // Also set with domain if not localhost
+        if (window.location.hostname !== 'localhost' && 
window.location.hostname !== '127.0.0.1') {
+            document.cookie = 'googtrans=' + cookieValue + '; path=/; domain=' 
+ window.location.hostname;
+        }
+
+        // If currently on a /zh-CN/ page, redirect to English version first
+        const currentPath = window.location.pathname;
+        if (currentPath.startsWith('/zh-CN/')) {
+            // Remove /zh-CN prefix to go to English version
+            const englishPath = currentPath.replace(/^\/zh-CN/, '') || '/';
+            window.location.href = englishPath + window.location.search + 
window.location.hash;
+        } else {
+            // Reload the page to apply translation
+            window.location.reload();
         }
     };
 
+    const activeGoogleLang = getGoogleTranslateLangCode();
+    const activeClass = mobile ? 'menu__link--active' : 
'dropdown__link--active';
+
     const localeItems = locales.map((locale) => {
         const baseTo = `pathname://${alternatePageUtils.createUrl({
             locale,
@@ -71,47 +120,64 @@ export default function LocaleDropdownNavbarItem({
         })}`;
         const to = `${baseTo}${search}${hash}`;
 
+        // Native locale is only active if no Google Translate is active AND 
locale matches
+        const isActive = !activeGoogleLang && locale === currentLocale;
+
         return {
             label: localeConfigs[locale].label,
             lang: localeConfigs[locale].htmlLang,
             to,
             target: '_self',
             autoAddBaseUrl: false,
-            className:
-                locale === currentLocale
-                    ? mobile
-                        ? 'menu__link--active'
-                        : 'dropdown__link--active'
-                    : '',
+            className: `notranslate ${isActive ? activeClass : ''}`.trim(),
             onClick: () => {
-                // Clear Google Translate cookie when switching to native 
locales
-                document.cookie = 'googtrans=; expires=Thu, 01 Jan 1970 
00:00:00 UTC; path=/;';
+                // Clear Google Translate cookies when switching to native 
locales
+                const clearCookie = (name) => {
+                    document.cookie = name + '=; expires=Thu, 01 Jan 1970 
00:00:00 UTC; path=/;';
+                    document.cookie = name + '=; expires=Thu, 01 Jan 1970 
00:00:00 UTC; path=/seatunnel-website;';
+                    if (window.location.hostname !== 'localhost' && 
window.location.hostname !== '127.0.0.1') {
+                        document.cookie = name + '=; expires=Thu, 01 Jan 1970 
00:00:00 UTC; domain=.' + window.location.hostname + '; path=/;';
+                    }
+                };
+                clearCookie('googtrans');
+                // Update the label immediately
+                setCurrentLangLabel(localeConfigs[locale].label);
             }
         };
     });
 
-    const googleItems = GOOGLE_LANGUAGES.map((lang) => ({
-        label: lang.label,
-        to: '#',
-        onClick: (e) => {
-            e.preventDefault();
-            handleGoogleTranslate(lang.code);
-        },
-    }));
+    const googleItems = GOOGLE_LANGUAGES.map((lang) => {
+        const isActive = activeGoogleLang === lang.code;
+        return {
+            label: lang.label,
+            to: '#',
+            className: `notranslate ${isActive ? activeClass : ''}`.trim(),
+            onClick: (e) => {
+                e.preventDefault();
+                e.stopPropagation();
+                // Update the label immediately
+                setCurrentLangLabel(lang.label);
+                handleGoogleTranslate(lang.code);
+                return false;
+            },
+        };
+    });
 
     const items = [...dropdownItemsBefore, ...localeItems, ...googleItems, 
...dropdownItemsAfter];
+
     const dropdownLabel = mobile
         ? translate({
             message: 'Languages',
             id: 'theme.navbar.mobileLanguageDropdown.label',
             description: 'The label for the mobile language switcher dropdown',
         })
-        : localeConfigs[currentLocale].label;
+        : currentLangLabel;
 
     return (
         <DropdownNavbarItem
             {...props}
             mobile={mobile}
+            className="notranslate"
             label={
                 <>
                     <div id="google_translate_element" style={{ visibility: 
'hidden', height: 0, overflow: 'hidden', position: 'absolute' }} />
diff --git a/static/js/google_translate_init.js 
b/static/js/google_translate_init.js
index 5826a162ad1d..c8b41ed4f63a 100644
--- a/static/js/google_translate_init.js
+++ b/static/js/google_translate_init.js
@@ -3,7 +3,8 @@ function googleTranslateElementInit() {
         {
             pageLanguage: "en",
             // Only languages NOT provided by native Docusaurus i18n
-            includedLanguages: "zh-CN,ja,ko,fr,es,ru,de",
+            // en and zh-CN are handled by Docusaurus natively
+            includedLanguages: "ja,ko,fr,es,ru,de",
             autoDisplay: false,
         },
         "google_translate_element"

Reply via email to