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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git


The following commit(s) were added to refs/heads/master by this push:
     new 1b277128747 [fix](website) Fix benchmark entry and restore English 
footer (#4360)
1b277128747 is described below

commit 1b277128747562dcd71415a5b9d7cb0fe20b17d8
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Sun Oct 18 19:55:37 2026 +0100

    [fix](website) Fix benchmark entry and restore English footer (#4360)
    
    Selecting Why Doris → Benchmarks from Chinese documentation inherited
    `/zh-CN/`, although the benchmark content was English and its language
    controls were hidden. Documentation and community pages also replaced
    the full footer with a compact copyright notice.
    
    Both desktop and mobile Benchmark links now open `/why-doris/benchmarks`
    in the English locale. Page language controls remain available on
    fallback pages and offer the existing translations. The full footer now
    renders on documentation and community pages, using one shared English
    configuration and `lang="en"` regardless of the page locale.
    
    ## Validation
    
    - All 18 tests passed in `marketing-pages.test.cjs`,
    `locale-registry.test.cjs`, and `doc-navigation.test.cjs`, including new
    navigation and fallback-language regressions.
    - Scoped TypeScript check and `git diff --check` passed.
    - A small native Docusaurus fixture built successfully for English,
    Chinese, and Japanese using the production components and locale
    dictionaries. It covers Dev/4.x documentation, community pages, and the
    benchmark page; a full documentation build was not run.
    - Browser checks passed at 1440 px and 390 px across all three locales:
    18 documentation/community route and viewport combinations, English
    benchmark entry, English/Japanese round trips, query/fragment
    preservation, refresh, fallback Chinese language controls, and English
    footer content before and after hydration. No horizontal overflow, page
    errors, or hydration errors occurred. Desktop and mobile screenshots
    were inspected.
    - The shared footer configuration preserves all existing links, logo
    settings, and copyright content.
    
    ## Review conclusions
    
    - Goal: Benchmark navigation enters English, manual page-language
    switching remains available, and documentation/community pages show the
    full English footer.
    - Scope: Changes stay within shared navigation, language controls,
    footer configuration/rendering, and regression tests.
    - Information architecture: Documentation versions, localized content,
    sidebars, blog, and community organization remain consistent.
    - Routing: Existing page URLs and anchors are preserved. Only the
    Benchmark menu destination changes; no redirects or sidebar updates are
    required.
    - Frontend: Desktop and mobile use the same menu data. The footer
    retains existing styling and semantic theme tokens, adds an English
    language attribute, and removes its post-hydration replacement.
    - Coverage: Targeted tests, scoped type checking, production fixture
    builds, and browser interactions cover the changed behavior. Full-site
    compilation remains for CI.
    - Other issues: No additional correctness, accessibility, SEO, or
    maintainability issues found in the changed scope.
    
    ## Versions
    
    - [x] dev
    - [x] 4.x
    - [x] 3.x
    - [x] 2.1 or older (not covered by version/language sync gate)
    
    The shared navigation and footer apply across documentation versions.
    
    ## Languages
    
    - [x] Chinese
    - [x] English
    - [x] Japanese
    
    The footer deliberately uses English in every locale; document
    translations need no content changes.
    
    ## Docs Checklist
    
    - [x] Checked by AI
    - [x] Test Cases Built
    - [x] Updated required version and language counterparts, or explained
    why not
    - [x] If only one language changed, confirmed whether source/translation
    counterparts need sync
    
    Co-authored-by: morningman <[email protected]>
---
 config/footer.js                                  | 90 +++++++++++++++++++++++
 docusaurus.config.js                              | 89 +---------------------
 scripts/i18n/__tests__/marketing-pages.test.cjs   | 39 +++++++++-
 src/components/home-next/NavbarNext.tsx           |  3 +-
 src/components/home-next/PageLanguageSwitcher.tsx |  3 +-
 src/theme/Footer/index.tsx                        | 56 ++------------
 src/theme/Footer/styles.scss                      | 19 -----
 7 files changed, 137 insertions(+), 162 deletions(-)

diff --git a/config/footer.js b/config/footer.js
new file mode 100644
index 00000000000..59f95e98f5a
--- /dev/null
+++ b/config/footer.js
@@ -0,0 +1,90 @@
+// Shared English footer content. Render this source in every locale so theme
+// translations cannot change the global footer.
+module.exports = {
+    links: [
+        {
+            title: 'ASF',
+            items: [
+                {
+                    label: 'Foundation',
+                    href: 'https://www.apache.org/',
+                },
+                {
+                    label: 'License',
+                    href: 'https://www.apache.org/licenses/',
+                },
+                {
+                    label: 'Events',
+                    href: 'https://www.apache.org/events/current-event',
+                },
+                {
+                    label: 'Sponsorship',
+                    href: 'https://www.apache.org/foundation/sponsorship.html',
+                },
+                {
+                    label: 'Privacy',
+                    href: 
'https://privacy.apache.org/policies/privacy-policy-public.html',
+                },
+                {
+                    label: 'Security',
+                    href: 'https://www.apache.org/security/',
+                },
+                {
+                    label: 'Thanks',
+                    href: 'https://www.apache.org/foundation/thanks.html',
+                },
+            ],
+        },
+        {
+            title: 'Resources',
+            items: [
+                {
+                    label: 'Download',
+                    href: '/download',
+                },
+                {
+                    label: 'Brand Assets',
+                    href: '/brand-assets',
+                },
+                // {
+                //     label: 'Docs',
+                //     href: '/docs/get-starting/quick-start',
+                // },
+                {
+                    label: 'Blog',
+                    href: '/blog',
+                },
+            ],
+        },
+        {
+            title: 'Community',
+            items: [
+                {
+                    label: 'How to contribute',
+                    href: '/community/how-to-contribute/contribute-to-doris',
+                },
+                {
+                    label: 'Source code',
+                    href: 'https://github.com/apache/doris/',
+                },
+                {
+                    label: 'Doris team',
+                    href: '/community/team',
+                },
+                {
+                    label: 'Roadmap',
+                    href: '/community/roadmap',
+                },
+                {
+                    label: 'Improvement proposal',
+                    href: 
'https://cwiki.apache.org/confluence/display/DORIS/Doris+Improvement+Proposals',
+                },
+            ],
+        },
+    ],
+    logo: {
+        alt: '',
+        src: '/images/asf_logo_apache.svg',
+    },
+    copyright: `Copyright © ${new Date().getFullYear()} The Apache Software 
Foundation,Licensed under the <a 
href="https://www.apache.org/licenses/LICENSE-2.0"; target="_blank">Apache 
License, Version 2.0</a>. Apache, Doris, Apache Doris, the Apache feather logo 
and the Apache Doris logo are trademarks of The Apache Software Foundation.`,
+};
diff --git a/docusaurus.config.js b/docusaurus.config.js
index ae7c2098759..b10d238fc69 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -553,94 +553,7 @@ const config = {
             navbar: {
                 items: [],
             },
-            footer: {
-                links: [
-                    {
-                        title: 'ASF',
-                        items: [
-                            {
-                                label: 'Foundation',
-                                href: 'https://www.apache.org/',
-                            },
-                            {
-                                label: 'License',
-                                href: 'https://www.apache.org/licenses/',
-                            },
-                            {
-                                label: 'Events',
-                                href: 
'https://www.apache.org/events/current-event',
-                            },
-                            {
-                                label: 'Sponsorship',
-                                href: 
'https://www.apache.org/foundation/sponsorship.html',
-                            },
-                            {
-                                label: 'Privacy',
-                                href: 
'https://privacy.apache.org/policies/privacy-policy-public.html',
-                            },
-                            {
-                                label: 'Security',
-                                href: 'https://www.apache.org/security/',
-                            },
-                            {
-                                label: 'Thanks',
-                                href: 
'https://www.apache.org/foundation/thanks.html',
-                            },
-                        ],
-                    },
-                    {
-                        title: 'Resources',
-                        items: [
-                            {
-                                label: 'Download',
-                                href: '/download',
-                            },
-                            {
-                                label: 'Brand Assets',
-                                href: '/brand-assets',
-                            },
-                            // {
-                            //     label: 'Docs',
-                            //     href: '/docs/get-starting/quick-start',
-                            // },
-                            {
-                                label: 'Blog',
-                                href: '/blog',
-                            },
-                        ],
-                    },
-                    {
-                        title: 'Community',
-                        items: [
-                            {
-                                label: 'How to contribute',
-                                href: 
'/community/how-to-contribute/contribute-to-doris',
-                            },
-                            {
-                                label: 'Source code',
-                                href: 'https://github.com/apache/doris/',
-                            },
-                            {
-                                label: 'Doris team',
-                                href: '/community/team',
-                            },
-                            {
-                                label: 'Roadmap',
-                                href: '/community/roadmap',
-                            },
-                            {
-                                label: 'Improvement proposal',
-                                href: 
'https://cwiki.apache.org/confluence/display/DORIS/Doris+Improvement+Proposals',
-                            },
-                        ],
-                    },
-                ],
-                logo: {
-                    alt: '',
-                    src: '/images/asf_logo_apache.svg',
-                },
-                copyright: `Copyright © ${new Date().getFullYear()} The Apache 
Software Foundation,Licensed under the <a 
href="https://www.apache.org/licenses/LICENSE-2.0"; target="_blank">Apache 
License, Version 2.0</a>. Apache, Doris, Apache Doris, the Apache feather logo 
and the Apache Doris logo are trademarks of The Apache Software Foundation.`,
-            },
+            footer: require('./config/footer'),
             docs: {
                 sidebar: {
                     autoCollapseCategories: true,
diff --git a/scripts/i18n/__tests__/marketing-pages.test.cjs 
b/scripts/i18n/__tests__/marketing-pages.test.cjs
index e2e50d9917b..543c9dc3748 100644
--- a/scripts/i18n/__tests__/marketing-pages.test.cjs
+++ b/scripts/i18n/__tests__/marketing-pages.test.cjs
@@ -23,13 +23,24 @@ function modules(locale, pathname, enabled = true) {
             customFields: {defaultLocalePageLocales: ['ja'], 
translatedPagePaths: enabled ? {ja: pagePaths} : {}}},
         '@docusaurus/Translate': {translate: ({message}) => message},
         '@docusaurus/useDocusaurusContext': () => ({i18n}),
+        '@docusaurus/useBaseUrl': source => source,
         '@docusaurus/useGlobalData': () => ({}),
         '@docusaurus/router': {useLocation: () => location},
-        '@docusaurus/Link': ({to, autoAddBaseUrl, children, ...props}) =>
-            React.createElement('a', {...props, href: 
to.replace(/^pathname:\/\//, '')}, children),
+        '@docusaurus/Link': React.forwardRef(({to, href, autoAddBaseUrl = 
true, children, ...props}, ref) => {
+            const target = (to || href).replace(/^pathname:\/\//, '');
+            const baseUrl = locale === 'en' ? '' : `/${locale}`;
+            const destination = autoAddBaseUrl && target.startsWith('/') && 
!target.startsWith(`${baseUrl}/`)
+                ? baseUrl + target : target;
+            return React.createElement('a', {...props, ref, href: 
destination}, children);
+        }),
+        '@site/src/components/brand-theme/BrandThemeSwitcher': 
{BrandThemeSwitcher: () => null},
     };
     function load(file) {
         file = path.resolve(root, file);
+        if (!path.extname(file) || !fs.existsSync(file)) {
+            file = ['', '.ts', '.tsx', '.js', '.json'].map(extension => file + 
extension)
+                .find(candidate => fs.existsSync(candidate) && 
fs.statSync(candidate).isFile());
+        }
         if (cache.has(file)) return cache.get(file).exports;
         const module = {exports: {}};
         cache.set(file, module);
@@ -39,8 +50,8 @@ function modules(locale, pathname, enabled = true) {
         const resolve = name => {
             if (Object.hasOwn(imports, name)) return imports[name];
             if (name.endsWith('.scss')) return {};
-            if (name.startsWith('@site/')) return load(name.slice(6) + '.ts');
-            if (name.startsWith('.')) return 
load(path.resolve(path.dirname(file), name) + '.ts');
+            if (name.startsWith('@site/')) return load(name.slice(6));
+            if (name.startsWith('.')) return 
load(path.resolve(path.dirname(file), name));
             return require(name);
         };
         new Function('require', 'module', 'exports', outputText)(resolve, 
module, module.exports);
@@ -91,6 +102,26 @@ test('page language controls preserve query/hash and mark 
the active language',
     }
 });
 
+test('fallback Chinese benchmark pages still offer English and available 
translations', () => {
+    const {PageLanguageSwitcher} = modules('zh-CN', 
'/zh-CN/why-doris/benchmarks/')
+        ('src/components/home-next/PageLanguageSwitcher.tsx');
+    const html = 
renderToStaticMarkup(React.createElement(PageLanguageSwitcher));
+    assert.match(html, /href="\/why-doris\/benchmarks\/\?from=test#tech"/);
+    assert.match(html, /href="\/ja\/why-doris\/benchmarks\/\?from=test#tech"/);
+    assert.doesNotMatch(html, /href="\/zh-CN\//);
+    assert.doesNotMatch(html, /aria-current="page"/);
+});
+
+test('desktop and mobile benchmark navigation always enters the English page', 
() => {
+    for (const locale of ['en', 'zh-CN', 'ja']) {
+        const {NavbarNext} = modules(locale, 
`/${locale}/docs/4.x/getting-started/what-is-apache-doris/`)
+            ('src/components/home-next/NavbarNext.tsx');
+        const html = renderToStaticMarkup(React.createElement(NavbarNext));
+        assert.equal((html.match(/href="\/why-doris\/benchmarks"/g) ?? 
[]).length, 2, locale);
+        assert.doesNotMatch(html, /href="\/(zh-CN|ja)\/why-doris\/benchmarks/);
+    }
+});
+
 test('language controls stay absent on untranslated pages and when Japanese is 
disabled', () => {
     for (const [locale, pathname, enabled] of [['en', '/download/', true], 
['ja', '/ja/why-doris/users/', true], ['en', '/use-cases/ai/', false]]) {
         const {PageLanguageSwitcher} = modules(locale, pathname, 
enabled)('src/components/home-next/PageLanguageSwitcher.tsx');
diff --git a/src/components/home-next/NavbarNext.tsx 
b/src/components/home-next/NavbarNext.tsx
index 0d0c4b7e2c8..b3036304702 100644
--- a/src/components/home-next/NavbarNext.tsx
+++ b/src/components/home-next/NavbarNext.tsx
@@ -42,7 +42,8 @@ function buildNavItems(
             label: translate({ id: "homepage.navbar.001", message: "Why Doris" 
}),
             items: [
                 { label: translate({ id: "homepage.navbar.002", message: 
"Doris vs. Others" }), href: '/why-doris/compare' },
-                { label: translate({ id: "homepage.navbar.003", message: 
"Benchmarks" }), href: '/why-doris/benchmarks' },
+                // Enter through English from every locale; the page offers 
its own language controls.
+                { label: translate({ id: "homepage.navbar.003", message: 
"Benchmarks" }), href: 'pathname:///why-doris/benchmarks' },
                 { label: translate({ id: "homepage.navbar.004", message: "Key 
Features" }), href: '/why-doris/key-features' },
                 { label: translate({ id: "homepage.navbar.005", message: "User 
Stories" }), href: '/why-doris/users' },
             ],
diff --git a/src/components/home-next/PageLanguageSwitcher.tsx 
b/src/components/home-next/PageLanguageSwitcher.tsx
index 29e787c38a8..5610c7a1fcc 100644
--- a/src/components/home-next/PageLanguageSwitcher.tsx
+++ b/src/components/home-next/PageLanguageSwitcher.tsx
@@ -12,7 +12,8 @@ export function PageLanguageSwitcher(): JSX.Element | null {
     const { pathname, search, hash } = useLocation();
     const path = normalizePathname(pathname, locales).replace(/\/+$/, '');
     const translations = locales.filter(locale => hasTranslatedPage(path, 
locale));
-    if (!translations.length || (currentLocale !== defaultLocale && 
!translations.includes(currentLocale))) return null;
+    // Fallback pages also need an exit to English or an available translation.
+    if (!translations.length) return null;
 
     const languages = [defaultLocale, ...translations];
     return (
diff --git a/src/theme/Footer/index.tsx b/src/theme/Footer/index.tsx
index a5059333fc2..99b1d3cbc68 100644
--- a/src/theme/Footer/index.tsx
+++ b/src/theme/Footer/index.tsx
@@ -1,11 +1,9 @@
-import React, { useState, useEffect } from 'react';
+import React from 'react';
 
-import { useThemeConfig } from '@docusaurus/theme-common';
-import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import footer from '@site/config/footer';
 import FooterLinks from '@theme/Footer/Links';
 import FooterLogo from '@theme/Footer/Logo';
 import FooterCopyright from '@theme/Footer/Copyright';
-import FooterLayout from '@theme/Footer/Layout';
 import './styles.scss';
 import { MailIcon } from '@site/src/components/Icons/mail';
 import { GithubIcon } from '@site/src/components/Icons/github';
@@ -13,53 +11,15 @@ import { TwitterIcon } from 
'@site/src/components/Icons/twitter';
 import { SlackIcon } from '@site/src/components/Icons/slack';
 import { buildSlackEntryUrl } from 
'@site/src/components/slack-redirect/slack-attribution.logic';
 import { DiscordIcon } from '@site/src/components/Icons/discord-icon';
-import { BilibiliIcon } from '@site/src/components/Icons/bilibili';
-import { WechatIcon } from '@site/src/components/Icons/wechat';
 import { YoutubeIcon } from '@site/src/components/Icons/youtube';
 import { LinkedinIcon } from '@site/src/components/Icons/linkedin';
 import { MediumIcon } from '@site/src/components/Icons/medium';
-import Translate from '@docusaurus/Translate';
-import Link from '@docusaurus/Link';
-import { normalizePathname } from '@site/src/utils/locale';
 
-function Footer(): React.ReactElement | null {
-    const { footer } = useThemeConfig();
-    if (!footer) {
-        return null;
-    }
-    const { copyright, links, logo, style } = footer;
-    const {
-        i18n: { locales },
-    } = useDocusaurusContext();
-
-    const [isDocsPage, setIsDocsPage] = useState(false); // docs page or 
community page
-    useEffect(() => {
-        if (typeof window !== 'undefined') {
-            const normalizedPathname = normalizePathname(location.pathname, 
locales);
-            const pathname = normalizedPathname.split('/')[1];
-            const docsPage = pathname === 'docs' || 
normalizedPathname.startsWith('/community');
-            setIsDocsPage(docsPage);
-        }
-    }, [locales, typeof window !== 'undefined' && location.pathname]);
-
-    const ResourcesItems = (links.find(e => e.title === 'Resources')?.items || 
[]) as any[];
-    const CommunityItems = (links.find(e => e.title === 'Community')?.items || 
[]) as any[];
-    if (isDocsPage) {
-        return (
-            <div className="docs-footer flex-col lg:flex-row">
-                <p className='docs-footer-p'>
-                    The contents of this website are © 2024{' '}
-                    <Link href="https://www.apache.org/";>Apache Software 
Foundation</Link> under the terms of the{' '}
-                    <Link 
href="https://www.apache.org/licenses/LICENSE-2.0.html";>Apache License 
v2.</Link> Apache
-                    Doris, Doris, and the Doris logo are either registered 
trademarks or trademarks of The Apache
-                    Software Foundation in the United States and other 
countries.
-                </p>
-            </div>
-        );
-    }
+function Footer(): React.ReactElement {
+    const { copyright, links, logo } = footer;
 
     return (
-        <div className="footer pt-16 pb-10">
+        <footer className="footer pt-16 pb-10" lang="en">
             <div className="container">
                 <div className="footer-box">
                     <div className="left">
@@ -68,9 +28,7 @@ function Footer(): React.ReactElement | null {
                     </div>
                     <div className="right">
                         <div className="footer__title">
-                            <Translate id="footer.follow" description="Footer 
Follow">
-                                Join the community
-                            </Translate>
+                            Join the community
                         </div>
                         <div className="social-list">
                             <div className="social">
@@ -141,7 +99,7 @@ function Footer(): React.ReactElement | null {
                 </div>
                 <FooterCopyright copyright={copyright} />
             </div>
-        </div>
+        </footer>
     );
 }
 
diff --git a/src/theme/Footer/styles.scss b/src/theme/Footer/styles.scss
index c4e649e97a3..e700f7e5f56 100644
--- a/src/theme/Footer/styles.scss
+++ b/src/theme/Footer/styles.scss
@@ -210,22 +210,3 @@
         }
     }
 }
-
-.docs-footer {
-    height: 3.25rem;
-    background-color: #fff;
-    padding: 1rem 1.5rem;
-    border-top: 1px solid #EDF2FA;
-    .docs-footer-p {
-        text-align: center;
-        color: rgba(29, 29, 29, 0.4);
-        font-family: Inter;
-        font-size: 9px;
-        font-style: normal;
-        font-weight: 400;
-        line-height: 20px;
-    }
-    .docs-footer-p a {
-        text-decoration: underline;
-    }
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to