Next.js позволяет настроить маршрутизацию и рендеринг контента для поддержки нескольких языков. Адаптация вашего сайта к различным языкам включает перевод контента (локализацию) и интернационализацию маршрутов.
У нас будет полный контроль над i18n, так как мы пишем всё без сторонних библиотек. Для этой цели нам достаточно будет middleware.ts.
Не нужно передавать язык в getDictionary(lang), как это реализовано в
Просто используем в любом серверном компоненте const dict = await getDictionary();, прокидываем в клиентский компонент как props { dict }: { dict: Dictionary['ui'] } или используем useDictionary()
Пример использования:
1exportconstComponent=async()=>{2const dictionary =awaitgetDictionary();3const lang =awaitgetLang();45return(6<>7<h1>{dictionary.ui['title']}</h1>8<p>Выбранный язык: {lang}</p>9</>10);11};
Создадим файлы с переводами ru.json и en.json в shared/config/i18n/dictionaries.
Пример:
ru.json
1{
2 "home-page": {
3 "note": "Главная страница",
4 "title": "👋 Привет, я Mark Melior",
5 "description": "Ищу компанию, в которой буду совершенствовать свои навыки до сильного Frontend разработчика (:"
6 }
7}
Весь функционал интернационализации находится здесь!
В middleware.ts реализуем передачу url в headers для будущего getPathname() + функционал:
middleware.ts
1import{ i18n }from'@/shared/config/i18n';2import{ NextRequest, NextResponse }from'next/server';34exportfunctionmiddleware(request: NextRequest){5const{ pathname }= request.nextUrl;67// Передаём в headers url текущей страницы8// Это нужно для будущего хука getPathname()9const requestHeaders =newHeaders(request.headers);10 requestHeaders.set('x-url', request.url);1112// `/_next/" и "/api/" игнорируются наблюдателем, но нам нужно вручную игнорировать файлы в `public`13const ignoredPaths =[14/^\/images\/.*$/,15/^\/videos\/.*$/,16/^\/files\/.*$/,17/^\/favicon\.ico$/,18];19if(ignoredPaths.some((regex)=> regex.test(pathname))){20return;21}2223if(24 pathname.startsWith(`/${i18n.defaultLocale}/`)||25 pathname ===`/${i18n.defaultLocale}`26){27// Если входящий запрос предназначен для /ru/whatever, тогда мы перенаправим его на /whatever28const response = NextResponse.redirect(29newURL(30 pathname.replace(31`/${i18n.defaultLocale}`,32 pathname ===`/${i18n.defaultLocale}`?'/':'',33),34 request.url,35),36{37 headers: requestHeaders,38},39);40return response;41}4243const pathnameIsMissingLocale = i18n.locales.every(44(locale)=>45!pathname.startsWith(`/${locale}/`)&& pathname !==`/${locale}`,46);4748if(pathnameIsMissingLocale){49// Теперь для /en или /ru мы собираемся указать Next.js, что запрос предназначен для /ru/whatever50const response = NextResponse.rewrite(51newURL(52`/${i18n.defaultLocale}${pathname}${request.nextUrl.search}`,53 request.nextUrl.href,54),55{56 request:{57 headers: requestHeaders,58},59},60);61return response;62}6364const response = NextResponse.next({65 request:{66 headers: requestHeaders,67},68});69return response;70}7172exportconst config ={73 matcher:['/((?!api|_next/static|_next/image|favicon.ico).*)'],74};
Как вы видите, реализовать интернационализацию можно буквально одним middleware.ts. Получаем переводы через const dict = await getDictionaries() и всё!
Остальные хуки нужны больше для удобства, чем для функциональности i18n.
Ещё вместо хранения языка в роуте можете попробовать на Cookie переписать конечно. Но это будет плохо для SEO