# General Translation Knowledge Base: Как настроить SEO для многоязычного приложения Next.js?
URL: https://generaltranslation.com/ru/kb/multilingual-nextjs-seo.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Выделите каждому языку собственный URL, задайте атрибут lang у тега html, укажите для каждой страницы канонический URL, ведущий на неё саму, добавьте альтернативные версии hreflang для всех языков, переведите заголовки и описания и перечислите все языковые версии в карте сайта.
Category: Многоязычное SEO
Last updated: 2026-02-17
Authors: General Translation Team
Published: 2026-02-17

## Video

The video is narrated in English, with English captions.

[How do I set up SEO for a multilingual Next.js app?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-multilingual-nextjs-seo.mp4) (50 с)

General Translation lets you give every language its own URL and tell search engines about them. Move your pages into `app/[locale]` with `gt-next`'s middleware, set the html `lang` attribute with `useLocale`, add canonical and hreflang links with a helper, translate the title with `getGT`, and list every page in every language in a sitemap.

## Почему многоязычному SEO нужно уделить особое внимание

Большинство разработчиков, добавляющих i18n в своё приложение Next.js, ограничиваются переводом UI и считают работу законченной.
Но если поисковые системы не могут найти и проиндексировать языковые версии вашего сайта и правильно связать их между собой,
вся работа по переводу пропадает впустую.

Многоязычный сайт без правильной настройки SEO сталкивается с проблемами:

* Google может проиндексировать только одну языковую версию и проигнорировать остальные
* Пользователи, которые ищут на испанском, попадают на английскую страницу
* Возникают санкции за дублирующийся контент, поскольку Google считает `/en/about` и `/fr/about` одной и той же страницей
* В сниппетах поисковой выдачи отображается не тот язык

**Хорошая новость:** правильно настроить многоязычное SEO в Next.js несложно.
Достаточно учесть шесть моментов, и в этом руководстве все они рассмотрены на примере [`gt-next`](/docs/react/nextjs-quickstart).

***

## 1. Маршрутизация URL с учётом локали

Основа многоязычного SEO — отдельный URL для каждого языка.
Поисковым системам нужны отдельные URL, доступные для сканирования, чтобы индексировать каждую языковую версию независимо.

Иными словами, нужна **локаль в URL**, а не cookie-файлы, не параметры строки запроса и не одно лишь определение языка по `Accept-Language`.

```text
✅ generaltranslation.com/en/about
✅ generaltranslation.com/fr/about
✅ generaltranslation.com/es/about

❌ generaltranslation.com/about?lang=fr
❌ generaltranslation.com/about (локаль хранится в cookie-файле)
```

### Настройка маршрутизации по локалям с помощью gt-next

Сначала разместите страницы внутри динамического сегмента `[locale]`:

```text
app/
└── [locale]/
    ├── layout.tsx
    ├── page.tsx
    └── about/
        └── page.tsx
```

Затем создайте промежуточное ПО в корневом каталоге проекта (`proxy.ts` для Next.js 16+ или `middleware.ts` для Next.js 15 и более ранних версий):

```ts title="proxy.ts"
import { createNextMiddleware } from 'gt-next/middleware';

export default createNextMiddleware();

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

Так вы автоматически получаете URL-адреса с префиксом локали.
По умолчанию для локали по умолчанию (например, английской) префикс не добавляется — `/about` остаётся без изменений,
а испаноязычные пользователи видят `/es/about`, франкоязычные — `/fr/about`.

***

## 2. Установка HTML-атрибута `lang`

Атрибут `lang` в теге `<html>` сообщает браузерам и поисковым системам, на каком языке написана страница.
Это одна из самых простых и при этом самых действенных мер для улучшения доступности и SEO.

Без него программы экранного доступа пытаются угадать язык (и часто ошибаются), а поисковые системы менее уверенно определяют язык страницы.

{/* useLocale работает в компонентах с рендерингом как на клиенте, так и на сервере, но не в асинхронных компонентах */}

gt-next предоставляет хук [`useLocale`](/docs/react/reference/hooks/use-locale), с которым в корневом макете это делается элементарно:

```tsx title="app/[locale]/layout.tsx"
import { useLocale, GTProvider } from 'gt-next';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const locale = useLocale();

  return (
    <html lang={locale}>
      <body>
        <GTProvider>
          {children}
        </GTProvider>
      </body>
    </html>
  );
}
```

[`useLocale`](/docs/react/reference/hooks/use-locale) возвращает код локали в формате BCP 47 (например, `en-US`, `ar`, `zh-Hans`).

***

## 3. Канонические URL-адреса

Канонические теги сообщают поисковым системам, какой URL-адрес является «основной» версией страницы.
На многоязычных сайтах каждая языковая версия должна указывать как на каноническую на саму себя:

```html
<!-- На странице /fr/about -->
<link rel="canonical" href="https://example.com/fr/about" />
```

Так поисковые системы не будут считать вашу французскую страницу дубликатом английской.

В Next.js канонические URL задаются через [API метаданных](https://nextjs.org/docs/app/api-reference/functions/generate-metadata).
Используйте его вместе с [`getLocale`](/docs/react/nextjs/reference/functions/get-locale) из gt-next, чтобы генерировать правильный канонический URL для каждой локали:

```tsx title="app/[locale]/about/page.tsx"
import { getLocale } from 'gt-next/server';

