Building a Multi-Language Site with Next.js i18n
Do you have a question or doubt about something?
Scroll down to the bottom to ask your question, and I or anyone else will respond!
🌍 Quick Summary (2-3 sentences)
English only covers about 25% of internet users. To reach a global audience, your application must support multiple languages (i18n). In 2026, Next.js provides the most powerful routing-based localization system, allowing you to serve language-specific content with zero impact on performance.
🔴 What Most People Get Wrong
Most developers think i18n is just "swapping strings" in the UI. They use a massive JSON object and a global state variable to change the text.
The problem? This is terrible for SEO. Google needs to see unique URLs for each language (e.g., /fr/about or /es/about) to index your content correctly in different countries. If your URL doesn't change when the language changes, you are invisible to international users.
📊 Localization Strategies
| Strategy | SEO Friendly | Performance | Implementation | Recommendation |
|---|---|---|---|---|
| Client-side Switch | ❌ No | ✅ Good | Easy | Not for production |
| Subdomains (es.site.com) | ✅ Yes | ✅ Good | Hard (DNS setup) | Large Corporations |
| URL Prefixes (/es/page) | ✅ Best | ✅ Best | Native Next.js | Standard Apps |
| Browser Detect only | ❌ No | ✅ Good | Easy | Accessibility only |
🟢 Deep Dive
🚀 1. Routing-based i18n
The "Right Way" in Next.js App Router is to use a dynamic route segment [lang]. This ensures that every page has a unique URL for every language, and Next.js can handle the dictionary loading on the server.
🧠 2. The Dictionary Pattern
Instead of importing a massive JSON file in every component, create a "Dictionary Loader." This only loads the specific language file the user needs, keeping your JavaScript bundle tiny.
🌓 3. Handling Right-to-Left (RTL)
If you support Arabic or Hebrew, your CSS must change. I recommend using Tailwind Logical Properties (like ms-4 instead of ml-4) which automatically adjust based on the document direction.
✅ Step-by-Step Implementation
Step 1: Configure the Dynamic Route
Create a folder structure like app/[lang]/page.tsx.
// app/[lang]/layout.tsx
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'fr' }, { lang: 'es' }];
}
export default function RootLayout({ children, params: { lang } }) {
return (
<html lang={lang} dir={lang === 'ar' ? 'rtl' : 'ltr'}>
<body>{children}</body>
</html>
);
}
Step 2: Create a Dictionary Utility
This lazily loads the JSON files.
// lib/get-dictionary.ts
const dictionaries = {
en: () => import('@/dictionaries/en.json').then((module) => module.default),
fr: () => import('@/dictionaries/fr.json').then((module) => module.default),
};
export const getDictionary = async (locale: string) => dictionaries[locale]();
Step 3: Use Translations in a Server Component
Zero client-side JS required for basic text.
// app/[lang]/page.tsx
import { getDictionary } from '@/lib/get-dictionary';
export default async function Page({ params: { lang } }) {
const dict = await getDictionary(lang);
return (
<main>
<h1>{dict.welcome_message}</h1>
<p>{dict.hero_description}</p>
</main>
);
}
📊 The 80/20 Rule / Quick Wins
The 80% of your localization success comes from Language Detection Middleware. Instead of forcing users to pick a language, use a simple middleware that checks their browser headers (Accept-Language) and redirects them to the correct /lang prefix automatically on their first visit.
📚 Resources for Further Reading
| Resource | Purpose |
|---|---|
| Next.js i18n Docs | Official implementation guide |
| i18next | Advanced translation management |
| Tailwind RTL Guide | Styling for global audiences |
🎯 Your Action Item
Create an en.json and a fr.json dictionary today. Implement the [lang] dynamic route in your Next.js project and see how easy it is to switch your entire landing page between languages with a single URL change.
Discussion
0Do you have a question or any doubt?
Ask here and I or anyone else will respond!
By 2BigDev
Full-Stack Engineer