I am just learning nextjs little by little, and I wanted to make a multilanguage page, I am doing it with next-intl, but I am not very good at generatingMetadata, what I want is for it to be dynamic, right now with the code I have if it updates the metadatas , but only when the page loads, for example, if I want to share the link of my page, the og and twitter, it will come out by default and what I want is for each page to have a different title and load the og well , someone could help me?
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>
</>
);
}