Как перевести веб-сайт Next.js (маршрутизатор приложений и без кода)

Два способа перевода веб-сайта Next.js: интернационализация App Router с маршрутами [lang], proxy.js, словарями и метаданными hreflang или скрипт без кода с переведенными URL-адресами, удобными для SEO.
Нет данных карты Никаких обязательств

· Обновлено · Алекс Б · Блог

Подведите итог этому посту следующим образом: 9 мин чтения

Существует два способа перевода сайта Next.js. The кодовый маршрут: поместите каждый маршрут под app/[lang] сегмент, определить язык посетителя в proxy.js, загрузите словарь перевода для каждой локали и выведите теги hreflang с помощью alternates поле метаданных. The маршрут без кода: добавьте скрипт службы перевода в корневой макет и позвольте ему переводить отрендеренные страницы, при этом переведенные URL-адреса будут обслуживаться из подкаталога или поддомена для SEO.

Маршрут кода дает вам полный контроль и работает лучше всего, когда текст находится в вашей кодовой базе и разработчик поддерживает его. Маршрут без кода быстрее, когда текст поступает из CMS, когда лицам, не являющимся разработчиками, необходимо редактировать переводы или когда вам нужно одновременно использовать несколько языков. В этом руководстве показаны оба варианта на основе документации Next.js 16, а в конце приводится контрольный список для многоязычного SEO в любом случае.

Ключевые выводы

  • Маршрутизатор приложений: вложенные страницы под app/[lang], перенаправить в proxy.js (называется middleware.js перед Next.js 16) загрузите словари JSON в компоненты сервера и выполните предварительную визуализацию локалей с помощью generateStaticParams.
  • Маршрутизатор страниц: используйте встроенный i18n конфигурация в next.config.js. Это не работает с output: 'export'.
  • Next.js не добавляет для вас hreflang. В маршрутизаторе приложений используйте alternates.languages в generateMetadata.
  • Вариант без кода — один из них <Script> тег в app/layout.tsx. Для индексируемых переведенных страниц используйте настройку подкаталога или поддомена, а не перевод только в браузере.
  • Какой бы маршрут вы ни выбрали, установите <html lang>, переводить заголовки и описания и связывать каждую языковую версию с hreflang.

Вариант 1: Интернационализация Next.js с помощью App Router

Это следует из официальное руководство по интернационализации Next.js (версия 16.3 на момент написания статьи).

Шаг 1: Поместите свои маршруты в языковой сегмент

Переместите свои страницы и макеты в app/[lang]/. Затем каждая страница получает локаль в качестве параметра маршрута:

// app/[lang]/page.tsx
export default async function Page({ params }: PageProps<'/[lang]'>) {
  const { lang } = await params;
  return <h1>{lang}</h1>;
}

Маршрутизация может использовать подпуть (/fr/products) или домен (my-site.fr/products). Подпуть проще размещать, и все языки хранятся в одном домене.

Шаг 2: Определите язык и перенаправьте в proxy.js

В Next.js 16 middleware соглашение о файлах было переименовано в proxy (есть кодовый мод: npx @next/codemod@canary middleware-to-proxy .). Прокси-сервер проверяет, есть ли у URL-адреса локаль, и если нет, перенаправляет:

// proxy.js
import { NextResponse } from 'next/server';

const locales = ['en', 'fr', 'de'];

function getLocale(request) {
  // Read Accept-Language, e.g. with @formatjs/intl-localematcher and negotiator
  return 'en';
}

export function proxy(request) {
  const { pathname } = request.nextUrl;
  const hasLocale = locales.some((l) => pathname.startsWith(`/${l}/`) || pathname === `/${l}`);
  if (hasLocale) return;

  request.nextUrl.pathname = `/${getLocale(request)}${pathname}`;
  return NextResponse.redirect(request.nextUrl);
}

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

Будьте осторожны с автоматическими перенаправлениями. Руководство Google для многоязычные сайты рекомендует предоставить пользователям возможность выбора: “Рассмотреть возможность добавления гиперссылок на другие языковые версии страницы.” Перенаправляйте только в том случае, если URL-адрес не имеет локали, никогда не отходите от локали, запрошенной посетителем (или Googlebot), и всегда показывайте переключатель языка.

Шаг 3: Загрузите словарь для каждого языка

