如何在next-intl中忽略特定路由并解决MISSING_MESSAGE报错?
在next-intl中为特定路由禁用国际化的方案
问题根源
你遇到的报错是因为全局的ErrorBoundary组件调用了useTranslations,即便目标页面本身没用到翻译,但该组件被包裹在IntlProvider下,而非国际化路由未传入messages,最终触发MISSING_MESSAGE错误。另外,ignoreRoutes是next-i18next的专属配置项,next-intl并不支持,所以之前的配置无效。
正确解决方案
1. 在中间件中排除指定路由
next-intl的中间件支持通过exclude选项跳过特定路由,让这类路由完全不经过国际化处理:
// middleware.js import createNextIntlMiddleware from 'next-intl/middleware'; import { locales, defaultLocale } from './i18n.config'; export default createNextIntlMiddleware({ locales, defaultLocale, // 填入不需要国际化的路由列表 exclude: ['/privacy-policy', '/terms-of-service'] }); export const config = { matcher: ['/((?!api|_next|.*\\..*).*)'] };
2. 在根组件中动态控制IntlProvider包裹范围
确保非国际化路由不会被IntlProvider包裹,从根源避免无messages的报错:
// Pages Router: pages/_app.jsx import { IntlProvider } from 'next-intl'; import { useRouter } from 'next/router'; // 定义不需要国际化的路由 const nonI18nRoutes = ['/privacy-policy', '/terms-of-service']; function MyApp({ Component, pageProps }) { const router = useRouter(); const isNonI18nRoute = nonI18nRoutes.includes(router.pathname); if (isNonI18nRoute) { // 非国际化路由直接渲染,不经过IntlProvider return <Component {...pageProps} />; } return ( <IntlProvider messages={pageProps.messages}> <Component {...pageProps} /> </IntlProvider> ); } export default MyApp;
如果使用App Router,只需把useRouter替换为usePathname:
// App Router: app/layout.jsx import { IntlProvider } from 'next-intl'; import { usePathname } from 'next/navigation'; const nonI18nRoutes = ['/privacy-policy', '/terms-of-service']; export default function RootLayout({ children, messages }) { const pathname = usePathname(); const isNonI18nRoute = nonI18nRoutes.includes(pathname); if (isNonI18nRoute) { return <html><body>{children}</body></html>; } return ( <html> <body> <IntlProvider messages={messages}> {children} </IntlProvider> </body> </html> ); }
3. 修复ErrorBoundary的翻译依赖
如果你的ErrorBoundary必须保留,需要在组件内部做容错处理,避免无messages时抛出错误:
// ErrorBoundary.tsx import { useTranslations } from 'next-intl'; function ErrorBoundary({ children }) { let t; try { t = useTranslations('ErrorBoundary'); } catch (e) { // 无可用messages时,直接返回键名或自定义默认文本 t = (key) => key; } // 后续组件逻辑 }
或者,为非国际化路由单独提供一个不依赖翻译的ErrorBoundary版本。
内容的提问来源于stack exchange,提问作者Jeppe Christensen
相关产品推荐
相关产品推荐

