如何在Next.js中实现国家/语言双码子路径路由方案?
Next.js 实现包含国家码+语言码的子路径路由方案
方案一:自定义路由重写(next.config.js)
直接在next.config.js中配置路由重写规则,将/[country]/[lang]/:path*格式的请求转发到对应页面,同时传递国家码和语言码参数:
// next.config.js module.exports = { async rewrites() { return [ { source: '/:country/:lang/:path*', destination: '/:path*?country=:country&lang=:lang', }, // 根路径重定向到默认国家+语言组合 { source: '/', destination: '/us/en', permanent: true, }, ]; }, };
页面中通过useRouter获取参数:
// pages/category/[id].js import { useRouter } from 'next/router'; export default function CategoryPage() { const router = useRouter(); const { country, lang, id } = router.query; // 根据country和lang请求对应地区的商品数据、库存信息 // ... }
方案二:使用中间件(Middleware)处理路由校验与参数注入
通过Next.js中间件拦截请求,校验国家码和语言码的合法性,将参数注入到请求上下文,同时处理非法路径的重定向:
// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; // 定义合法的国家码、语言码列表 const VALID_COUNTRIES = ['us', 'de', 'fr', 'jp']; const VALID_LANGUAGES = ['en', 'de', 'fr', 'ja']; export function middleware(request: NextRequest) { const pathParts = request.nextUrl.pathname.split('/').filter(Boolean); // 检查路径是否包含合法的国家码+语言码组合 if (pathParts.length >= 2) { const [country, lang] = pathParts; if (VALID_COUNTRIES.includes(country) && VALID_LANGUAGES.includes(lang)) { // 将参数注入请求头,页面可通过headers()获取 const requestHeaders = new Headers(request.headers); requestHeaders.set('x-country-code', country); requestHeaders.set('x-language-code', lang); return NextResponse.next({ request: { headers: requestHeaders, }, }); } } // 非法路径重定向到默认国家+语言组合 return NextResponse.redirect(new URL('/us/en', request.url)); } // 指定匹配所有路由规则 export const config = { matcher: ['/:path*'], };
页面中获取参数:
// pages/category/[id].js import { headers } from 'next/headers'; export default function CategoryPage() { const headersList = headers(); const country = headersList.get('x-country-code'); const lang = headersList.get('x-language-code'); // 业务逻辑处理(如请求地区专属商品数据) // ... }
方案三:封装本地化路由组件
创建自定义的LocalizedLink组件和useLocalization hook,统一管理路径中的国家码和语言码,避免重复拼接:
// components/LocalizedLink.js import Link from 'next/link'; export default function LocalizedLink({ country, lang, href, ...props }) { const localizedHref = `/${country}/${lang}${href}`; return <Link href={localizedHref} {...props} />; }
// hooks/useLocalization.js import { useRouter } from 'next/router'; export function useLocalization() { const router = useRouter(); const pathParts = router.asPath.split('/').filter(Boolean); // 从路径中提取国家码和语言码,默认值兜底 const country = pathParts[0] || 'us'; const lang = pathParts[1] || 'en'; // 生成带国家码和语言码的路径方法 const getLocalizedPath = (path) => `/${country}/${lang}${path}`; return { country, lang, getLocalizedPath }; }
页面中使用示例:
// pages/category/[id].js import { useLocalization } from '../hooks/useLocalization'; import LocalizedLink from '../components/LocalizedLink'; export default function CategoryPage() { const { country, lang } = useLocalization(); return ( <div> <h2>当前地区:{country} | 当前语言:{lang}</h2> <LocalizedLink country={country} lang={lang} href="/products"> 查看商品列表 </LocalizedLink> </div> ); }
静态生成(SSG)适配
如果使用静态生成,需要在getStaticPaths中预生成所有合法的国家码+语言码组合路径:
// pages/category/[id].js export async function getStaticPaths() { const countries = ['us', 'de', 'fr']; const languages = ['en', 'de', 'fr']; // 实际项目中从API获取所有分类ID const categoryIds = ['1', '2', '3', '4']; const paths = []; for (const country of countries) { for (const lang of languages) { for (const id of categoryIds) { paths.push({ params: { id }, // 配合rewrites规则,生成对应路径 locale: `${country}-${lang}` }); } } } return { paths, fallback: 'blocking' }; }
内容的提问来源于stack exchange,提问作者emred
相关产品推荐
相关产品推荐

