5 Next.js i18n Mistakes: Moving from React State to next-intl
Five mistakes from rebuilding a bilingual Next.js site: state-only locales, late routing changes, SEO signals, language switching and outdated examples.
5 min read · 915 words
I originally thought Next.js internationalization meant creating two message files and adding a language button. After rebuilding my personal site in Chinese and English, I learned that translation was the easy part. Routing, content relationships, and SEO were the real work.
This is the migration story—not another installation walkthrough. It covers the approaches that looked correct in the browser but failed once pages needed to be refreshed, shared, maintained, and indexed.
If you need the implementation, use the complete Next.js and next-intl App Router guide.
The requirements looked simple
- Chinese and English content
- Separate blog versions
- The same information architecture
- Shareable, crawlable language URLs
My first solution addressed only the first item.
Mistake 1: treating locale as React state
The original flow was simple:
store locale → update state → render different copy
It worked visually, but /blog/post stayed unchanged. That created predictable problems:
- Refreshing could lose the selected language
- Shared links did not preserve it
- Server and client state could disagree
- Crawlers had no stable URL for each version
Switching text is not the same as internationalizing a website.
Public content needed route-based language state instead:
/en/blog/post
/zh/blog/post
Mistake 2: changing the URL architecture too late
Moving from /blog/[slug] to /[locale]/blog/[slug] sounds small when a site has three pages. In practice, it touches navigation, redirects, dynamic routes, metadata, sitemaps, content folders, and every internal link.
If multilingual support is likely, decide the locale URL model on day one.
Mistake 3: assuming locale URLs finish the SEO work
/en and /zh are only the foundation. Search engines still need consistent signals:
- A self-referencing canonical for the current language
- Reciprocal hreflang links between real translations
- Titles, descriptions, and visible content in the same language
- Sitemap coverage for every indexable locale URL
- Reachable links between language versions
Do not connect two pages with hreflang merely because their slugs match. They should represent corresponding content.
Mistake 4: sending users back to the homepage
My early switcher changed every page to /en or /zh. Someone reading an article would lose their place.
A better switch preserves the pathname:
/en/blog/nextjs-intl-i18n
↓
/zh/blog/nextjs-intl-i18n
When no translation exists, provide an explicit fallback instead of generating a dead URL.
Mistake 5: copying Pages Router examples
Many search results still mix routing generations. Patterns such as passing locale to a plain next/link, or rendering another <html> inside a nested layout, do not describe a current App Router setup.
I now check four things before adopting an example:
- It explicitly targets App Router
- Its Next.js and next-intl versions are relevant
- The current official API confirms the pattern
- Direct loads, refreshes, and production builds all pass
Why next-intl became the right fit
The route becomes the language state
Locale comes from the URL, so components no longer synchronize a second global language value.
Server and Client Components both have focused APIs
Page copy can be translated on the server while interactive controls use client hooks. Internationalization does not force the whole page into the client bundle.
Navigation lives in one configuration
Locale-aware Link, redirect, pathname, and router helpers reduce hand-built URL strings and inconsistent edge cases.
SEO has a stable foundation
next-intl does not create rankings by itself. It does make canonical, hreflang, and sitemap implementation much more predictable.
My post-migration checklist
- Deep
/enand/zhlinks survive direct access and refresh - Unsupported locale values return 404
- Language switching preserves the current page
- Metadata matches the visible language
- Canonical, hreflang, and sitemap URLs agree
- Missing translations have an intentional fallback
What I learned
Internationalization is an information architecture problem before it is a translation problem.
next-intl solved much of the implementation, but the important decisions were still mine: stable locale URLs, honest content relationships, and consistent indexing signals. Once those were clear, the translation layer became the straightforward part.
A practical troubleshooting order
| Symptom | First check | How to verify |
|---|---|---|
| The language resets on refresh | Locale stored only in React state | Open the copied URL in a new window |
| Switching an article returns to the homepage | Pathname discarded by the switcher | Test a detail page, not just the homepage |
| Raw message keys appear | Message file, namespace and Provider | Compare the same key in both languages |
| Both languages share one canonical | Homepage metadata inherited from a layout | Inspect each article's final HTML |
| A working page is not indexed | Status, robots, canonical and content | Inspect the URL in Google Search Console |
The first four checks address implementation. The last cannot be solved simply by installing next-intl; absence from the index alone does not prove a routing bug.
References and implementation
- next-intl routing setup for current APIs and file structure.
- Google's multilingual site guidance for language URLs and crawling.
- The implementation tutorial for the Next.js 15 and next-intl 4 setup.
Frequently asked questions
- Why is React state alone a poor solution for public multilingual content?
- The copy changes but the URL does not, so refreshes and shared links cannot reliably preserve the language and search engines lack stable language-specific pages.
- What should be designed first in a Next.js internationalization project?
- Define locale URLs, default-locale behavior, and translated content relationships before choosing how translation messages are stored.
- Does next-intl solve international SEO automatically?
- No. It provides a strong routing foundation, but canonical URLs, hreflang, sitemaps, metadata, and content quality still need deliberate implementation.