Сохраните один JSON-файл на каждый язык и загрузите его на сервер:

// app/[lang]/dictionaries.ts
import 'server-only';

const dictionaries = {
  en: () => import('./dictionaries/en.json').then((m) => m.default),
  fr: () => import('./dictionaries/fr.json').then((m) => m.default),
};

export type Locale = keyof typeof dictionaries;
export const hasLocale = (l: string): l is Locale => l in dictionaries;
export const getDictionary = async (l: Locale) => dictionaries[l]();
// app/[lang]/page.tsx
import { notFound } from 'next/navigation';
import { getDictionary, hasLocale } from './dictionaries';

export default async function Page({ params }: PageProps<'/[lang]'>) {
  const { lang } = await params;
  if (!hasLocale(lang)) notFound();
  const dict = await getDictionary(lang);
  return <button>{dict.products.cart}</button>;
}

Поскольку страницы App Router по умолчанию являются компонентами сервера, словари не отправляются в браузер. Документы также описывают next/root-params, что позволяет любому компоненту сервера читать lang не передавая его через реквизит.

Шаг 4: Предварительная визуализация каждого языка и установка атрибута html lang

// app/[lang]/layout.tsx
export async function generateStaticParams() {
  return [{ lang: 'en' }, { lang: 'fr' }, { lang: 'de' }];
}

export default async function RootLayout({ children, params }: LayoutProps<'/[lang]'>) {
  return (
    <html lang={(await params).lang}>
      <body>{children}</body>
    </html>
  );
}

Шаг 5: Добавьте теги hreflang и canonical

Next.js не знает, какие страницы являются переводами друг друга, поэтому вы объявляете об этом. С API метаданных, alternates выводит как каноническую, так и hreflang ссылки:

// app/[lang]/pricing/page.tsx
export async function generateMetadata({ params }) {
  const { lang } = await params;
  return {
    alternates: {
      canonical: `https://example.com/${lang}/pricing`,
      languages: {
        en: 'https://example.com/en/pricing',
        fr: 'https://example.com/fr/pricing',
        de: 'https://example.com/de/pricing',
        'x-default': 'https://example.com/en/pricing',
      },
    },
  };
}

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

Библиотеки, которые выполняют тяжелую работу

В документации Next.js перечислены несколько библиотек для маршрутизации и трансляции, в том числе next-intl, next-international, next-i18n-router, paraglide-next, lingui и tolgee. Они добавляют множественное число, форматирование чисел и дат, а также типобезопасные ключи сообщений. Если вы хотите создать что-то большее, чем просто небольшой сайт, выбирайте его, а не пишите свой собственный.

Вариант 1б: Маршрутизатор страниц

Если ваш проект все еще использует pages/ каталог, Next.js имеет встроенную маршрутизацию i18n начиная с версии 10. Добавьте локали в next.config.js:

module.exports = {
  i18n: {
    locales: ['en-US', 'fr', 'de'],
    defaultLocale: 'en-US',
  },
};

Это дает вам /fr/blog и /de/blog автоматически и устанавливает <html lang>. По данным Страницы Руководство по маршрутизатору, два ограничения имеют значение: вы все равно добавляете hreflang самостоятельно (с next/head) и “Интернационализированная маршрутизация не интегрируется с output: 'export'”. Для статического экспорта требуется подход App Router или другая настройка.

Сколько стоит вам кодовый маршрут

Маршрут кода — правильный выбор для пользовательского интерфейса продукта, строки которого находятся в компонентах. Все остальное обходится дорого:

  • Контент вне вашего кода (безголовая CMS, ленты продуктов, пользовательский контент) нуждается в собственном конвейере перевода.
  • Каждая новая строка перед выпуском необходим ключ и перевод на все языки.
  • Неразработчики не могут исправить перевод без запроса на извлечение, если только вы не добавите инструмент управления переводами.
  • Больше языков — больше файлов для синхронизации.

Вариант 2: Переведите сайт Next.js, не меняя код

Служба перевода веб-сайтов, такая как ConveyThis, переводит HTML-код, отображаемый вашим приложением Next.js, поэтому вам не придется создавать словари или менять маршруты.

Шаг 1: Создайте учетную запись и добавьте свой домен

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

Шаг 2: Добавьте скрипт в корневой макет

