blob: ac888c970e3d2218013ee27e14448197f5de510a [file]
import React from 'react';
import {useLocation} from '@docusaurus/router';
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
const cnPrefixes = ['/cn/docs/', '/cn/blog/', '/cn/community/', '/cn/team/', '/cn/users/', '/cn/download/'];
const enPrefixes = ['/docs/', '/blog/', '/community/', '/team/', '/users/', '/download/'];
const enToCnFallbacks = new Map([
['/community/maturity/', '/cn/community/'],
]);
function appendSuffix(pathname, suffix) {
return `${pathname}${suffix}`;
}
function matchesPrefix(pathname, prefix) {
return pathname === prefix.slice(0, -1) || pathname.startsWith(prefix);
}
function normalizeLookupPath(pathname) {
return pathname.endsWith('/') ? pathname : `${pathname}/`;
}
function normalizeRoutePath(pathname) {
const normalized = pathname.replace(/\/+$/, '');
return normalized || '/';
}
function isNotFoundPath(pathname) {
return pathname === '/404' || pathname === '/404.html' || pathname === '/404/';
}
function isDocsPath(pathname) {
return pathname === '/docs' || pathname.startsWith('/docs/') || pathname === '/cn/docs' || pathname.startsWith('/cn/docs/');
}
function collectDocsPaths(allDocsData) {
const paths = new Set();
for (const pluginData of Object.values(allDocsData)) {
for (const version of pluginData.versions || []) {
paths.add(normalizeRoutePath(version.path));
for (const doc of version.docs || []) {
paths.add(normalizeRoutePath(doc.path));
}
}
}
return paths;
}
function docsRootFor(pathname) {
const match = pathname.match(/^\/(cn\/)?docs(\/(?:next|docusaurus-[^/]+))?/);
if (!match) {
return pathname.startsWith('/cn/') ? '/cn/docs/' : '/docs/';
}
return `/${match[1] || ''}docs${match[2] || ''}/`;
}
function fallbackForMissingDocsPath(pathname) {
const docsRoot = docsRootFor(pathname);
if (pathname.includes('/changelog/')) {
return `${docsRoot}changelog/`;
}
return docsRoot;
}
function resolveDocsTarget(pathname, docsPaths) {
if (!isDocsPath(pathname) || docsPaths.has(normalizeRoutePath(pathname))) {
return pathname;
}
const fallback = fallbackForMissingDocsPath(pathname);
return docsPaths.has(normalizeRoutePath(fallback)) ? fallback : docsRootFor(pathname);
}
function toEnglish(pathname) {
if (isNotFoundPath(pathname)) {
return '/';
}
if (pathname === '/cn' || pathname === '/cn/') {
return '/';
}
const matchedPrefix = cnPrefixes.find((prefix) => matchesPrefix(pathname, prefix));
if (matchedPrefix) {
const englishPrefix = matchedPrefix.replace('/cn', '');
if (pathname === matchedPrefix.slice(0, -1)) {
return englishPrefix.slice(0, -1);
}
return pathname.replace(matchedPrefix, englishPrefix);
}
return pathname.startsWith('/cn/') ? pathname.replace(/^\/cn/, '') : pathname;
}
function toChinese(pathname) {
if (isNotFoundPath(pathname)) {
return '/cn/';
}
if (pathname === '/') {
return '/cn/';
}
if (pathname === '/cn' || pathname.startsWith('/cn/')) {
return pathname;
}
const fallback = enToCnFallbacks.get(normalizeLookupPath(pathname));
if (fallback) {
return fallback;
}
const matchedPrefix = enPrefixes.find((prefix) => matchesPrefix(pathname, prefix));
if (matchedPrefix) {
return `/cn${pathname}`;
}
return '/cn/';
}
export default function LanguageSwitcherNavbarItem(props) {
const location = useLocation();
const allDocsData = useAllDocsData();
const docsPaths = React.useMemo(() => collectDocsPaths(allDocsData), [allDocsData]);
const suffix = `${location.search}${location.hash}`;
const isChinese = location.pathname === '/cn/' || location.pathname.startsWith('/cn/');
const englishPath = resolveDocsTarget(toEnglish(location.pathname), docsPaths);
const chinesePath = resolveDocsTarget(toChinese(location.pathname), docsPaths);
return (
<DropdownNavbarItem
{...props}
label={isChinese ? '中文' : 'English'}
items={[
{
label: 'English',
to: appendSuffix(englishPath, suffix),
},
{
label: '中文',
to: appendSuffix(chinesePath, suffix),
},
]}
/>
);
}