DEV Community

Anton
Anton

Posted on • Edited on

How i18n in Next.js broke my route interceptors (and how I fixed it)

In this article, I share my experience fixing a subtle issue in a Next.js 14 project where route interceptors were silently ignored. The app still worked as an SPA — pages rendered and navigation occurred — but clicking on <Link> components bypassed the expected interceptors and triggered full navigations instead. After hours of debugging, I realized the issue wasn’t inside the app folder or React components, but stemmed from the internationalization (i18n) configuration.

🧩 What happened?
I was using localized routing with next-i18next. Everything seemed configured correctly.

But suddenly:

  • Navigation through <Link> components was not intercepted by Next.js.
  • No errors appeared in the console.
  • Copying the whole app folder into a fresh Next.js project didn’t solve the problem.

Turns out, the real issue was outside the app folder.

🧨 The root cause
It boiled down to a misconfigured or duplicated i18n setup:

  • next-i18next.config.mjs contained the i18n config (locales, defaultLocale, etc).
  • That config was spread into next.config.js via the spread operator.
  • This sometimes caused Next.js to mishandle locale routing and break interceptors.

My custom i18n.js file looked like this:

// i18n.js
import { initReactI18next } from 'react-i18next';
import i18next from 'i18next';
import en from '../../public/locales/en/common.json';
import uk from '../../public/locales/uk/common.json';
import ru from '../../public/locales/ru/common.json';

i18next.use(initReactI18next).init({
  resources: {
    en: { common: en },
    uk: { common: uk },
    ru: { common: ru },
  },
  fallbackLng: 'en',
  interpolation: {
    escapeValue: false,
  },
});

export default i18next;
Enter fullscreen mode Exit fullscreen mode

And next.config.js looked like this:

// next.config.js
import nextI18NextConfig from './next-i18next.config.mjs';

/** @type {import('next').NextConfig} */
const nextConfig = {
  ...nextI18NextConfig,
  reactStrictMode: true,
};

export default nextConfig;
Enter fullscreen mode Exit fullscreen mode

🛠 How I fixed it
In my case, I ended up:

  • Deleting the custom i18n.js setup
  • Deleting the .next folder (Next.js cache)
  • Restarting the dev server

After that, the interceptors worked again.

If you want to try a more minimal fix, I recommend:

  • Ensure next-i18next.config.mjs exports only the i18n config — avoid other settings or duplications.
  • Import it cleanly into next.config.js.
  • Make sure locales match in both files.
  • Test navigation with and without locale prefixes in components.

💡 Tip: If routing doesn’t behave as expected in Next.js, try deleting the .next folder. Cached data there can cause subtle and hard-to-diagnose bugs.

🧠 What you can learn

  1. When navigation silently fails in a localized Next.js app, check your config files — not just your components.
  2. Don't assume the issue is in the app folder if the structure looks correct.
  3. Inconsistent or duplicated i18n config can silently break routing.
  4. Delete .next if all else fails — caching is sneaky.

🔎 app folder structure

app/
├── favicon.ico
├── globals.css
├── layout.tsx
├── (dashboard)/
├── (root)/
│   ├── layout.tsx
│   ├── page.tsx
│   ├── @modal/
│   │   ├── default.tsx
│   │   ├── (.)product/
│   │   │   └── [id]/
│   │   │       └── page.tsx
│   │   └── [...catchAll]/
│   │       └── page.tsx
│   └── product/
│       └── [id]/
│           └── page.tsx
api/
├── ingredients/
│   └── route.ts
└── products/
    └── search/
        └── route.ts
Enter fullscreen mode Exit fullscreen mode

Final thoughts
Next.js is powerful — but sometimes a single misconfigured file or leftover cache can silently break features like interceptors or routing.

If you're stuck with navigation bugs and use next-i18next, check your config, and don’t forget about .next.

Top comments (0)