Next.js+next-intl本地化URL修改:将en-GB改为en/UK的问题
问题背景
使用Next.js (v13.5.4) 和next-intl (v3.0.0-beta.19) 基于App Router实现国际化,希望将URL结构从en-GB格式改为en/UK格式,但配置rewrite后出现错误重定向:访问http://localhost:3000/en/uk会被重定向到http://localhost:3000/en-GB/en/uk。
解决方案
1. 自定义中间件的Locale解析与路径映射
修改middleware.ts,让next-intl直接识别en/uk为en-GB的别名,同时生成符合要求的URL格式:
import createMiddleware from 'next-intl/middleware'; import { NextRequest } from 'next/server'; // 定义URL路径到标准locale的映射 const localePathMap = { 'en/uk': 'en-GB', 'de/de': 'de-DE' }; // 反向映射,用于将标准locale转换为URL路径 const localeReverseMap = Object.fromEntries( Object.entries(localePathMap).map(([path, locale]) => [locale, path]) ); export default createMiddleware({ locales: ['de-DE', 'en-GB'], defaultLocale: 'en-GB', // 设置有效的默认locale,禁止留空 // 自定义检测请求中的locale async localeDetector(request: NextRequest) { const pathSegments = request.nextUrl.pathname.split('/').filter(Boolean); // 检查路径前两段是否匹配自定义locale路径 if (pathSegments.length >= 2) { const candidatePath = `${pathSegments[0]}/${pathSegments[1]}`; if (localePathMap[candidatePath]) { return localePathMap[candidatePath]; } } // fallback到next-intl默认检测逻辑 const defaultDetector = createMiddleware({ locales: ['de-DE', 'en-GB'], defaultLocale: 'en-GB' }).localeDetector; return defaultDetector(request); }, // 自定义生成URL时的locale前缀 async getLocalePrefix(request: NextRequest, locale: string) { return localeReverseMap[locale] || locale; }, localePrefix: 'always' // 确保所有路由都带locale前缀 }); export const config = { matcher: ['/((?!api|_next|_vercel|.*\\..*).*)'] };
2. 移除无效的Rewrite配置
修改next.config.js,删除之前的rewrites配置(中间件已处理路径映射):
/** @type {import('next').NextConfig} */ const nextConfig = { // 无需额外rewrite配置 }; module.exports = withNextIntl(nextConfig);
3. 保持现有目录结构
App Router的目录结构无需修改,仍然使用app/[locale]/...(如app/en-GB/page.tsx),中间件会自动将en/uk请求映射到对应locale的页面。
之前方案失败的原因
- Rewrite与中间件冲突:rewrite会将
en/uk重写到en-GB,但next-intl中间件会先检测路径locale。由于en/uk不在配置的locales列表中,中间件会将缓存的默认locale(如en-GB)追加到路径前,导致错误重定向。 - 排除路径导致Locale检测失败:将
en/uk从matcher中排除后,next-intl无法解析该路径的locale,抛出Unable to find next-intl locale错误。 - 空默认Locale:
defaultLocale设为空字符串会让中间件无法确定默认locale,进而使用缓存locale进行重定向,加剧路径错误。
额外注意事项
- 内部链接请使用next-intl提供的
Link组件,确保生成的URL为en/uk格式。 - 测试前清除浏览器缓存,避免旧重定向规则干扰结果。
内容的提问来源于stack exchange,提问作者Giovanni Della Cagna
相关产品推荐
相关产品推荐

