2

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>
    </>
  );
}
GuniX
  • 21
  • 3

1 Answers1

0

To make the metadata dynamic in Next.js with next-intl, you can update the metadata tags in the Page component using the Head component from next/head and the useTranslations hook. Here's an example of how you can update the metadata dynamically:

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 */}
    </>
  );
}

In the useEffect hook, the updateMetaTags function is responsible for updating the metadata tags by selecting the appropriate tags based on their name or property attribute and setting their content attribute with the translated values from t. The document.title is also updated to set the page title.

Make sure you have the necessary translations for Articulos.Curiosidades_Secretos.id_1.PaginaHeader, Articulos.Curiosidades_Secretos.id_1.PaginaTitulo, and Articulos.Curiosidades_Secretos.id_1.PaginaImage in your translation files.

By using this approach, the metadata will be updated dynamically when the page loads, allowing for different titles and correctly loaded Open Graph (og) and Twitter tags when sharing the page link.

Sathya
  • 43
  • 1
  • 8