Skip to main content

Panduan Lengkap Internasionalisasi Next.js

Siapkan next-intl dengan App Router, konfigurasikan perutean bahasa, dan otomatiskan penerjemahan dengan AI.

1

Instal next-intl

next-intl adalah satu paket yang menangani perutean bahasa, pemuatan pesan, dan hook terjemahan untuk App Router Next.js.

Terminal
npm install next-intl
Mengapa next-intl, bukan next-i18next? next-intl dibuat untuk App Router dan komponen server. next-i18next dirancang untuk Pages Router dan memiliki dukungan App Router terbatas.
2

Buat 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
// 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);
Turbopack (bundler default di Next.js 15) memerlukan experimental.turbo.resolveAlias dalam next.config.js. Tanpanya, Anda akan mendapat kesalahan "Couldn't find next-intl config file".
3

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
// 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|.*\\..*).*)'],
};
middleware.ts HARUS berada di direktori root proyek, bukan di dalam src/. Ini adalah kesalahan konfigurasi next-intl yang paling umum.
4

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
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
Anda HARUS memanggil setRequestLocale(locale) di setiap page.tsx dan layout.tsx yang menggunakan terjemahan. Tanpanya, Next.js beralih ke rendering dinamis dan performa build menurun secara signifikan.
5

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
// 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>
  );
}
NextIntlClientProvider memerlukan prop locale eksplisit. Jika dihilangkan, komponen klien mengalami kesalahan halus yang sulit di-debug.
6

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.

app/[locale]/page.tsx
// 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')} />;
}
Pilih komponen server untuk konten terjemahan. Komponen tersebut mencegah string terjemahan masuk ke bundle JavaScript klien sehingga waktu muat pengguna berkurang.
7

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
// 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}`])
      ),
    },
  };
}
Di Vercel, build dapat menghasilkan localhost sebagai URL kanonis jika metadataBase tidak diatur. Selalu atur metadataBase di root layout ke domain produksi Anda.
8

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
// 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>
  );
}
Next.js hanya merender halaman 404 lokal saat notFound() dipanggil secara eksplisit dalam kode. Rute tidak dikenal tanpa halaman yang cocok menampilkan 404 default Next.js, bukan versi lokal Anda.
9

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.

Terminal
# 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)
Gunakan next-intl-localechain untuk fallback bahasa cerdas—pengguna pt-BR akan melihat terjemahan pt-PT alih-alih beralih ke bahasa Inggris saat Portugis Brasil tidak tersedia.

Otomatiskan Kualitas Terjemahan

Temukan kunci hilang dan placeholder rusak sebelum dirilis dengan i18n-validate. Uji UI dengan terjemahan palsu menggunakan i18n-pseudo sebelum terjemahan asli tersedia.

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.

src/i18n/request.ts
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'
}));
Menggabungkan terjemahan secara mendalam di seluruh rantai bahasa secara otomatis
Rantai bawaan untuk bahasa Portugis, Spanyol, Prancis, Jerman, dan lainnya
Melewati file pesan yang hilang dengan baik tanpa kesalahan
Penyiapan satu baris—membungkus getRequestConfig yang ada
Lihat di GitHub

@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.

Terminal
# 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,es
Terjemahkan JSON, YAML, PO, dan format file i18n lainnya dari terminal
Siap untuk CI/CD—autentikasi melalui variabel lingkungan untuk pipeline otomatis
Lacak status pekerjaan, lanjutkan pekerjaan gagal, dan unduh hasil
Keluaran JSON yang dapat dibaca mesin untuk skrip dan otomatisasi
Lihat di GitHub

Kesalahan 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

Project Structure
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.json

Coba i18n Agent Sekarang

Lepaskan file terjemahan Anda di sini

JSON, YAML, PO, XML, CSV, Markdown, Properties

atau klik untuk menjelajahi

Bahasa target

Tidak perlu mendaftarEstimasi instan

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.

Terminal
npm install next-intl-localechain
Configuration
import { 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 →

Pertanyaan yang Sering Diajukan