Loading page...
Proyek ini menggunakan Next.js App Router dan next-intl untuk Bahasa Indonesia (id) dan Inggris (en). Pilihan bahasa disimpan di cookie NEXT_LOCALE selama satu tahun. URL tetap sama, tanpa awalan /id atau /en.
Alurnya: pilih bahasa → simpan cookie → router.refresh() → teks diperbarui.
Simpan teks di i18n/id.json dan i18n/en.json dengan key yang sama.
Contoh Bahasa Indonesia:
{
"NAV": {
"home": "Beranda"
}
}
Padanan Inggrisnya:
{
"NAV": {
"home": "Home"
}
}
i18n/request.ts menentukan bahasa dan memuat JSON yang sesuai. Berikut versi ringkasnya:
import { cookies } from 'next/headers';
import { getRequestConfig } from 'next-intl/server';
export default getRequestConfig(async () => {
const cookieStore = await cookies();
const locale = cookieStore.get('NEXT_LOCALE')?.value === 'en' ? 'en' : 'id';
return {
locale,
messages: (await import(`@/i18n/${locale}.json`)).default,
};
});
Jika cookie belum ada atau nilainya tidak valid, bahasa kembali ke Indonesia.
Hubungkan konfigurasi ini melalui plugin di next.config.ts:
import type { NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {...};
const withNextIntl = createNextIntlPlugin('./i18n/request.ts');
export default withNextIntl(nextConfig);
Di app/layout.tsx, ambil locale dan pesan menggunakan getLocale() serta getMessages() dari next-intl/server.
Bagian inti dalam fungsi layout async:
import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getMessages } from "next-intl/server";
const locale = await getLocale();
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
Import NextIntlClientProvider dari next-intl. Provider menyediakan pesan untuk komponen client dan mewarisi locale dari konfigurasi server.
import { useTranslations } from 'next-intl';
export default function HomeLabel() {
const t = useTranslations('NAV');
return <span>{t('home')}</span>;
}
NAV adalah kelompok pesan, sedangkan home adalah key-nya. Untuk Server Component async, gunakan await getTranslations('NAV') dari next-intl/server.
const router = useRouter(); // next/navigation
const locale = useLocale(); // next-intl
const [isPending, startTransition] = useTransition(); // react
const changeLanguage = (lang: 'id' | 'en') => {
if (lang === locale || isPending) return;
// eslint-disable-next-line react-hooks/immutability
document.cookie = `NEXT_LOCALE=${lang}; path=/; max-age=31536000; SameSite=Lax`;
startTransition(() => router.refresh());
};
Panggil lewat tombol:
<button
type="button"
disabled={isPending}
onClick={() => changeLanguage('en')}
>
English
</button>
Cookie menyimpan pilihan, lalu router.refresh() meminta hasil render terbaru ke server tanpa memuat ulang seluruh dokumen. Request jaringan tetap terjadi. useTransition() menyediakan status isPending untuk indikator proses dan menonaktifkan tombol sementara.
router.refresh().Referensi: next-intl · Next.js router.refresh.