Інтернаціоналізація (i18n) в Next.js
Інтернаціоналізація в Next.js
Інтернаціоналізація (i18n) — це процес проектування вашого додатку для підтримки кількох мов і регіонів. Next.js App Router підтримує i18n через шаблони маршрутизації та бібліотеки перекладу.
Стратегія маршрутизації: Локаль у URL
app/
[locale]/
page.tsx → /en, /ua, /de
about/page.tsx → /en/about, /ua/about
blog/
[slug]/page.tsx → /en/blog/hello, /ua/blog/hello
layout.tsxПроміжне ПЗ для Виявлення Локалі
tsx
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
const locales = ["en", "ua"];
const defaultLocale = "en";
function getLocale(request: NextRequest): string {
// Перевірка кукі
const cookieLocale = request.cookies.get("locale")?.value;
if (cookieLocale && locales.includes(cookieLocale)) return cookieLocale;
// Перевірка заголовка Accept-Language
const acceptLanguage = request.headers.get("accept-language") || "";
for (const locale of locales) {
if (acceptLanguage.includes(locale)) return locale;
}
return defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Перевірка, чи вже є локаль у pathname
const hasLocale = locales.some(
locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (hasLocale) return NextResponse.next();
// Перенаправлення на локалізований шлях
const locale = getLocale(request);
return NextResponse.redirect(
new URL(`/${locale}${pathname}`, request.url)
);
}
export const config = {
matcher: ["/((?!api|_next|favicon.ico).*)"],
};Файли Перекладу (JSON)
json
// messages/en.json
{
"nav": {
"home": "Home",
"about": "About Us",
"contact": "Contact"
},
"hero": {
"title": "Welcome to our platform",
"description": "The best tool for developers"
}
}
// messages/ua.json
{
"nav": {
"home": "Головна",
"about": "Про нас",
"contact": "Контакти"
},
"hero": {
"title": "Ласкаво просимо на нашу платформу",
"description": "Найкращий інструмент для розробників"
}
}Використання next-intl (Популярна Бібліотека)
tsx
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}У Серверних Компонентах
tsx
import { useTranslations } from "next-intl";
export default function HomePage() {
const t = useTranslations("hero");
return (
<div>
<h1>{t("title")}</h1>
<p>{t("description")}</p>
</div>
);
}У Клієнтських Компонентах
tsx
"use client";
import { useTranslations } from "next-intl";
export function Navbar() {
const t = useTranslations("nav");
return (
<nav>
<a href="/">{t("home")}</a>
<a href="/about">{t("about")}</a>
<a href="/contact">{t("contact")}</a>
</nav>
);
}Перемикач Мови
tsx
"use client";
import { usePathname, useRouter } from "next/navigation";
export function LanguageSwitcher() {
const pathname = usePathname();
const router = useRouter();
const switchLocale = (newLocale: string) => {
// Замінити поточну локаль у шляху
const segments = pathname.split("/");
segments[1] = newLocale;
router.push(segments.join("/"));
};
return (
<div>
<button onClick={() => switchLocale("en")}>EN</button>
<button onClick={() => switchLocale("ua")}>UA</button>
</div>
);
}Ключові Моменти
| Аспект | Підхід |
|---|---|
| Маршрутизація | [locale] динамічний сегмент |
| Виявлення | Проміжне ПЗ (кукі, заголовок Accept-Language) |
| Переклади | JSON файли + бібліотека (next-intl, react-i18next) |
| SEO | <html lang>, альтернативні hreflang теги |
| Форматування дати/чисел | Intl API або бібліотека |
| Підтримка RTL | CSS логічні властивості, атрибут dir |
Важливо:
i18n у Next.js з App Router використовує сегмент [locale] у URL, проміжне ПЗ для автоматичного виявлення локалі та перенаправлення, а також бібліотеки перекладу, такі як next-intl. Зберігайте переклади у JSON файлах, використовуйте useTranslations() у компонентах і забезпечте належне SEO з атрибутами lang та тегами hreflang.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.