
Panduan Lengkap Internasionalisasi Next.js
Siapkan next-intl dengan App Router, konfigurasikan perutean bahasa, dan otomatiskan penerjemahan dengan AI.
Instal next-intl
next-intl adalah satu paket yang menangani perutean bahasa, pemuatan pesan, dan hook terjemahan untuk App Router Next.js.
npm install next-intlBuat Konfigurasi Permintaan i18n
Buat dua file: src/i18n/request.ts untuk memuat pesan dan src/i18n/routing.ts untuk definisi bahasa. File ini mengonfigurasi cara next-intl memilih pesan dan rute.
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';
export const routing = defineRouting({
locales: ['en', 'de', 'ja', 'es'],
defaultLocale: 'en',
localePrefix: 'as-needed', // /about for en, /de/about for de
});
export const { Link, redirect, usePathname, useRouter } =
createNavigation(routing);Konfigurasikan Middleware
Tambahkan middleware.ts untuk menangani deteksi bahasa, penulisan ulang URL, dan pengalihan. Middleware mencegat setiap permintaan dan memastikan bahasa yang benar diterapkan.
// middleware.ts <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';
export default createMiddleware(routing);
export const config = {
matcher: ['/((?!api|_next|.*\\..*).*)'],
};Siapkan Struktur Folder [locale]
Pindahkan rute aplikasi ke dalam app/[locale]/. Tambahkan generateStaticParams untuk membuat halaman bagi setiap bahasa saat build. Ini menghasilkan struktur URL /en/about, /de/about, dan seterusnya.
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}Perbarui Root Layout
Muat pesan dengan getMessages() dan teruskan ke NextIntlClientProvider dalam root layout bahasa. Atur atribut lang HTML dari parameter bahasa.
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const { locale } = await params;
if (!routing.locales.includes(locale as any)) notFound();
setRequestLocale(locale);
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider locale={locale} messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}Gunakan Terjemahan dalam Komponen
Komponen server menggunakan getTranslations (asinkron, await). Komponen klien menggunakan useTranslations (hook). Pilih berdasarkan tempat komponen dirender—komponen server sepenuhnya mencegah terjemahan masuk ke bundle JavaScript.
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';
export default async function AboutPage({
params,
}: { params: { locale: string } }) {
const { locale } = await params;
setRequestLocale(locale);
const t = await getTranslations('AboutPage');
return <h1>{t('title')}</h1>;
}
// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';
export default function SearchBar() {
const t = useTranslations('SearchBar');
return <input placeholder={t('placeholder')} />;
}Tambahkan SEO: Metadata dan Hreflang
Gunakan generateMetadata untuk menghasilkan judul dan deskripsi halaman spesifik bahasa. Tambahkan alternates.languages untuk tag hreflang agar mesin pencari menemukan semua versi bahasa setiap halaman.
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';
export async function generateMetadata({
params,
}: { params: { locale: string } }) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: 'Metadata' });
return {
title: t('title'),
description: t('description'),
alternates: {
languages: Object.fromEntries(
routing.locales.map((l) => [l, `/${l}`])
),
},
};
}Tangani Halaman Kesalahan dan Tidak Ditemukan
error.tsx dan not-found.tsx memerlukan penanganan khusus karena dapat dirender di luar layout bahasa normal. Root not-found.tsx memerlukan penyiapan penyedia i18n sendiri untuk menampilkan pesan kesalahan lokal.
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';
export default function Error() {
const t = useTranslations('Error');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
);
}
// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';
export default async function GlobalNotFound() {
return (
<html lang={routing.defaultLocale}>
<body>
<h1>404 - Page Not Found</h1>
</body>
</html>
);
}Otomatiskan Penerjemahan
Setelah penyiapan i18n selesai, terjemahkan file pesan menggunakan AI langsung dari IDE atau gunakan CLI i18n Agent dalam pipeline CI/CD untuk penerjemahan otomatis pada setiap deployment.
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish
✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)Otomatiskan Kualitas Terjemahan
Alat Sumber Terbuka untuk Next.js i18n
Paket sumber terbuka ini mengatasi masalah umum dalam alur kerja internasionalisasi Next.js.
next-intl-localechain
next-intl standar langsung beralih ke bahasa default saat terjemahan hilang. Pengguna Portugis Brasil melihat bahasa Inggris, bukan terjemahan pt-PT yang masih sesuai. next-intl-localechain menambahkan rantai fallback cerdas—sistem menggabungkan terjemahan secara mendalam dari bahasa terkait agar pengguna regional selalu melihat terjemahan terdekat yang tersedia.
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';
export default getRequestConfig(withLocaleChain({
loadMessages: (locale) =>
import(`../../messages/${locale}.json`).then(m => m.default),
defaultLocale: 'en'
}));@i18n-agent/cli
Alat baris perintah untuk menerjemahkan file pesan Next.js tanpa meninggalkan terminal. Terjemahkan file secara langsung, periksa status pekerjaan, dan unduh hasil. Berfungsi dalam pipeline CI/CD dengan autentikasi kunci API untuk alur kerja lokalisasi yang sepenuhnya otomatis.
# Install the CLI
npm install -g @i18n-agent/cli
# Authenticate
i18nagent login
# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es
# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,esKesalahan Umum
"Unable to find next-intl locale"
Middleware tidak cocok dengan permintaan. Periksa: apakah middleware.ts berada di root proyek? Apakah pola matcher mengecualikan file statis dengan benar? Apakah bahasa tercantum dalam konfigurasi perutean?
Rendering Dinamis yang Tidak Terduga
setRequestLocale(locale) tidak ada di halaman atau layout. Tanpanya, next-intl menggunakan header/cookie untuk mendeteksi bahasa sehingga memaksa rendering dinamis dan mencegah pembuatan statis.
Rute Paralel Rusak dengan i18n
Rute paralel (@modal) dan rute pencegat ((.)photo) diketahui tidak kompatibel dengan segmen dinamis [locale]. Gunakan perutean berbasis middleware sebagai solusi sementara untuk pola perutean tingkat lanjut ini.
Pengalihan Bahasa Kehilangan Rute Saat Ini
Saat beralih bahasa, pertahankan pathname saat ini dengan usePathname() dan ganti hanya segmen bahasa. Berhati-hatilah dengan parameter rute dinamis—parameter tersebut harus dipilih ulang untuk bahasa baru.
Struktur File yang Disarankan
my-nextjs-app/
├── middleware.ts # Locale routing (project root!)
├── next.config.mjs
├── messages/
│ ├── en.json # Source messages
│ ├── de.json
│ └── ja.json
├── src/
│ ├── i18n/
│ │ ├── request.ts # Message loading config
│ │ └── routing.ts # Locale definitions
│ └── app/
│ └── [locale]/
│ ├── layout.tsx # Root locale layout
│ ├── page.tsx # Home page
│ ├── error.tsx # Localized error page
│ ├── not-found.tsx # Localized 404
│ └── about/
│ └── page.tsx
└── package.jsonCoba i18n Agent Sekarang
Lepaskan file terjemahan Anda di sini
JSON, YAML, PO, XML, CSV, Markdown, Properties
atau klik untuk menjelajahi
Bahasa target
Fallback Bahasa dengan next-intl-localechain
Saat kunci terjemahan tidak ada dalam bahasa regional seperti pt-BR, next-intl langsung beralih ke bahasa default alih-alih memeriksa bahasa induk pt terlebih dahulu.
npm install next-intl-localechainimport { withLocaleChain } from 'next-intl-localechain';
export default withLocaleChain({
fallbacks: {
'pt-BR': ['pt', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
},
defaultLocale: 'en',
loadMessages: (locale) => import(`./messages/${locale}.json`),
});Lihat Panduan Fallback Bahasa kami untuk daftar lengkap framework yang didukung dan 75 rantai bawaan. Learn more →