Как в Next.js корректно организовать структуру мультиязычных URL, чтобы обеспечить оптимальную SEO-оптимизацию?

Делаю мультиязычный сайт на Next.js (App Router). Есть русская (RU) и английская (EN) версии. Сейчас рассматриваю такую структуру URL:
  • 7 мая 2026 г. 7:01
Ответы на вопрос 1
Коротко — для SEO лучше всего использовать префиксы в путях (/ru/, /en/) + корректные rel="alternate" (hreflang) и канонические URL. Ниже — почему и как это правильно организовать в Next.js (App Router) с конкретными рекомендациями и примерами кода.

Почему префиксы в путях (recommended)
- Google рекомендует отдельные URL для каждой языковой версии (поддомены, субдиректории или ccTLD). Субдиректории (/en/, /ru/) проще в настройке и управлении.
- Явный URL позволяет ссылкам, индексации и ссылочному весу быть привязанными к конкретной локали.
- Итого: используйте /en/... и /ru/... (а не ?lang= или cookies-only).

Структура папок (App Router)
Простой и гибкий вариант — динамический сегмент [lang], чтобы переиспользовать лэйауты и логику:
app/
  [lang]/
    layout.tsx
    page.tsx             // /ru и /en
    about/
      page.tsx           // /ru/about и /en/about
    blog/
      [slug]/
        page.tsx
  layout.tsx             // глобальный root, можно здесь делать редирект/детект

Пример layout для локали (app/[lang]/layout.tsx):
- ставим атрибут lang на тег html (важно для доступа поисковиков и доступности).
- используем params.lang для выбора текста/локали.

Пример:
export default function LocaleLayout({ children, params }) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

Генерация метаданных (hreflang + canonical)
В App Router можно использовать metadata API (generateMetadata) либо вручную вставлять теги <link rel="alternate"> и <link rel="canonical">. Лучше: в каждой странице/лейауте сгенерировать alternates для всех локалей.

Пример generateMetadata (в app/[lang]/page.tsx или layout):
export async function generateMetadata({ params }) {
  const base = 'https://example.com';
  const lang = params.lang; // 'ru' или 'en'
  return {
    alternates: {
      canonical: `${base}/${lang}`,
      languages: {
        ru: `${base}/ru`,
        en: `${base}/en`
      }
    }
  };
}

Если вы не используете metadata API, добавьте вручную:
<link rel="alternate" href="https://example.com/ru/page" hreflang="ru" />
<link rel="alternate" href="https://example.com/en/page" hreflang="en" />
<link rel="alternate" href="https://example.com/" hreflang="x-default" />  // по желанию

Sitemap
Генерируйте sitemap.xml (или sitemap index) с URL-ами для всех локалей. Можно также включать hreflang в sitemap. Это улучшает обнаружение версий страницы.

Canonical и duplicate content
- Каждая локализованная страница должна иметь ссылку canonical на свой собственный URL.
- Не дублируйте контент без hreflang/canonical — это может привести к падению SEO.

Redirects / Detect language
- Авто-редиректы с корня (/) на /ru или /en можно сделать, но будьте осторожны: для SEO лучше давать уникальные URL и не полагаться только на Accept-Language.
- Если делаете редирект по заголовку Accept-Language, используйте временный редирект (302/307), чтобы не «закладывать» его в индекс навсегда. Также не редиректите поисковых роботов — лучше показать выбор языка или ссылку на другие версии.
Пример middleware для редиректа корня:
import { NextResponse } from 'next/server';
export function middleware(req) {
  const url = req.nextUrl.clone();
  if (url.pathname === '/') {
    // простая логика — детект по headers или fallback
    const accept = req.headers.get('accept-language') || '';
    const lang = accept.startsWith('en') ? 'en' : 'ru';
    url.pathname = `/${lang}`;
    return NextResponse.redirect(url);
  }
  return NextResponse.next();
}

i18n в next.config.js
Next.js поддерживает встроенную i18n-конфигурацию:
module.exports = {
  i18n: {
    locales: ['ru', 'en'],
    defaultLocale: 'ru',
    localeDetection: true
  }
}
Учтите: встроенная i18n влияет на поведение маршрутизации и автоматическое добавление префикса для defaultLocale (по умолчанию Next может не добавлять префикс для defaultLocale). Если хотите, чтобы для defaultLocale тоже использовался префикс (/ru), проще сделать структуру вручную через app/[lang] (или дополнительно настроить маршрутизацию).

SEO-практики и чеклист
- Используйте отдельные URL (/ru/, /en/).
- Для каждой страницы добавьте rel="alternate" hreflang для всех локалей + x-default при необходимости.
- Установите canonical на соответствующую локаль.
- Установите атрибут lang в теге <html>.
- Генерируйте sitemap с URL для всех локалей.
- Рендерьте контент на стороне сервера (SSR или SSG) для лучшей индексации.
- Не используйте только cookie/JS-переключение языка без изменения URL.
- По возможности переводите не только текст, но и метаданные (title, description) для каждой локали.

Итого: оптимальная схема — префиксы /ru/ и /en/, корректные hreflang и canonical, lang на html, sitemap со всеми локалями, SSG/SSR и аккуратные редиректы. Если нужно — могу дать готовый минимальный репозиторий/пример проекта с реализацией (app/[lang] структура, middleware, generateMetadata и скрипт генерации sitemap).
Похожие вопросы