diff --git a/app/tags/[tag]/page.tsx b/app/tags/[tag]/page.tsx index 953deea..1b7c4e5 100644 --- a/app/tags/[tag]/page.tsx +++ b/app/tags/[tag]/page.tsx @@ -27,10 +27,12 @@ interface Props { export async function generateMetadata({ params }: Props): Promise { const { tag: slug } = await params; + // Decode the slug since Next.js encodes non-ASCII characters in URLs + const decodedSlug = decodeURIComponent(slug); // Find original tag label by slug const tag = allPosts .flatMap((post) => post.tags ?? []) - .find((t) => getTagSlug(t) === slug); + .find((t) => getTagSlug(t) === decodedSlug); return { title: tag ? `標籤:${tag}` : '標籤' @@ -39,13 +41,15 @@ export async function generateMetadata({ params }: Props): Promise { export default async function TagPage({ params }: Props) { const { tag: slug } = await params; + // Decode the slug since Next.js encodes non-ASCII characters in URLs + const decodedSlug = decodeURIComponent(slug); const posts = allPosts.filter( - (post) => post.tags && post.tags.some((t) => getTagSlug(t) === slug) + (post) => post.tags && post.tags.some((t) => getTagSlug(t) === decodedSlug) ); const tagLabel = - posts[0]?.tags?.find((t) => getTagSlug(t) === slug) ?? slug; + posts[0]?.tags?.find((t) => getTagSlug(t) === decodedSlug) ?? decodedSlug; return ( diff --git a/lib/posts.ts b/lib/posts.ts index 9828894..58a0b02 100644 --- a/lib/posts.ts +++ b/lib/posts.ts @@ -27,14 +27,14 @@ export function getPageBySlug(slug: string): Page | undefined { } export function getTagSlug(tag: string): string { - // Normalize spaces and convert to lowercase first + // Normalize spaces and convert to lowercase // Replace multiple spaces/dashes with single dash - const normalized = tag + // Next.js will handle URL encoding automatically, so we don't encode here + return tag .toLowerCase() .replace(/\s+/g, '-') - .replace(/-+/g, '-'); - // Encode URI components to handle non-ASCII characters properly - return encodeURIComponent(normalized); + .replace(/-+/g, '-') + .trim(); } export function getAllTagsWithCount(): { tag: string; slug: string; count: number }[] {