const BASE_URL = 'https://example.com';

export async function generateMetadata() {
  const locale = await getLocale();

  return {
    alternates: {
      canonical: `${BASE_URL}/${locale}/about`,
    },
  };
}

export default function AboutPage() {
  return <h1>About Us</h1>;
}
```

Если для локали по умолчанию префикс не используется, внесите соответствующие изменения:

```tsx
import { getDefaultLocale } from 'gt-next';
import { getLocale } from 'gt-next/server';

export async function generateMetadata() {
  const locale = await getLocale();
  const defaultLocale = getDefaultLocale();
  const path = '/about';

  const prefix = locale === defaultLocale ? '' : `/${locale}`;

  return {
    alternates: {
      canonical: `${BASE_URL}${prefix}${path}`,
    },
  };
}
```

***

## 4. Теги hreflang

Теги hreflang — важнейший сигнал для многоязычного SEO.
Они сообщают поисковым системам: «эта страница доступна и на других языках, вот их URL-адреса».

Без hreflang Google вынужден угадывать, какую языковую версию показать в результатах поиска, — и нередко ошибается.

```html
<link rel="alternate" hreflang="en" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
```

Тег `x-default` сообщает поисковым системам, какой URL показывать, если ни один из указанных языков не подходит пользователю.

В Next.js hreflang можно добавить с помощью свойства `alternates.languages` в API метаданных.
Вот универсальная вспомогательная функция для работы с gt-next:

```tsx title="lib/i18n-metadata.ts"
import { getDefaultLocale } from 'gt-next';
import { getLocale } from 'gt-next/server';

const BASE_URL = 'https://example.com';
const SUPPORTED_LOCALES = ['en', 'fr', 'es'];

export async function getI18NMetadata(path: string) {
  const locale = await getLocale();
  const defaultLocale = getDefaultLocale();

  const getUrl = (loc: string) => {
    const prefix = loc === defaultLocale ? '' : `/${loc}`;
    return `${BASE_URL}${prefix}${path}`;
  };

  const languages: Record<string, string> = {};
  for (const loc of SUPPORTED_LOCALES) {
    languages[loc] = getUrl(loc);
  }
  languages['x-default'] = getUrl(defaultLocale);

  return {
    alternates: {
      canonical: getUrl(locale),
      languages,
    },
  };
}
```

Затем используйте его на любой странице:

```tsx title="app/[locale]/about/page.tsx"
import { getI18NMetadata } from '@/lib/i18n-metadata';

export async function generateMetadata() {
  return await getI18NMetadata('/about');
}
```

Так за один вызов генерируются и канонический тег, и все теги hreflang.

***

## 5. Переведённые метаданные

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

Чтобы перевести строки метаданных, используйте функцию [`getGT`](/docs/react/nextjs/reference/functions/get-gt) из gt-next:

```tsx title="app/[locale]/about/page.tsx"
import { getGT } from 'gt-next/server';
import { getI18NMetadata } from '@/lib/i18n-metadata';

