refactor: optimize multilingual article routing logic, modify slug to abbrlink

This commit is contained in:
radishzzz 2025-03-11 00:34:30 +00:00
parent 16491dae50
commit e5165dd740
16 changed files with 673 additions and 133 deletions

View file

@ -25,7 +25,7 @@ export async function checkSlugDuplication(posts: Post[]): Promise<string[]> {
posts.forEach((post) => {
const lang = post.data.lang || ''
const slug = post.data.slug || post.slug
const slug = post.data.abbrlink || post.slug
if (!slugMap.has(lang)) {
slugMap.set(lang, new Set())

View file

@ -20,7 +20,14 @@ export function getLangFromPath(path: string) {
export function getLocalizedPath(path: string, currentLang?: string) {
const clean = cleanPath(path)
const lang = currentLang || getLangFromPath(path)
return lang === defaultLocale ? `/${clean}` : `/${lang}/${clean}`
// 如果是根目录clean为空则返回/
if (clean === '') {
return lang === defaultLocale ? '/' : `/${lang}/`
}
// 其他路径正常处理
return lang === defaultLocale ? `/${clean}/` : `/${lang}/${clean}/`
}
export function isHomePage(path: string) {
@ -55,3 +62,27 @@ export function getPagePath(path: string) {
getLocalizedPath: (targetPath: string) => getLocalizedPath(targetPath, currentLang),
}
}
/**
*
* @param post
* @returns
*/
export function getAvailableLanguages(post?: { data?: { lang?: string } }) {
// 默认支持所有配置的语言
const defaultLangs = ['', ...themeConfig.global.moreLocale]
// 如果没有提供文章对象,返回所有语言
if (!post || !post.data) {
return defaultLangs
}
// 确定文章支持的语言
if (post.data.lang && typeof post.data.lang === 'string' && post.data.lang.trim() !== '') {
// 如果lang是字符串
return ['', post.data.lang]
}
// 如果没有指定或格式不对,返回所有语言
return defaultLangs
}

View file

@ -1,6 +1,9 @@
import type { CollectionEntry } from 'astro:content'
import { themeConfig } from '@/config'
// 获取默认语言
const defaultLocale = themeConfig.global.locale
export function generateLanguagePaths() {
return themeConfig.global.moreLocale.map(lang => ({
params: { lang },
@ -10,29 +13,77 @@ export function generateLanguagePaths() {
export function generatePostPaths(posts: CollectionEntry<'posts'>[]) {
return posts.map(post => ({
params: {
slug: post.data.slug || post.slug,
slug: post.data.abbrlink || post.slug,
},
props: { post },
}))
}
export function generateMultiLangPostPaths(posts: CollectionEntry<'posts'>[]) {
return themeConfig.global.moreLocale.flatMap(lang =>
posts.map(post => ({
params: {
lang,
slug: post.data.slug || post.slug,
},
props: { post },
})),
)
interface PathResult {
params: {
lang: string
slug: string
}
props: {
post: CollectionEntry<'posts'>
}
}
const result: PathResult[] = []
posts.forEach((post) => {
// 确定这篇文章应该生成哪些语言版本
let postLangs: string[] = themeConfig.global.moreLocale
if (post.data.lang && typeof post.data.lang === 'string' && post.data.lang.trim() !== '') {
// 如果lang是单个字符串转为数组
postLangs = [post.data.lang]
}
// 处理非默认语言的路径
postLangs.forEach((lang) => {
// 跳过默认语言,它将通过 generatePostPaths 生成
if (lang !== defaultLocale) {
result.push({
params: {
lang,
slug: post.data.abbrlink || post.slug,
},
props: { post },
})
}
})
// 如果文章支持默认语言,则生成无语言代码的路径
// 默认语言条件未指定lang属性或lang属性等于defaultLocale
const supportsDefaultLang = !post.data.lang
|| (typeof post.data.lang === 'string' && post.data.lang === defaultLocale)
if (supportsDefaultLang) {
// 默认语言的路径不包含语言代码,在这里用特殊参数标记
// 这将由 [slug].astro 页面处理不在URL中显示语言代码
result.push({
params: {
lang: 'default',
slug: post.data.abbrlink || post.slug,
},
props: { post },
})
}
})
return result
}
export function generateMultiLangTagPaths(tags: string[]) {
return themeConfig.global.moreLocale.flatMap(lang =>
tags.map(tag => ({
params: { lang, tag },
props: { tag },
})),
// 跳过默认语言,它将通过其他路径生成
lang !== defaultLocale
? tags.map(tag => ({
params: { lang, tag },
props: { tag },
}))
: [],
)
}

View file

@ -46,7 +46,7 @@ export async function generateRSS({ lang }: GenerateRSSOptions = {}) {
description: post.data.description || getExcerpt(post.body),
// Generate absolute URL with optional language prefix
link: new URL(
`${lang ? `${lang}/` : ''}posts/${post.data.slug || post.slug}/`,
`${lang ? `${lang}/` : ''}posts/${post.data.abbrlink || post.slug}/`,
url,
).toString(),
// Convert markdown content to HTML, allowing img tags