5 min read
ā¢Question 27 of 47mediumHow to implement i18n in Next.js?
Internationalization and routing.
What You'll Learn
- i18n routing
- Language detection
- Content translation
Folder Structure
code.jsJavaScript
app/
āāā [lang]/
ā āāā layout.tsx
ā āāā page.tsx
ā āāā about/
ā āāā page.tsx
āāā dictionaries/
āāā en.json
āāā es.jsonDictionary Files
data.jsonJSON
// dictionaries/en.json
{
"welcome": "Welcome",
"about": "About Us"
}
// dictionaries/es.json
{
"welcome": "Bienvenido",
"about": "Sobre Nosotros"
}Load Dictionary
code.txtTSX
// lib/dictionaries.ts
const dictionaries = {
en: () => import('../dictionaries/en.json').then((m) => m.default),
es: () => import('../dictionaries/es.json').then((m) => m.default),
};
export const getDictionary = async (locale: string) => {
return dictionaries[locale]();
};Page Usage
code.txtTSX
// app/[lang]/page.tsx
import { getDictionary } from '@/lib/dictionaries';
export default async function Home({ params: { lang } }) {
const dict = await getDictionary(lang);
return <h1>{dict.welcome}</h1>;
}Middleware for Detection
code.txtTSX
import { NextRequest, NextResponse } from 'next/server';
const locales = ['en', 'es'];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (pathnameHasLocale) return;
const locale = request.headers.get('accept-language')?.split(',')[0].split('-')[0] || 'en';
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}