ConveyThis предоставляет вам URL-адрес скрипта с вашим ключом API. В маршрутизаторе приложений добавьте его один раз app/layout.tsx с next/script:

// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://cdn.conveythis.com/javascript/conveythis.js?api_key=YOUR_API_KEY"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

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

Шаг 3: Выберите SEO-дружественную структуру URL-адресов

Посетителям достаточно скрипта, который меняет текст в браузере, но поисковым системам нужен отдельный URL-адрес для каждого языка, чтобы индексировать его. На панели управления ConveyThis выберите Поддомен (fr.example.com) или Подкаталог (example.com/fr/) в структуре URL. Переведенные страницы затем обслуживаются по собственным URL-адресам с добавлением тегов hreflang. Для специально созданного сайта поддомен обычно является более простым выбором: ваш хост Next.js продолжает обслуживать основной домен, и вы добавляете одну запись CNAME на каждый язык, в то время как подкаталог означает маршрутизацию всего домена через ConveyThis. Оба варианта указаны в бизнес-плане и выше; Справочная статья по поддоменам и подкаталогам объясняет, какие записи DNS нужны каждому. Если ваш домен уже находится на Cloudflare, Настройка Cloudflare Workers (O2O) сохраняет вашу зону на месте.

Шаг 4: Просмотрите и уточните переводы

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

Кодовый маршрут или маршрут без кода?

Маршрутизатор приложений i18n (код)ConveyThis (без кода)
НастраиватьРеструктуризация маршрутов, добавление прокси, словарей, метаданныхОдин тег скрипта плюс DNS для URL-адресов SEO
Откуда берется текстВаши словариЧто бы ни отображала страница, включая контент CMS
Кто редактирует переводыРазработчики (или TMS)Любой, у кого есть доступ к панели управления
хрефлангВы добавляете его с помощью alternatesДобавлено с URL-адресами подкаталогов или поддоменов
Лучше всего подходит дляСтроки пользовательского интерфейса приложения, полный контрольМаркетинговые сайты, контент CMS, много языков
СтоимостьВремя разработчикаПлан, основанный на словах и языках (ценообразование)

Многие команды объединяют их: кодовый i18n для входа в приложение, сервис перевода для маркетингового сайта и справочный центр.

Многоязычный контрольный список SEO для Next.js

  • Один URL-адрес на язык (/fr/… или fr.example.com), никогда не используйте один и тот же URL-адрес для каждого языка.
  • <html lang> соответствует языку страницы.
  • Название и метаописание переведены на каждый язык.
  • Канонический текст на каждой переведенной странице указывает на себя, а не на английскую страницу.
  • Hreflang перечисляет все языковые версии, включая саму страницу, а также x-default.
  • Карта сайта включает URL-адреса всех языков.
  • Видимый переключатель языка с реальными ссылками, а не только раскрывающийся список, изменяющий состояние.
  • Никаких принудительных перенаправлений с языка, запрошенного посетителем.

Для более широкой картины прочтите наш многоязычный обзор SEO.

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ

Есть ли в Next.js встроенный перевод? Он имеет встроенную интернационализацию маршрутизация в маршрутизаторе страниц и задокументированных шаблонах i18n для маршрутизатора приложений. Сам переведенный текст взят из ваших словарей, библиотеки или службы перевода.

Что случилось с middleware.js? В Next.js 16 middleware Соглашение о файлах устарело и переименовано в proxy. Логика определения местоположения та же.

Добавляет ли Next.js теги hreflang автоматически? Нет. Использовать alternates.languages в метаданных App Router, или next/head в маршрутизаторе страниц.

Могу ли я перевести статически экспортированный сайт Next.js? Маршрутизация Pages Router i18n не работает с output: 'export', а прокси не поддерживается для статического экспорта. Используйте предварительно сгенерированные [lang] маршруты или служба перевода, которая обслуживает переведенные страницы из своего собственного подкаталога или поддомена.


Хотите, чтобы ваш сайт Next.js был на нескольких языках на этой неделе, а не в следующем квартале? Создать учетную запись ConveyThis, добавьте скрипт в корневой макет и выберите структуру URL, которая соответствует вашему плану SEO.

Поделиться:
G2 High Performer Spring 2023
G2 Easiest Setup Fall 2024
G2 Best Support Spring 2025