Build a fully internationalized Next.js application with URL-based locale routing, translated content, and right-to-left language support.

Abdur Razzak
Full-Stack Web Developer
Building multilingual web applications opens your product to global markets. Next.js App Router handles internationalization through URL-based locale routing — each language gets its own URL prefix (/en/about, /fr/about, /ar/about). This approach is SEO-friendly, cacheable, and lets users share language-specific links. Libraries like next-intl and next-i18next simplify the implementation significantly.
next-intl is the most popular i18n library for Next.js App Router. Create a [locale] dynamic segment at the root of your app directory. Define your supported locales and default locale in the next-intl middleware. Store translation messages in JSON files organized by locale (messages/en.json, messages/fr.json). Use the useTranslations hook in client components and getTranslations in server components.
Organize translation keys hierarchically in your JSON files: { "navigation": { "home": "Home", "about": "About" }, "hero": { "title": "Hello World" } }. Use ICU message format for variables: "greeting": "Hello, {name}!" and for pluralization: "items": "{count, plural, one {# item} other {# items}}". next-intl handles rich text formatting with HTML elements like <b> and <i>.
Implement a language switcher component that links to the current page in a different locale. Use next-intl's useRouter and usePathname hooks to generate locale-prefixed URLs. Store the user's preferred language in a cookie so returning visitors see their chosen language. Add alternate link hreflang tags in your metadata for SEO — this tells search engines about all language versions of each page.
Languages like Arabic, Hebrew, and Persian read right-to-left. Set the dir attribute on the html element dynamically based on the locale. In Tailwind CSS, use logical properties (ml- becomes ms-, mr- becomes me-) that automatically flip in RTL. Test your layout thoroughly in RTL mode — many designs break when direction flips, requiring specific RTL overrides.
Localization goes beyond text translation. Numbers, dates, and currencies are formatted differently across locales — 1,000.50 in English is 1.000,50 in German and 1 000,50 in French. Use the Intl.NumberFormat and Intl.DateTimeFormat browser APIs, or next-intl's built-in format helpers. Always pass locale-aware formatting functions to ensure your numbers and dates look correct for each user.