Как перевести метаданные страницы в Next.js (Pages Router) v16

Перевод метаданных для поиска и социальных сетей

Проблема

Метаданные страницы — заголовки и описания — находятся вне основного содержимого страницы. Они отображаются на вкладках браузера, в закладках, в результатах поисковых систем и в предварительных просмотрах в социальных сетях. Когда метаданные не соответствуют языку страницы, пользователи сталкиваются с резким несоответствием ещё до того, как увидят содержимое. Испанская страница с английским заголовком сбивает посетителей с толку и указывает на низкое качество локализации.

Поисковые системы интерпретируют несоответствие языков как признак низкого качества локализации, что может привести к снижению рейтинга в языковых результатах. Социальные сети отображают неверный язык в предварительных просмотрах ссылок, что снижает вовлечённость международной аудитории. Последовательный перевод на всех уровнях, включая метаданные, необходим для профессионального многоязычного опыта.

Решение

Переводите метаданные страницы, используя те же ресурсы перевода, что и для содержимого страницы. Используйте хук useIntl из react-intl для доступа к переведённым строкам и размещайте их в компоненте <Head> страницы. Это гарантирует, что заголовки и описания будут соответствовать текущей локали в вкладках браузера, результатах поиска и предварительных просмотрах в социальных сетях.

Используя метаданные из тех же каталогов сообщений, что и видимое содержимое, вы сохраняете последовательность и избегаете дублирования усилий по переводу. Этот подход работает как для статических страниц, так и для динамических маршрутов, где метаданные зависят от данных, специфичных для страницы.

Шаги

1. Добавьте сообщения метаданных в ваши файлы перевода

Определите дескрипторы сообщений для заголовков и описаний страниц в ваших каталогах перевода, используя ту же структуру, что и для другого переведённого содержимого.

{
"home.title": "Добро пожаловать в наш магазин",
"home.description": "Откройте для себя удивительные товары по отличным ценам",
"products.title": "Наши товары",
"products.description": "Просмотрите наш полный каталог товаров"
}

Каждая страница, для которой нужны переведённые метаданные, должна иметь соответствующие идентификаторы сообщений для её заголовка и описания.

2. Создайте компонент переведенных метаданных

Используйте хук useIntl для доступа к функции formatMessage, а затем отобразите переведенные строки внутри компонента Head.

import Head from "next/head";
import { useIntl } from "react-intl";

export default function HomePage() {
  const intl = useIntl();

  return (
    <>
      <Head>
        <title>{intl.formatMessage({ id: "home.title" })}</title>
        <meta
          name="description"
          content={intl.formatMessage({ id: "home.description" })}
        />
      </Head>
      <main>
        <h1>{intl.formatMessage({ id: "home.title" })}</h1>
      </main>
    </>
  );
}

Компонент Head — это React-компонент, встроенный в Next.js, который позволяет изменять <head> страницы. Функция formatMessage возвращает переведенную строку для текущей локали.

3. Добавьте метаданные Open Graph и социальных сетей

Расширьте шаблон, чтобы включить метаданные Open Graph и Twitter Card для предварительного просмотра в социальных сетях.

import Head from "next/head";
import { useIntl } from "react-intl";

export default function ProductsPage() {
  const intl = useIntl();
  const title = intl.formatMessage({ id: "products.title" });
  const description = intl.formatMessage({ id: "products.description" });

  return (
    <>
      <Head>
        <title>{title}</title>
        <meta name="description" content={description} />
        <meta property="og:title" content={title} />
        <meta property="og:description" content={description} />
        <meta name="twitter:title" content={title} />
        <meta name="twitter:description" content={description} />
      </Head>
      <main>
        <h1>{title}</h1>
      </main>
    </>
  );
}

Сохранение отформатированных сообщений в переменных позволяет избежать многократного вызова formatMessage для одного и того же перевода и делает JSX более чистым.

4. Обрабатывайте динамические метаданные для страниц с параметрами

Для страниц с динамическими маршрутами объедините параметры маршрута с переведенными строками, чтобы создать контекстные метаданные.

import Head from "next/head";
import { useIntl } from "react-intl";
import { useRouter } from "next/router";

export default function ProductDetailPage() {
  const intl = useIntl();
  const router = useRouter();
  const { id } = router.query;

  const title = intl.formatMessage(
    { id: "product.detail.title" },
    { productId: id },
  );

  return (
    <>
      <Head>
        <title>{title}</title>
      </Head>
      <main>
        <h1>{title}</h1>
      </main>
    </>
  );
}

Описатели сообщений поддерживают интерполяцию переменных, что позволяет вставлять динамические значения, такие как идентификаторы или названия продуктов, в переведенные строки метаданных. Соответствующее сообщение может быть "Продукт {productId} - Наш магазин".