← スキル一覧に戻る
2. Middleware (

nextjs-internationalization-i18n
by ngxtm
⭐ 0🍴 0📅 2026年1月23日
SKILL.md
name: Next.js Internationalization (i18n) description: Best practices for multi-language handling, locale routing, and detection middleware. metadata: labels: [nextjs, i18n, middleware, routing] triggers: files: ['middleware.ts', 'app/[lang]/**', 'messages/*.json'] keywords: [i18n, locale, translation, next-intl, redirect]
Internationalization (i18n)
Priority: P2 (MEDIUM)
Use Sub-path Routing (/en, /de) and Server Components for translations.
Principles
- Sub-path Routing: Use URL segments (e.g.,
app/[lang]/page.tsx) to manage locales.- Why: SEO friendly, sharable, and cacheable.
- Server-Side Translation: Load dictionary files (
en.json) in Server Components.- Why: Reduces client bundle size. No huge JSON blobs sent to browser.
- Middleware Detection: Use
middleware.tsto detectAccept-Languageheaders and redirect users to their preferred locale. - Type Safety: Use robust typing for translation keys to prevent broken text UI.
Implementation Pattern
1. Directory Structure
app/
├── [lang]/ # Dynamic Locale Segment
│ ├── layout.tsx # <html lang={params.lang}>
│ └── page.tsx
└── api/
messages/ # Translation Dictionaries
├── en.json
└── es.json
middleware.ts # Locale Redirection
2. Middleware (middleware.ts)
Redirect root traffic (/) to localized traffic (/en).
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { match } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
const LOCALES = ['en', 'es', 'fr'];
const DEFAULT = 'en';
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// 1. Check if path already has locale
const pathnameHasLocale = LOCALES.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (pathnameHasLocale) return;
// 2. Detect locale (Header matching)
const headers = {
'accept-language': request.headers.get('accept-language') || '',
};
const languages = new Negotiator({ headers }).languages();
const locale = match(languages, LOCALES, DEFAULT);
// 3. Redirect
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: ['/((?!_next|api|static|favicon.ico).*)'],
};
3. Server Component Usage
// app/[lang]/page.tsx
// 1. Dynamic Params ensure static generation works for each language
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'es' }];
}
export default async function Page({ params: { lang } }) {
// 2. Load Dictionary On Demand
const dict = await getDictionary(lang);
return <h1>{dict.home.title}</h1>;
}
Redirect Handling Strategy
When handling redirects (Authentication, Legacy URLs) in an i18n app:
- Always preserve locale: Use
redirect(/${lang}/login)instead of just/login. - Server Actions: Return
redirect(...)from actions. - Next Config: Use
next.config.jsfor legacy SEO 301s (e.g., old-site/about-us->/en/about).
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です