typescriptadvanced
Internationalization (i18n) Routing
Implement locale-based routing with middleware detection and dictionary loading.
typescriptPress ⌘/Ctrl + Shift + C to copy
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
const locales = ['en', 'de', 'fr', 'es'];
const defaultLocale = 'en';
function getLocale(request: NextRequest): string {
const acceptLanguage = request.headers.get('accept-language') || '';
const preferred = acceptLanguage.split(',')[0]?.split('-')[0];
return locales.includes(preferred) ? preferred : defaultLocale;
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Check if pathname has a locale
const hasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
);
if (hasLocale) return NextResponse.next();
// Redirect to locale-prefixed path
const locale = getLocale(request);
const url = request.nextUrl.clone();
url.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(url);
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};
// app/[locale]/layout.tsx
import { getDictionary } from '@/lib/dictionaries';
export async function generateStaticParams() {
return locales.map((locale) => ({ locale }));
}
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const dict = await getDictionary(locale);
return (
<html lang={locale}>
<body>{children}</body>
</html>
);
}
// lib/dictionaries.ts
const dictionaries: Record<string, () => Promise<Record<string, string>>> = {
en: () => import('@/dictionaries/en.json').then((m) => m.default),
de: () => import('@/dictionaries/de.json').then((m) => m.default),
fr: () => import('@/dictionaries/fr.json').then((m) => m.default),
};
export async function getDictionary(locale: string) {
return dictionaries[locale]?.() || dictionaries.en();
}Use Cases
- multi-language websites
- locale detection
- content translation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptadvanced
Parallel Routes Layout
Next.js parallel routes pattern to render multiple page slots simultaneously in a shared layout.
Best for: Dashboard multi-panel layouts
#parallel-routes#layout
typescriptadvanced
Next.js Parallel Routes Layout
Use parallel routes with named slots to render multiple pages simultaneously in a layout.
Best for: Dashboard layouts with independent loading states
#nextjs#routing
typescriptadvanced
Next.js Intercepting Routes for Modals
Implement modal patterns with intercepting routes that work with both soft and hard navigation.
Best for: Image gallery modals with shareable URLs
#nextjs#routing
typescriptintermediate
Route Groups for Layout Organization
Use route groups to share layouts across routes without affecting URL structure.
Best for: Marketing vs. dashboard layouts
#nextjs#routing