Next.js Internationalization (i18n) Guide

Sanjeev SharmaSanjeev Sharma
2 min read

Advertisement

Next.js Internationalization (i18n) Guide

Support multiple languages in your Next.js application for global audiences.

Installation

npm install next-intl

Configuration

// app/layout.tsx
import { notFound } from 'next/navigation'
import { getRequestConfig } from 'next-intl/server'

export const metadata = { title: 'My App' }

export default async function RootLayout({
  children,
  params: { locale }
}: any) {
  let messages
  try {
    messages = (await import(`@/messages/${locale}.json`)).default
  } catch (error) {
    notFound()
  }

  return (
    <html lang={locale}>
      <body>{children}</body>
    </html>
  )
}

export function generateStaticParams() {
  return [{ locale: 'en' }, { locale: 'es' }, { locale: 'fr' }]
}

Translations File

// messages/en.json
{
  "welcome": "Welcome",
  "home": "Home",
  "about": "About",
  "contact": "Contact"
}
// messages/es.json
{
  "welcome": "Bienvenido",
  "home": "Inicio",
  "about": "Acerca de",
  "contact": "Contacto"
}

Using Translations

// app/[locale]/page.tsx
import { useTranslations } from 'next-intl'

export default function HomePage() {
  const t = useTranslations()

  return (
    <div>
      <h1>{t('welcome')}</h1>
      <nav>
        <a href="/">{t('home')}</a>
        <a href="/about">{t('about')}</a>
      </nav>
    </div>
  )
}

Language Switcher

'use client'

import { useLocale } from 'next-intl'
import { useRouter, usePathname } from 'next/navigation'

export function LocaleSwitcher() {
  const locale = useLocale()
  const router = useRouter()
  const pathname = usePathname()

  const switchLocale = (newLocale: string) => {
    const newPath = pathname.replace(`/${locale}`, `/${newLocale}`)
    router.push(newPath)
  }

  return (
    <select value={locale} onChange={(e) => switchLocale(e.target.value)}>
      <option value="en">English</option>
      <option value="es">Español</option>
      <option value="fr">Français</option>
    </select>
  )
}

Date and Number Formatting

import { useFormatter } from 'next-intl'

export function Prices() {
  const format = useFormatter()

  return (
    <div>
      <p>
        Price: {format.number(99.99, {
          style: 'currency',
          currency: 'USD'
        })}
      </p>

      <p>
        Date: {format.dateTime(new Date(), {
          year: 'numeric',
          month: 'long',
          day: 'numeric'
        })}
      </p>
    </div>
  )
}

FAQ

Q: Should I use URL routing or locale detection? A: URL routing for better SEO and user control. Detect preference, then redirect.

Q: How do I handle default locale? A: Configure in middleware to redirect /page to /en/page.

Q: Can I support RTL languages? A: Yes, set dir="rtl" on html element for Arabic, Hebrew, etc.


Internationalization enables your app to reach global audiences.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro