diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx index acb0046e4..8831a3fa3 100644 --- a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx +++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx @@ -1,10 +1,6 @@ import React from 'react'; import { useThemeConfig, ErrorCauseBoundary } from '@docusaurus/theme-common'; -import { - splitNavbarItems, - useNavbarMobileSidebar, - useAlternatePageUtils, -} from '@docusaurus/theme-common/internal'; +import { splitNavbarItems, useNavbarMobileSidebar } from '@docusaurus/theme-common/internal'; import NavbarItem from '@theme/NavbarItem'; import './primary-menu.scss'; import { @@ -19,16 +15,14 @@ export function useNavbarItems() { return useThemeConfig().navbar.items; } -function normalizePath(path) { - return path.replace(/\/{2,}/g, '/'); -} - export default function CustomMobileSidebar() { const [languageSidebarVisible, setLanguageSidebarVisible] = React.useState(false); const mobileSidebar = useNavbarMobileSidebar(); const items = useNavbarItems(); const [leftItems] = splitNavbarItems(items); - const { pathname } = useLocation(); + const { pathname, search, hash } = useLocation(); + const pathSegments = pathname.split('/').filter(Boolean); + const currentLocale = pathSegments[0]; React.useEffect(() => { if (!mobileSidebar?.shown) { @@ -41,25 +35,55 @@ export default function CustomMobileSidebar() { }; const { - i18n: { currentLocale, locales, localeConfigs }, + i18n: { currentLocale: currentLocaleCtx, locales, localeConfigs }, } = useDocusaurusContext(); - const alternatePageUtils = useAlternatePageUtils(); + + const constructHref = (locale) => { + if (pathname === '/') { + return locale === 'en' ? '/' : `/${locale}`; + } else { + const firstSlashIndex = pathname.indexOf('/'); + const secondSlashIndex = pathname.indexOf('/', firstSlashIndex + 1); + let newPathname = pathname; + + if (secondSlashIndex === -1) { + newPathname = + locale === 'en' || pathname === '/en' + ? pathname.substring(firstSlashIndex) + : `/${locale}${pathname}`; + } else { + const currentLocaleInPath = pathname.substring(1, secondSlashIndex); + const isValidLocale = locales.includes(currentLocaleInPath); + + if (isValidLocale && locale === 'en') { + return pathname.substring(secondSlashIndex); + } else if (isValidLocale) { + return pathname.replace(`/${currentLocaleInPath}`, `/${locale}`); + } else if (locale !== 'en') { + return `/${locale}${pathname}`; + } else { + return pathname; + } + } + + return newPathname; + } + }; + + const handleLocaleChange = (newLocale) => { + const newPathname = constructHref(newLocale); + window.history.pushState(null, '', newPathname); + }; const localeItems = locales.map((locale) => { - const baseTo = alternatePageUtils.createUrl({ - locale, - fullyQualified: false, - }); - console.log('baseTo', baseTo); - const localePath = normalizePath(`${baseTo}${pathname}`); + const newPathname = constructHref(locale); return { label: localeConfigs[locale].label, lang: locale, - target: '_self', - autoAddBaseUrl: false, + to: newPathname, className: classnames({ 'dropdown__link--active': locale === currentLocale }), - to: localePath, + onClick: () => handleLocaleChange(locale), }; }); @@ -78,7 +102,7 @@ export default function CustomMobileSidebar() { } }; - const dropdownLabel = getShortNames(currentLocale); + const dropdownLabel = getShortNames(currentLocaleCtx); return ( @@ -116,7 +140,10 @@ export default function CustomMobileSidebar() { key={localeItem.lang} href={localeItem.to} className={localeItem.className} - onClick={() => mobileSidebar.toggle()} + onClick={() => { + localeItem.onClick(); + mobileSidebar.toggle(); + }} > {localeItem.label} diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/primary-menu.scss b/src/theme/Navbar/MobileSidebar/PrimaryMenu/primary-menu.scss index 8d9917014..a84eb6f51 100644 --- a/src/theme/Navbar/MobileSidebar/PrimaryMenu/primary-menu.scss +++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/primary-menu.scss @@ -12,6 +12,7 @@ line-height: 1.25rem; height: 40px; width: 100vw; + cursor: pointer; } .language_sidebar { @@ -41,6 +42,7 @@ flex-direction: column; gap: 24px; align-items: flex-start; + cursor: pointer; } a { diff --git a/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx index 040ad4aea..a7f22a9c7 100644 --- a/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx +++ b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx @@ -1,46 +1,63 @@ import React from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { useAlternatePageUtils } from '@docusaurus/theme-common/internal'; import { useLocation } from '@docusaurus/router'; import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem'; -import type { LinkLikeNavbarItemProps } from '@theme/NavbarItem'; -import type { Props } from '@theme/NavbarItem/LocaleDropdownNavbarItem'; import classnames from 'classnames'; import './locale-dropdown-navbar-item.scss'; -function normalizePath(path) { - return path.replace(/\/{2,}/g, '/'); -} - export default function LocaleDropdownNavbarItem({ dropdownItemsBefore = [], dropdownItemsAfter = [], ...props -}: Props): JSX.Element { +}) { const { i18n: { currentLocale, locales, localeConfigs }, } = useDocusaurusContext(); - const alternatePageUtils = useAlternatePageUtils(); - const { pathname, search, hash } = useLocation(); + const { pathname } = useLocation(); - const localeItems = locales.map((locale): LinkLikeNavbarItemProps => { - const baseTo = alternatePageUtils.createUrl({ - locale, - fullyQualified: false, - }); + const constructHref = (locale) => { + if (pathname === '/') { + return locale === 'en' ? '/' : `/${locale}`; + } else { + const firstSlashIndex = pathname.indexOf('/'); + const secondSlashIndex = pathname.indexOf('/', firstSlashIndex + 1); - const localePath = normalizePath(`${baseTo}${pathname}`); - const to = `${localePath}${search}${hash}`; + if (secondSlashIndex === -1) { + // Only one slash + return locale === 'en' ? pathname.substring(firstSlashIndex) : `/${locale}${pathname}`; // Correct for single slash case + } else { + const currentLocaleInPath = pathname.substring(1, secondSlashIndex); + const isValidLocale = locales.includes(currentLocaleInPath); + + if (isValidLocale && locale === 'en') { + // Switch to 'en' when valid locale exists + return pathname.substring(secondSlashIndex); // Remove the locale prefix + } else if (isValidLocale) { + // Switch between valid locales + return pathname.replace(`/${currentLocaleInPath}`, `/${locale}`); + } else if (locale !== 'en') { + // Add locale prefix if no valid locale and not switching to 'en' + return `/${locale}${pathname}`; + } else { + // Switch to 'en' with no valid locale in path + return pathname; // Return the original path + } + } + } + }; + + const handleLocaleChange = (newLocale) => { + const newPathname = constructHref(newLocale); + window.history.pushState({ path: newPathname }, '', newPathname); + }; - return { - label: localeConfigs[locale].label, - lang: localeConfigs[locale].htmlLang, - to, - target: '_self', - autoAddBaseUrl: false, - className: classnames({ 'dropdown__link--active': locale === currentLocale }), - }; - }); + const localeItems = locales.map((locale) => ({ + label: localeConfigs[locale].label, + lang: localeConfigs[locale].htmlLang, + onClick: () => handleLocaleChange(locale), + className: classnames({ 'dropdown__link--active': locale === currentLocale }), + href: constructHref(locale), + })); const getShortNames = (locale) => { switch (locale) { diff --git a/src/theme/NavbarItem/LocaleDropdownNavbarItem/locale-dropdown-navbar-item.scss b/src/theme/NavbarItem/LocaleDropdownNavbarItem/locale-dropdown-navbar-item.scss index f5854a836..4b1d965e6 100644 --- a/src/theme/NavbarItem/LocaleDropdownNavbarItem/locale-dropdown-navbar-item.scss +++ b/src/theme/NavbarItem/LocaleDropdownNavbarItem/locale-dropdown-navbar-item.scss @@ -1,6 +1,7 @@ .language_switcher { .dropdown { position: relative; + cursor: pointer; } .dropdown > .navbar__link:after { display: none; @@ -21,6 +22,7 @@ background-color: var(--ifm-navbar-background-color); box-shadow: var(--ifm-navbar-shadow); align-items: flex-end; + cursor: pointer; } .navbar__items--right .dropdown__link {