Next.js Internationalization (i18n)

Overview

Internationalization (i18n) enables your application to support multiple languages. Next.js provides built-in i18n routing support and integrates with various third-party libraries.

Installation

npm install next-intl

Configuration

// i18n.ts
import { getRequestConfig } from 'next-intl/server'

export default getRequestConfig(async ({ locale }) => ({
  messages: (await import(`./messages/${locale}.json`)).default
}))

// middleware.ts
import createMiddleware from 'next-intl/middleware'

export default createMiddleware({
  locales: ['zh', 'en'],
  defaultLocale: 'zh'
})

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)']
}

Translation Files

// messages/zh.json
{
  "home": {
    "title": "欢迎",
    "description": "这是首页"
  },
  "nav": {
    "home": "首页",
    "about": "关于"
  }
}

// messages/en.json
{
  "home": {
    "title": "Welcome",
    "description": "This is home page"
  },
  "nav": {
    "home": "Home",
    "about": "About"
  }
}

Using Translations

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

export default function Home() {
  const t = useTranslations('home')
  
  return (
    <div>
      <h1>{t('title')}</h1>
      <p>{t('description')}</p>
    </div>
  )
}

react-i18next

Installation

npm install react-i18next i18next

Configuration

// lib/i18n.ts
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'

i18n
  .use(initReactI18next)
  .init({
    resources: {
      zh: {
        translation: {
          welcome: '欢迎',
          hello: '你好,{{name}}'
        }
      },
      en: {
        translation: {
          welcome: 'Welcome',
          hello: 'Hello, {{name}}'
        }
      }
    },
    lng: 'zh',
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false
    }
  })

export default i18n

Usage

'use client'

import { useTranslation } from 'react-i18next'

export default function Component() {
  const { t, i18n } = useTranslation()
  
  return (
    <div>
      <h1>{t('welcome')}</h1>
      <p>{t('hello', { name: '张三' })}</p>
      <button onClick={() => i18n.changeLanguage('en')}>
        English
      </button>
    </div>
  )
}

Language Switching

Language Selector

'use client'

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

export default function LanguageSwitcher() {
  const router = useRouter()
  const pathname = usePathname()
  const locale = useLocale()
  
  const switchLanguage = (newLocale: string) => {
    const newPathname = pathname.replace(`/${locale}`, `/${newLocale}`)
    router.push(newPathname)
  }
  
  return (
    <select value={locale} onChange={(e) => switchLanguage(e.target.value)}>
      <option value="zh">中文</option>
      <option value="en">English</option>
    </select>
  )
}

Best Practices

1. Organize Translation Files

messages/
  zh/
    common.json
    home.json
    about.json
  en/
    common.json
    home.json
    about.json

2. Type Safety

// types/i18n.ts
export type Locale = 'zh' | 'en'

export type Messages = typeof import('../messages/zh.json')

3. Dynamic Imports

export default getRequestConfig(async ({ locale }) => ({
  messages: (await import(`./messages/${locale}.json`)).default
}))

Previous Chapter: Next.js Database Integration | Next Chapter: Next.js Testing