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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1f2eda7fe Locales nav (#289)
1f2eda7fe is described below

commit 1f2eda7feba6a7a5c62f1f56297d63c879175125
Author: dashuai <lishuail...@sifou.com>
AuthorDate: Mon Jan 13 14:32:53 2025 +0800

    Locales nav (#289)
---
 plugins/blog-plugin.js                             |  3 --
 .../blog/BlogCategoryPostsPage/index.tsx           |  1 -
 src/components/blog/BlogDetailPage/index.tsx       |  1 -
 src/components/blog/BlogHome/index.tsx             |  1 -
 src/theme/DocSidebarItem/Category/index.tsx        |  3 --
 src/theme/Layout/BrowserLanguage.tsx               | 57 ++++++++++++++++++++++
 src/theme/Layout/index.tsx                         |  3 +-
 src/theme/NavbarItem/NavbarNavLink.tsx             | 21 +++++++-
 8 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/plugins/blog-plugin.js b/plugins/blog-plugin.js
index fcd05dd90..59689bc83 100644
--- a/plugins/blog-plugin.js
+++ b/plugins/blog-plugin.js
@@ -149,8 +149,6 @@ async function blogPluginExtended(...pluginArgs) {
 
       const { createData, addRoute } = actions;
 
-      // console.log('blogPosts', blogPosts[0]);
-
       const removeDraftPosts = allBlogPosts.filter((post) => 
!post.metadata.frontMatter?.draft);
 
       // Fecommend posts list
@@ -264,7 +262,6 @@ async function blogPluginExtended(...pluginArgs) {
           permalink: generateCategoryPath(category.label),
         };
 
-        // console.log('categoryProp', categoryProp);
         const categoryPropPath = await createData(
           `${utils.docuHash(categoryProp.label)}.json`,
           JSON.stringify(categoryProp, null, 2),
diff --git a/src/components/blog/BlogCategoryPostsPage/index.tsx 
b/src/components/blog/BlogCategoryPostsPage/index.tsx
index 0c312f351..3b8ab793c 100644
--- a/src/components/blog/BlogCategoryPostsPage/index.tsx
+++ b/src/components/blog/BlogCategoryPostsPage/index.tsx
@@ -21,7 +21,6 @@ interface IProps extends Props {
 }
 const Index = (props: IProps) => {
   const { category, categoriyList, items, listMetadata, } = props
-  // console.log('...props', props);
   return (
     <HtmlClassNameProvider
       className={clsx(
diff --git a/src/components/blog/BlogDetailPage/index.tsx 
b/src/components/blog/BlogDetailPage/index.tsx
index f40da2d19..5c8ba8882 100644
--- a/src/components/blog/BlogDetailPage/index.tsx
+++ b/src/components/blog/BlogDetailPage/index.tsx
@@ -21,7 +21,6 @@ import BlogPostItem from '../BlogPostItem';
 function BlogPostPageContent({relatedList, sidebar, children}) {
   const {metadata, toc} = useBlogPost();
 
-  // console.log('BlogPostPageContent', toc);
   const { frontMatter} = metadata;
   const {
     hide_table_of_contents: hideTableOfContents,
diff --git a/src/components/blog/BlogHome/index.tsx 
b/src/components/blog/BlogHome/index.tsx
index 036ddf222..9508032c0 100644
--- a/src/components/blog/BlogHome/index.tsx
+++ b/src/components/blog/BlogHome/index.tsx
@@ -33,7 +33,6 @@ interface HomeProps {
 }
 
 export function Home({ featuredPosts, categoyList, metadata, blogList }: 
HomeProps): JSX.Element {
-  // console.log('metadata', metadata);
   return (
     <HtmlClassNameProvider
       className={clsx(
diff --git a/src/theme/DocSidebarItem/Category/index.tsx 
b/src/theme/DocSidebarItem/Category/index.tsx
index a8cfd2df1..0da5f3933 100644
--- a/src/theme/DocSidebarItem/Category/index.tsx
+++ b/src/theme/DocSidebarItem/Category/index.tsx
@@ -80,7 +80,6 @@ function CollapseButton({
   categoryLabel: string;
   onClick: ComponentProps<'button'>['onClick'];
 }) {
-  // console.log('categoryLabel', categoryLabel);
   return (
     <button
       aria-label={
@@ -157,8 +156,6 @@ export default function DocSidebarItemCategory({
     }
   }, [collapsible, expandedItem, index, setCollapsed, autoCollapseCategories]);
 
-  console.log('collapsed', item);
-
   return (
     <li
       className={clsx(
diff --git a/src/theme/Layout/BrowserLanguage.tsx 
b/src/theme/Layout/BrowserLanguage.tsx
new file mode 100644
index 000000000..631bc987e
--- /dev/null
+++ b/src/theme/Layout/BrowserLanguage.tsx
@@ -0,0 +1,57 @@
+import React, {useEffect} from 'react';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+
+const LANGUAGE_PREFERENCE_KEY = '_lang_browser_';
+
+export default function BrowserLanguageRedirect() {
+  const {
+    siteConfig: {
+      i18n: {defaultLocale, locales},
+    },
+  } = useDocusaurusContext();
+
+  useEffect(() => {
+    window.addEventListener('languagechange', () => {
+      localStorage.setItem(LANGUAGE_PREFERENCE_KEY, navigator.language);
+    })
+
+    const currentPath = window.location.pathname;
+    const storageLocale = localStorage.getItem('_lang_user_') || 
localStorage.getItem(LANGUAGE_PREFERENCE_KEY);
+    const storageLocaleIsDefault = storageLocale === defaultLocale;
+
+    if (storageLocale) {
+      if (storageLocaleIsDefault) {
+        if (currentPath === '/') return;
+        return;
+      } else {
+        if (currentPath.startsWith(`/${storageLocale}`)) {
+          return;
+        } else {
+          window.location.pathname = `/${storageLocale}${currentPath}`;
+          return;
+        }
+      }
+    } else {
+      const browserLanguage = navigator.language.toLowerCase();
+      const matchedLocale = locales.find(locale =>
+        browserLanguage === locale.toLowerCase() ||
+        browserLanguage.startsWith(locale.toLowerCase() + '-')
+      );
+      if (matchedLocale) {
+        localStorage.setItem(LANGUAGE_PREFERENCE_KEY, matchedLocale);
+        window.location.pathname = `/${matchedLocale}${currentPath}`;
+      } else {
+        window.location.pathname = currentPath;
+      }
+    }
+
+    // remove the event listener
+    return () => {
+      window.removeEventListener('languagechange', () => {
+        localStorage.setItem(LANGUAGE_PREFERENCE_KEY, navigator.language);
+      })
+    }
+  }, []);
+
+  return null;
+}
diff --git a/src/theme/Layout/index.tsx b/src/theme/Layout/index.tsx
index e310f20f8..ad7de5c10 100644
--- a/src/theme/Layout/index.tsx
+++ b/src/theme/Layout/index.tsx
@@ -23,6 +23,7 @@ import LayoutProvider from '@theme/Layout/Provider';
 import ErrorPageContent from '@theme/ErrorPageContent';
 import type {Props} from '@theme/Layout';
 import mixpanel from 'mixpanel-browser';
+import BrowserLanguage from './BrowserLanguage';
 
 import styles from './styles.module.css';
 
@@ -45,7 +46,6 @@ export default function Layout(props: Props): JSX.Element {
   }, [])
 
   useEffect(() => {
-    // console.log('Layout.tsx: location.pathname: ', location);
     mixpanel.track_pageview();
   }, [location]);
 
@@ -58,6 +58,7 @@ export default function Layout(props: Props): JSX.Element {
       <AnnouncementBar />
 
       <Navbar />
+      <BrowserLanguage />
 
       <div
         id={SkipToContentFallbackId}
diff --git a/src/theme/NavbarItem/NavbarNavLink.tsx 
b/src/theme/NavbarItem/NavbarNavLink.tsx
index 8e22a938f..70d0ba0c9 100644
--- a/src/theme/NavbarItem/NavbarNavLink.tsx
+++ b/src/theme/NavbarItem/NavbarNavLink.tsx
@@ -12,10 +12,16 @@ import isInternalUrl from '@docusaurus/isInternalUrl';
 import {isRegexpStringMatch} from '@docusaurus/theme-common';
 import IconExternalLink from '@theme/Icon/ExternalLink';
 import type {Props} from '@theme/NavbarItem/NavbarNavLink';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+
+interface SProps extends Props {
+  tos: Record<string, any>
+}
 
 export default function NavbarNavLink({
   activeBasePath,
   activeBaseRegex,
+  tos,
   to,
   href,
   label,
@@ -23,14 +29,23 @@ export default function NavbarNavLink({
   isDropdownLink,
   prependBaseUrlToHref,
   ...props
-}: Props): JSX.Element {
+}: SProps): JSX.Element {
   // TODO all this seems hacky
   // {to: 'version'} should probably be forbidden, in favor of {to: '/version'}
-  const toUrl = useBaseUrl(to);
+  const { i18n: { currentLocale } } = useDocusaurusContext();
+  // If to is a string, we assume it's a path that needs localization
+  const aliasTo = tos?.[currentLocale] || to;
+  const toUrl = useBaseUrl(aliasTo);
   const activeBaseUrl = useBaseUrl(activeBasePath);
   const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
   const isExternalLink = label && href && !isInternalUrl(href);
 
+  const clickLink = (e) => {
+     if (e.target?.lang) {
+       localStorage.setItem('_lang_user_', e.target.lang);
+     }
+  }
+
   // Link content is set through html XOR label
   const linkContentProps = html
     ? {dangerouslySetInnerHTML: {__html: html}}
@@ -53,6 +68,7 @@ export default function NavbarNavLink({
         href={prependBaseUrlToHref ? normalizedHref : href}
         {...props}
         {...linkContentProps}
+        onClick={clickLink}
       />
     );
   }
@@ -69,6 +85,7 @@ export default function NavbarNavLink({
       })}
       {...props}
       {...linkContentProps}
+      onClick={clickLink}
     />
   );
 }

Reply via email to