Back to Blog

5 Next.js i18n Mistakes: Moving from React State to next-intl

SiwoerPublished: Updated:

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.

Beginning
The site was Chinese-only with ordinary App Router routes.
Shortcut
Client state swapped translated copy.
Symptoms
Sharing, refresh behavior, SEO, and maintenance became inconsistent.
Migration
I introduced app/[locale], next-intl, and locale-aware content paths.
Now
Each language has a stable URL and matching metadata and sitemap entries.

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:

  1. It explicitly targets App Router
  2. Its Next.js and next-intl versions are relevant
  3. The current official API confirms the pattern
  4. 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.

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 /en and /zh links 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

SymptomFirst checkHow to verify
The language resets on refreshLocale stored only in React stateOpen the copied URL in a new window
Switching an article returns to the homepagePathname discarded by the switcherTest a detail page, not just the homepage
Raw message keys appearMessage file, namespace and ProviderCompare the same key in both languages
Both languages share one canonicalHomepage metadata inherited from a layoutInspect each article's final HTML
A working page is not indexedStatus, robots, canonical and contentInspect 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

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.
5 Next.js i18n Mistakes: Moving from React State to next-intl