blog OK
This commit is contained in:
parent
6c3cdc2470
commit
62fc8d3355
@ -119,12 +119,18 @@ const currentLocale = ref(locale.value)
|
|||||||
// Get the slug from the route
|
// Get the slug from the route
|
||||||
const slug = route.params.slug
|
const slug = route.params.slug
|
||||||
const base = `/${Array.isArray(slug) ? slug.join('/') : slug}`
|
const base = `/${Array.isArray(slug) ? slug.join('/') : slug}`
|
||||||
// Our list links to /blog/{locale}/{slug}, remove /blog prefix to query content file
|
// Our list links to /blog/{locale}/{slug}, derive content path
|
||||||
const articlePath = base.replace(/^\/blog(?=\/)/, '')
|
const articlePath = base.replace(/^\/blog(?=\/)/, '')
|
||||||
|
// Remove leading locale segment for @nuxt/content when using locales option
|
||||||
|
const normalizedPath = articlePath.replace(/^\/(en|zh|zh-hant)(?=\/)/, '')
|
||||||
|
|
||||||
// Fetch the article
|
// Fetch the article: prefer normalized path with _locale, fallback to original path
|
||||||
const { data: article, pending, error } = await useAsyncData(`article-${articlePath}`, async () => {
|
const { data: article, pending, error } = await useAsyncData(`article-${articlePath}`, async () => {
|
||||||
try {
|
try {
|
||||||
|
const localized = await queryContent(normalizedPath)
|
||||||
|
.where({ _locale: locale.value })
|
||||||
|
.findOne()
|
||||||
|
if (localized) return localized
|
||||||
return await queryContent(articlePath).findOne()
|
return await queryContent(articlePath).findOne()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error fetching article:', err)
|
console.error('Error fetching article:', err)
|
||||||
@ -159,7 +165,9 @@ const switchToTranslation = async (targetLocale) => {
|
|||||||
const base = articlePath.replace(/^\/(en|zh|zh-hant)/,'')
|
const base = articlePath.replace(/^\/(en|zh|zh-hant)/,'')
|
||||||
const translated = await queryContent(`/${targetLocale}${base}`).findOne()
|
const translated = await queryContent(`/${targetLocale}${base}`).findOne()
|
||||||
if (translated?._path) {
|
if (translated?._path) {
|
||||||
await navigateTo(`/blog${translated._path}`)
|
const appPrefix = targetLocale === 'en' ? '' : `/${targetLocale}`
|
||||||
|
const slugPath = translated._path.replace(/^\/(en|zh|zh-hant)(?=\/)/, '')
|
||||||
|
await navigateTo(`${appPrefix}/blog${slugPath}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error('Not found')
|
throw new Error('Not found')
|
||||||
|
|||||||
@ -119,14 +119,12 @@ const { data: articles, pending, error } = await useAsyncData(() => `blog-${loca
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Build localized link for article
|
// Build localized link for article (app-level locale prefix + blog + slug without locale)
|
||||||
const articleLink = (a) => {
|
const articleLink = (a) => {
|
||||||
if (!a || !a._path) return '/blog'
|
if (!a || !a._path) return '/blog'
|
||||||
const hasLocale = /^\/(en|zh|zh-hant)(\/|$)/.test(a._path)
|
const appPrefix = locale.value === 'en' ? '' : `/${locale.value}`
|
||||||
const localized = hasLocale
|
const slugPath = a._path.replace(/^\/(en|zh|zh-hant)(?=\/)/, '')
|
||||||
? a._path
|
return `${appPrefix}/blog${slugPath}`
|
||||||
: (locale.value === 'en' ? a._path : `/${locale.value}${a._path}`)
|
|
||||||
return `/blog${localized}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const availableLocales = computed(() =>
|
const availableLocales = computed(() =>
|
||||||
@ -148,7 +146,9 @@ const switchToTranslation = async (article, targetLocale) => {
|
|||||||
const basePath = article._path.replace(/^\/(en|zh|zh-hant)/, '')
|
const basePath = article._path.replace(/^\/(en|zh|zh-hant)/, '')
|
||||||
const translated = await queryContent(`/${targetLocale}${basePath}`).findOne()
|
const translated = await queryContent(`/${targetLocale}${basePath}`).findOne()
|
||||||
if (translated?._path) {
|
if (translated?._path) {
|
||||||
await navigateTo(`/blog${translated._path}`)
|
const appPrefix = targetLocale === 'en' ? '' : `/${targetLocale}`
|
||||||
|
const slugPath = translated._path.replace(/^\/(en|zh|zh-hant)(?=\/)/, '')
|
||||||
|
await navigateTo(`${appPrefix}/blog${slugPath}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
throw new Error('Not found')
|
throw new Error('Not found')
|
||||||
|
|||||||
@ -174,7 +174,9 @@ const { data: articles, pending } = await useAsyncData(() => `home-articles-${lo
|
|||||||
|
|
||||||
const articleLink = (a) => {
|
const articleLink = (a) => {
|
||||||
if (!a || !a._path) return '/blog'
|
if (!a || !a._path) return '/blog'
|
||||||
return `/blog${a._path}`
|
const appPrefix = locale.value === 'en' ? '' : `/${locale.value}`
|
||||||
|
const slugPath = a._path.replace(/^\/(en|zh|zh-hant)(?=\/)/, '')
|
||||||
|
return `${appPrefix}/blog${slugPath}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Services data
|
// Services data
|
||||||
|
|||||||
40
server/middleware/content-redirect.ts
Normal file
40
server/middleware/content-redirect.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { defineEventHandler, getRequestURL, sendRedirect } from 'h3'
|
||||||
|
// @ts-ignore: runtime module from @nuxt/content
|
||||||
|
import { queryContent } from '#content/server'
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const url = getRequestURL(event)
|
||||||
|
const path = url.pathname
|
||||||
|
|
||||||
|
// Match top-level locale-prefixed paths like /en/slug, /zh/slug, /zh-hant/slug
|
||||||
|
const match = path.match(/^\/(en|zh|zh-hant)(\/.*)$/)
|
||||||
|
if (!match) return
|
||||||
|
|
||||||
|
const locale = match[1]
|
||||||
|
const rest = match[2] // includes leading '/'
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if a content doc exists for this locale and slug
|
||||||
|
const doc = await queryContent(event)
|
||||||
|
.where({ _locale: locale, _path: `/${locale}${rest}` })
|
||||||
|
.findOne()
|
||||||
|
|
||||||
|
// If not found by _path, also try querying by normalized path with _locale filter
|
||||||
|
const normalized = rest // e.g., /getting-started-aws-ec2
|
||||||
|
const fallback = doc || await queryContent(event)
|
||||||
|
.where({ _locale: locale })
|
||||||
|
.path(normalized)
|
||||||
|
.findOne()
|
||||||
|
|
||||||
|
if (fallback) {
|
||||||
|
const appPrefix = locale === 'en' ? '' : `/${locale}`
|
||||||
|
const target = `${appPrefix}/blog${rest}`
|
||||||
|
// 301 permanent redirect
|
||||||
|
return sendRedirect(event, target, 301)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore errors and let normal routing continue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
6
types/content-server.d.ts
vendored
Normal file
6
types/content-server.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
declare module '#content/server' {
|
||||||
|
export function queryContent(event?: any): any
|
||||||
|
export function serverQueryContent(event?: any): any
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user