New options, fixes and improvements

pull/3312/head
Babak Farkhoopak 5 months ago
parent 2bd4666e36
commit 19524cd5d4

@ -77,14 +77,7 @@ export function createRouter(
let latestPendingPath: string | null = null
async function loadPage(
href: string,
scrollPosition = 0,
isRetry = false,
alreadyTriedLoadingRootFallback = false
) {
let fallbackLoaded = false
async function loadPage(href: string, scrollPosition = 0, isRetry = false) {
if ((await router.onBeforePageLoad?.(href)) === false) return
const targetLoc = new URL(href, fakeHost)
const pendingPath = (latestPendingPath = targetLoc.pathname)
@ -159,11 +152,11 @@ export function createRouter(
} catch (e) {}
}
if (!alreadyTriedLoadingRootFallback) {
fallbackLoaded = await loadPageFallback()
if (siteDataRef.value.localesFallback) {
await loadFallback()
}
if (!fallbackLoaded && latestPendingPath === pendingPath) {
if (latestPendingPath === pendingPath) {
latestPendingPath = null
route.path = inBrowser ? pendingPath : withBase(pendingPath)
route.component = fallbackComponent ? markRaw(fallbackComponent) : null
@ -171,84 +164,74 @@ export function createRouter(
}
}
// If failed to find the page, maybe it's not translated yet! if so, please fallback :)
async function loadPageFallback() {
async function loadFallback() {
const locales = siteDataRef.value.locales
if (!locales) return fallbackLoaded
const namedLocales = Object.fromEntries(
Object.entries(siteDataRef.value.locales).filter(
([name]) => name !== 'root'
)
)
if (!Object.entries(namedLocales).length) return fallbackLoaded
const langNames = Object.keys(namedLocales)
const failedLang = langNames.find(
(lang) =>
pendingPath === `/${lang}` || pendingPath.startsWith(`/${lang}/`)
)
if (failedLang) {
const fallbackLang =
getFailedLangFallbackLang() ?? getCustomFallbackLang()
if (fallbackLang) {
await loadPage(
pendingPath.replace(`/${failedLang}`, `/${fallbackLang}`)
for (const [key, value] of Object.entries(locales)) {
if (!value.fallback) continue
if (value.fallback === 'root') {
throw new Error(
`Invalid Vitepress Config: A locale (${key}), cannot fallback to (root).`
)
return fallbackLoaded
} else {
await loadPage(pendingPath.replace(`/${failedLang}`, ''))
return fallbackLoaded
}
} else {
const rootRouteFallbackPath = getRootRouteFallbackPath()
if (rootRouteFallbackPath) {
await loadPage(rootRouteFallbackPath, 0, true, true)
if (key === value.fallback) {
throw new Error(
`Invalid Vitepress Config: A locale (${key}), cannot have a fallback to itself.`
)
}
return fallbackLoaded
}
function getFailedLangFallbackLang() {
const failedLangFallbackLang = locales[failedLang!]?.fallback
if (!failedLangFallbackLang) return
if (!langNames.includes(failedLangFallbackLang)) {
console.warn(
`Invalid value received in "VitePress Config" > "locales.${failedLang}.fallback". "${failedLangFallbackLang}" is not a valid value.`
if (!Object.keys(locales).includes(value.fallback)) {
throw new Error(
`Invalid Vitepress Config: A locale (${key}), cannot have a fallback to a non existing locale.`
)
return
}
}
return failedLangFallbackLang
// If the length is less than 2, it means there are no alternative locales to fallback to.
if (!locales || Object.keys(locales).length < 2) {
return
}
const nonRootLocales = Object.fromEntries(
Object.entries(locales).filter(([name]) => name !== 'root')
)
const failedLocaleKey =
Object.keys(nonRootLocales).find(
(lang) =>
pendingPath === `/${lang}` || pendingPath.startsWith(`/${lang}/`)
) || 'root'
if (failedLocaleKey !== 'root') {
const fallbackLang =
locales[failedLocaleKey].fallback ?? getCustomFallbackLang()
await loadPage(
pendingPath.replace(
`/${failedLocaleKey}`,
fallbackLang ? `/${fallbackLang}` : ''
),
scrollPosition,
true
)
} else {
const fallbackPath = getRootLocaleFallbackPath()
if (!fallbackPath) return
await loadPage(fallbackPath, scrollPosition, true)
}
function getCustomFallbackLang() {
const customFallbackLang = Object.entries(namedLocales).filter(
([_, values]) => values.useAsFallback
)?.[0]?.[0]
if (customFallbackLang && customFallbackLang !== failedLang) {
const customFallbackLang = siteDataRef.value.localesDefaultFallback
if (customFallbackLang && customFallbackLang !== failedLocaleKey) {
return customFallbackLang
}
}
function getRootRouteFallbackPath() {
const fallbackLang = locales['root']?.fallback
function getRootLocaleFallbackPath() {
const fallbackLang = locales['root'].fallback
if (!fallbackLang) return
if (!langNames.includes(fallbackLang)) {
console.warn(
`Invalid value received in "VitePress Config" > "locales.root.fallback". "${fallbackLang}" is not a valid value.`
)
return
}
return pendingPath === '/'
? `/${fallbackLang}`
: `/${fallbackLang}${
pendingPath.startsWith('/') ? pendingPath : `/${pendingPath}`
}`
if (pendingPath === '/') return `/${fallbackLang}`
const pathDivider = pendingPath.startsWith('/') ? '' : '/'
return `/${fallbackLang}${pathDivider}${pendingPath}`
}
}
}

@ -252,6 +252,8 @@ export async function resolveSiteData(
appearance: userConfig.appearance ?? true,
themeConfig: userConfig.themeConfig || {},
locales: userConfig.locales || {},
localesFallback: userConfig.localesFallback ?? true,
localesDefaultFallback: userConfig.localesDefaultFallback,
scrollOffset: userConfig.scrollOffset ?? 134,
cleanUrls: !!userConfig.cleanUrls,
contentProps: userConfig.contentProps

@ -69,6 +69,16 @@ export interface UserConfig<ThemeConfig = any>
locales?: LocaleConfig<ThemeConfig>
/**
* If a page isn't found in the current language, allow switching to another language as a backup.
*/
localesFallback?: boolean
/**
* Use a custom locale key to be used as a default fallback for all locales. Default is root.
*/
localesDefaultFallback?: string
router?: {
prefetchLinks?: boolean
}

12
types/shared.d.ts vendored

@ -124,6 +124,14 @@ export interface SiteData<ThemeConfig = any> {
| string[]
| { selector: string | string[]; padding: number }
locales: LocaleConfig<ThemeConfig>
/**
* If a page isn't found in the current language, allow switching to another language as a backup.
*/
localesFallback?: boolean
/**
* Use a custom locale key to be used as a default fallback for all locales. Default is root.
*/
localesDefaultFallback?: string
localeIndex?: string
contentProps?: Record<string, any>
router: {
@ -159,8 +167,10 @@ export type LocaleConfig<ThemeConfig = any> = Record<
LocaleSpecificConfig<ThemeConfig> & {
label: string
link?: string
/**
* If the requested page isn't found in this language, switch to the same page in the specified language as a backup.
*/
fallback?: string
useAsFallback?: boolean
}
>

Loading…
Cancel
Save