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;
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;
🛠 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
- When navigation silently fails in a localized Next.js app, check your config files — not just your components.
- Don't assume the issue is in the app folder if the structure looks correct.
- Inconsistent or duplicated i18n config can silently break routing.
- 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
✅ 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)