Перевод метаданных страницы

Настройка локализованных тегов <title> и <description>

Проблема

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

Решение

Используйте функцию Next.js generateMetadata в ваших страницах и макетах. Эта серверная функция может загружать правильные переводы на основе параметра lang (используя ту же логику загрузки словарей, что и ваши компоненты) и возвращать динамический объект metadata с локализованными заголовком и описанием.

Шаги

1. Создайте функцию для загрузки словарей

Вам нужен способ загружать ваши плоские файлы переводов на сервере. Создайте вспомогательную функцию для этого.

// app/get-dictionary.ts
import 'server-only';

type Messages = Record<string, string>;

const dictionaries: { [key: string]: () => Promise<Messages> } = {
  en: () => import('@/dictionaries/en.json').then((module) => module.default),
  es: () => import('@/dictionaries/es.json').then((module) => module.default),
};

export const getDictionary = async (lang: string) => {
  const load = dictionaries[lang];
  if (load) {
    return load();
  }
  return dictionaries.en();
};

2. Определите метаданные на странице

В вашем файле страницы (например, app/[lang]/about/page.tsx) экспортируйте асинхронную функцию с именем generateMetadata. Next.js автоматически вызовет ее при рендеринге страницы.

// app/[lang]/about/page.tsx
import { getDictionary } from '@/app/get-dictionary';
import type { Metadata } from 'next';

type Props = {
  params: { lang: string };
};

// Эта функция генерирует метаданные
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  // Загрузите словарь для этой страницы
  const dict = await getDictionary(params.lang);

  return {
    title: dict['about.title'], // например, "О нас" или "Sobre Nosotros"
    description: dict['about.description'],
  };
}

// Остальная часть вашего компонента страницы
export default function AboutPage() {
  return (
    <div>
      {/* Контент страницы */}
      <h1>...</h1>
    </div>
  );
}

3. Установите шаблон заголовка в корневом макете

Чтобы избежать повторения названия вашего сайта в каждом заголовке, вы можете установить шаблон в корневом макете.

// app/[lang]/layout.tsx
import { getDictionary } from '@/app/get-dictionary';
import type { Metadata } from 'next';

type Props = {
  params: { lang: string };
  children: React.ReactNode;
};

// Вы также можете генерировать метаданные в макетах
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const dict = await getDictionary(params.lang);

  return {
    // Это задает базовый заголовок и шаблон
    title: {
      default: dict['site.name'], // например, "Мой потрясающий сайт"
      template: `%s | ${dict['site.name']}`, // например, "О нас | Мой потрясающий сайт"
    },
    description: dict['site.description'],
  };
}

export default async function RootLayout({ children, params }: Props) {
  // ... остальная часть вашего макета (загрузка провайдеров и т.д.)
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}