Technology · Next.js
Next.js Internationalization
Implement i18n in Next.js with routing, translations, locale detection, and multi-language support.
TL;DR
- 01Use locale-prefixed routing like /en, /es, /fr in the app directory.
- 02Organize translation files by locale and reference them in components.
- 03Detect locale from URL, user preference, or browser language.
Locale-Based Routing
- Create a locale folder structure to organize routes by language.
app/ [locale]/ layout.tsx page.tsx about/ page.tsx - This creates URLs like
/en,/es,/en/about,/es/about, etc. - Access the locale parameter in your layouts and pages.
export default function Layout({ children, params: { locale } }: { children: React.ReactNode; params: { locale: string }; }) { return <html lang={locale}>{children}</html>; } - Use middleware to redirect to the user's preferred locale.
- Generate static params for all supported locales.
Translation Files
- Create JSON or JSON5 files to store translations by locale.
locales/ en.json es.json fr.json - Structure translations hierarchically for nested content.
{ "common": { "welcome": "Welcome", "goodbye": "Goodbye" }, "home": { "title": "Home Page", "description": "Welcome to our site" } } - Load translations based on the current locale in your component.
import translations from "@/locales/en.json"; const message = translations.common.welcome; - Use a translation library like
next-intlfor complex needs.
Using the next-intl Library
- Install and configure next-intl for a complete i18n solution.
npm install next-intl - Create a configuration file for supported locales and messages.
import { getRequestConfig } from "next-intl/server"; export default getRequestConfig(async ({ locale }) => ({ messages: (await import(`./messages/${locale}.json`)).default })); - Use the
useTranslationshook to access translations in components."use client"; import { useTranslations } from "next-intl"; export default function HomePage() { const t = useTranslations("home"); return <h1>{t("title")}</h1>; } - next-intl handles formatting, pluralization, and date localization.
Locale Detection
- Detect the user's preferred locale from the Accept-Language header.
import { getLocale } from "next-intl/server"; export const getServerSideProps = async ({ req }) => { const acceptLanguage = req.headers["accept-language"]; const preferredLocale = acceptLanguage?.split(",")[0].split("-")[0]; // Use preferredLocale to redirect or set session }; - Store locale preference in a cookie or user profile.
const setLocale = (locale: string) => { document.cookie = `NEXT_LOCALE=${locale}`; router.push(`/${locale}`); }; - Allow users to manually select their language.
<select onChange={(e) => setLocale(e.target.value)}> <option value="en">English</option> <option value="es">Español</option> <option value="fr">Français</option> </select> - Respect browser language preference on first visit.
SEO and Hreflang
- Set the
langattribute on the HTML element per locale.<html lang={locale}> - Add hreflang links to alternate language versions for SEO.
export async function generateMetadata({ params }) { const alternates = { languages: { en: `https://example.com/en/page`, es: `https://example.com/es/page`, fr: `https://example.com/fr/page` } }; return { alternates }; } - Generate sitemaps for each locale to help search engines index them.
- Use canonical URLs to prevent duplicate content issues.
Tip: Use next-intl library for complex i18n needs like pluralization, date formatting, and locale-aware routing, as it handles many edge cases automatically.
Warning: Always set the HTML lang attribute correctly for each locale, since screen readers and search engines rely on it for language detection.