typescript - ฉันสามารถสร้างเมตาดาต้าที่เปลี่ยนแปลงได้สำหรับแต่ละหน้าหลายภาษาโดยใช้ Next.js 13.4 และ next-intl ได้อย่างไร?
ฉันเพิ่งเริ่มเรียน nextjs ทีละเล็กทีละน้อย และฉันอยากทำหน้าเว็บหลายภาษา ฉันกำลังทำมันด้วย next-intl แต่ฉันไม่ค่อยเก่งในการสร้าง Metadata สิ่งที่ฉันอยากได้คือให้มันเป็นแบบไดนามิก ตอนนี้ด้วยโค้ดที่ฉันมี หากมันอัปเดต metadata ก็จะอัปเดตแค่ตอนโหลดหน้าเว็บเท่านั้น ตัวอย่างเช่น หากฉันอยากจะแชร์ลิงก์ของหน้าฉัน og และ twitter มันจะออกมาเป็นค่าเริ่มต้น และสิ่งที่ฉันอยากได้คือแต่ละหน้ามีชื่อเรื่องแตกต่างกันและโหลด og ได้อย่างถูกต้อง ใครช่วยฉันได้ไหม?
Layout.tsx:
import { NextIntlClientProvider } from "next-intl";
import { notFound } from "next/navigation";
import { createTranslator } from "next-intl";
import { Footer } from "@/components/Footer";
import { Nav } from "@/components/Nav";
import { Analytics } from "@vercel/analytics/react";
import "./globals.css";
interface LocaleLayoutProps {
children: React.ReactNode;
params: { locale: string };
}
export function generateStaticParams() {
return [
{ locale: "es" },
{ locale: "en" },
{ locale: "zh" },
{ locale: "hi" },
{ locale: "bn" },
{ locale: "pt" },
{ locale: "ru" },
{ locale: "ja" },
];
}
export async function generateMetadata({ params: { locale } }: LocaleLayoutProps) {
const messages = (await import(`../../messages/${locale}.json`)).default;
const t = createTranslator({ locale, messages });
return {
generator: "Next.js",
title: t("Metadata.title"),
description: t("Metadata.description"),
keywords: t("Metadata.keywords"),
applicationName: t("Metadata.title"),
type: "website",
icons: {
icon: "/logo.png",
shortcut: "/logo.png",
apple: "/logo.png",
},
twitter: {
card: "summary_large_image",
title: t("Metadata.title"),
description: t("Metadata.description"),
images: {
url: t("Metadata.image"),
},
app: {
name: "twitter_app",
id: {
iphone: "twitter_app://iphone",
ipad: "twitter_app://ipad",
googleplay: "twitter_app://googleplay",
},
url: {
iphone: "https://iphone_url",
ipad: "https://ipad_url",
},
},
},
openGraph: {
title: t("Metadata.title"),
description: t("Metadata.description"),
},
robots: {
index: false,
follow: true,
nocache: true,
googleBot: {
index: true,
follow: false,
noimageindex: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
};
}
export default async function LocaleLayout({ children, params: { locale } }: LocaleLayoutProps) {
let messages;
try {
messages = (await import(`../../messages/${locale}.json`)).default;
} catch (error) {
notFound();
}
return (
<html lang={locale}>
<body>
<NextIntlClientProvider locale={locale} messages={messages}>
<Analytics />
<Nav />
<div className='flex-grow'>{children}</div>
<Footer />
</NextIntlClientProvider>
</body>
</html>
);
}
Page.tsx:
"use client";
import { useTranslations } from "next-intl";
import Head from "next/head";
import { useEffect } from "react";
export default function Page() {
const t = useTranslations("Articulos.Curiosidades_Secretos.id_1");
useEffect(() => {
const updateMetaTags = () => {
const metaTags = [
{ name: "description", content: t("PaginaHeader") },
{ property: "og:title", content: t("PaginaTitulo") },
{ property: "og:description", content: t("PaginaHeader") },
{ property: "og:image", content: t("PagineImage") },
{ name: "twitter:title", content: t("PaginaTitulo") },
{ name: "twitter:description", content: t("PaginaHeader") },
{ name: "twitter:image", content: t("PagineImage") },
];
metaTags.forEach(({ name, property, content }) => {
const tag = document.querySelector(`meta[name="${name}"], meta[property="${property}"]`);
if (tag) {
tag.setAttribute("content", content);
}
});
};
updateMetaTags();
document.title = t("PaginaTitulo");
}, [t]);
return (
<>
<main className='w-4/5 mx-auto flex flex-col'>
...
</main>
</>
);
}
คำตอบ #1
เพื่อทำให้เมตาดาต้าเป็นแบบไดนามิกใน Next.js ด้วย next-intl คุณสามารถอัปเดตแท็กเมตาดาต้าในคอมโพเนนต์ Page โดยใช้คอมโพเนนต์ Head จาก next/head และ hook useTranslations นี่คือตัวอย่างวิธีที่คุณสามารถอัปเดตเมตาดาต้าได้อย่างไดนามิก:
Page.tsx:
import { useTranslations } from "next-intl";
import Head from "next/head";
import { useEffect } from "react";
export default function Page() {
const t = useTranslations("Articulos.Curiosidades_Secretos.id_1");
useEffect(() => {
const updateMetaTags = () => {
const metaTags = [
{ name: "description", content: t("PaginaHeader") },
{ property: "og:title", content: t("PaginaTitulo") },
{ property: "og:description", content: t("PaginaHeader") },
{ property: "og:image", content: t("PagineImage") },
{ name: "twitter:title", content: t("PaginaTitulo") },
{ name: "twitter:description", content: t("PaginaHeader") },
{ name: "twitter:image", content: t("PagineImage") },
];
metaTags.forEach(({ name, property, content }) => {
const tag = document.querySelector(`meta[name="${name}"], meta[property="${property}"]`);
if (tag) {
tag.setAttribute("content", content);
}
});
};
updateMetaTags();
document.title = t("PaginaTitulo");
}, [t]);
return (
<>
<Head>
<title>{t("PaginaTitulo")}</title>
</Head>
{/* Rest of your page content */}
</>
);
}
ใน hook useEffect ฟังก์ชัน updateMetaTags มีหน้าที่ในการอัปเดตแท็กเมตาโดยการเลือกแท็กที่เหมาะสมตามชื่อหรือแอตทริบิวต์ property ของพวกมันและตั้งค่าแอตทริบิวต์ content ด้วยค่าที่แปลแล้วจาก t นอกจากนี้ document.title ยังได้รับการอัปเดตเพื่อตั้งชื่อหน้าด้วย
ตรวจสอบให้แน่ใจว่าคุณมีการแปลที่จำเป็นสำหรับ Articulos.Curiosidades_Secretos.id_1.PaginaHeader, Articulos.Curiosidades_Secretos.id_1.PaginaTitulo, และ Articulos.Curiosidades_Secretos.id_1.PaginaImage ในแฟ้มการแปลของคุณ
โดยการใช้วิธีนี้ เมทาดาต้าจะถูกอัปเดตแบบไดนามิกเมื่อหน้าเว็บโหลด ทำให้สามารถมีชื่อเรื่องที่แตกต่างกันและแท็ก Open Graph (og) และ Twitter ถูกโหลดอย่างถูกต้องเมื่อแชร์ลิงก์หน้าเว็บ