export async function generateMetadata() {
  const t = await getGT();
  const i18nMeta = await getI18NMetadata('/about');

  return {
    title: t('About Us'),
    description: t('Learn about our mission and team.'),
    ...i18nMeta,
  };
}
```

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

***

## 6. Многоязычные карты сайта

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

Next.js поддерживает [программную генерацию карт сайта](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap) с помощью файла `sitemap.ts`:

```ts title="app/sitemap.ts"
import { MetadataRoute } from 'next';

const BASE_URL = 'https://example.com';
const LOCALES = ['en', 'fr', 'es'];
const DEFAULT_LOCALE = 'en';
const PAGES = ['/', '/about', '/blog', '/contact'];

export default function sitemap(): MetadataRoute.Sitemap {
  return PAGES.flatMap((path) => {
    const getUrl = (locale: string) => {
      const prefix = locale === DEFAULT_LOCALE ? '' : `/${locale}`;
      return `${BASE_URL}${prefix}${path === '/' ? '' : path}`;
    };

    const languages: Record<string, string> = {};
    for (const locale of LOCALES) {
      languages[locale] = getUrl(locale);
    }

    return LOCALES.map((locale) => ({
      url: getUrl(locale),
      lastModified: new Date(),
      alternates: { languages },
    }));
  });
}
```

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

***

## Чек-лист

Краткая сводка всего, что мы рассмотрели:

| Требование SEO           | Реализация                                                                                                                    |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| Локаль в URL             | [`createNextMiddleware()`](/docs/react/nextjs/reference/functions/create-next-middleware) с динамическим сегментом `[locale]` |
| HTML-атрибут `lang`      | [`useLocale()`](/docs/react/reference/hooks/use-locale) в корневом макете                                                     |
| Канонические URL         | [`getLocale()`](/docs/react/nextjs/reference/functions/get-locale) + `alternates.canonical` из API метаданных Next.js         |
| Теги hreflang            | `alternates.languages` из API метаданных Next.js со всеми поддерживаемыми локалями                                            |
| Переведённые метаданные  | [`getGT()`](/docs/react/nextjs/reference/functions/get-gt) для заголовков и описаний страниц                                  |
| Многоязычная карта сайта | `sitemap.ts` с записями для каждой локали и альтернативными версиями hreflang                                                 |

***

Чтобы настроить полный стек интернационализации, воспользуйтесь руководством [«Быстрый старт» для `gt-next`](/docs/react/nextjs-quickstart). Затем настройте маршрутизацию по [руководству по промежуточному ПО](/docs/react/nextjs/app-router-middleware), сгенерируйте многоязычные страницы с помощью [генерации статических сайтов](/docs/react/nextjs/app-router-static-site-generation) и добавьте [поддержку right-to-left](/docs/react/guides/managing-locales).

## Related questions

- [Можно ли реализовать i18n без файлов перевода?](https://generaltranslation.com/ru/kb/i18n-without-translation-files.mdx): Да. С gt-react или gt-next контент остаётся встроенным прямо в ваши компоненты внутри компонента `<T>`, а переводы генерируются во время сборки, поэтому не нужно писать ключи и JSON-файлы для каждой локали и следить за их синхронизацией.
- [Какое ПО для локализации лучше всего подходит разработчикам?](https://generaltranslation.com/ru/kb/best-localization-software.mdx): Ищите единую систему, которая охватывает весь конвейер — от библиотеки интернационализации в вашем коде до перевода и доставки, — а не собирайте по частям отдельную библиотеку, систему управления переводами и поставщика переводов.
- [Что проверить перед запуском многоязычного приложения?](https://generaltranslation.com/ru/kb/multilingual-app-launch-checklist.mdx): Перед запуском многоязычного приложения проверьте девять аспектов в каждой поддерживаемой локали: пользовательские сценарии целиком, включая ошибки; определение и переключение языка; переменные и формы множественного числа; валюту и часовые пояса; увеличение длины текста; вёрстку для языков с письмом справа налево; доступность; доставку переводов в рабочей среде; индексируемые языковые URL для SEO. Для каждой проверки нужен явный критерий успешного прохождения.

## Previous and next questions

- Previous question: [Как перевести условный текст в JSX?](https://generaltranslation.com/ru/kb/translate-conditional-jsx.mdx)
- Next question: [Какое ПО для локализации лучше всего подходит разработчикам?](https://generaltranslation.com/ru/kb/best-localization-software.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ru/kb/sitemap.md) for every article.
