Next.js 12.2.5实现类Apple的区域子路径路由(仅显示地区码)
解决方案:Next.js 12.2.5 实现地区码式国际化子路径路由
1. 直接将地区码作为 i18n 配置的 locales 值
Next.js 的 i18n 路由支持自定义 locale 标识,你可以直接把 au、in 这类地区码作为配置项,替代完整的 en-AU 格式。
在 next.config.js 中修改配置:
module.exports = { i18n: { locales: ['au', 'in', 'en'], // 用地区码作为locale值 defaultLocale: 'en', localeDetection: true, // 保留自动检测浏览器locale的功能 }, }
这样路由就会直接显示为 ${mydomain}/au、${mydomain}/in/faq 这类格式,完全符合你的需求。
2. 适配浏览器 locale 到地区码的自动重定向
默认的 localeDetection 会匹配浏览器的完整 locale(比如 en-AU),我们需要将其映射到对应的地区码,避免出现 /en-AU 这类路由。可以通过 Next.js 中间件实现:
- 先安装依赖包:
npm install @formatjs/intl-localematcher negotiator
- 在项目根目录创建
middleware.js:
import { NextResponse } from 'next/server' import { match } from '@formatjs/intl-localematcher' import Negotiator from 'negotiator' // 定义支持的地区码 const supportedLocales = ['au', 'in', 'en'] // 建立完整locale到地区码的映射 const localeToRegionMap = { 'en-AU': 'au', 'en-IN': 'in', 'en-US': 'en', 'en-GB': 'en', // 可根据需求添加更多映射规则 } export function middleware(request) { const pathname = request.nextUrl.pathname // 检查当前路由是否已包含地区码 const hasValidLocale = supportedLocales.some( locale => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` ) if (!hasValidLocale) { // 获取浏览器首选locale const headers = { 'accept-language': request.headers.get('accept-language') || '' } const browserLanguages = new Negotiator({ headers }).languages() // 匹配到对应的地区码 let targetLocale = match(browserLanguages, supportedLocales, 'en') // 如果浏览器返回完整locale,优先用映射规则替换 const primaryBrowserLocale = browserLanguages[0] if (localeToRegionMap[primaryBrowserLocale]) { targetLocale = localeToRegionMap[primaryBrowserLocale] } // 重定向到带地区码的路由 return NextResponse.redirect( new URL(`/${targetLocale}${pathname}`, request.url) ) } } // 排除不需要处理的路由(如静态资源、API) export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], }
3. 本地化内容的处理
虽然路由显示的是地区码,但你可以在代码内部将其映射到对应的完整 locale,处理日期、货币这类地区化格式,或者加载对应地区的翻译文件:
import { useRouter } from 'next/router' // 导入各地区的翻译文件 import auTranslations from '../locales/au/common.json' import inTranslations from '../locales/in/common.json' import enTranslations from '../locales/en/common.json' const translationMap = { au: auTranslations, in: inTranslations, en: enTranslations, } // 地区码到完整locale的映射,用于格式化数据 const fullLocaleMap = { au: 'en-AU', in: 'en-IN', en: 'en-US', } export default function FaqPage() { const router = useRouter() const currentTranslations = translationMap[router.locale] const currentFullLocale = fullLocaleMap[router.locale] // 示例:格式化澳大利亚地区的货币 const formattedPrice = new Intl.NumberFormat(currentFullLocale, { style: 'currency', currency: router.locale === 'au' ? 'AUD' : 'INR', }).format(99) return ( <div> <h1>{currentTranslations.faqTitle}</h1> <p>{currentTranslations.priceText}: {formattedPrice}</p> </div> ) }
4. 注意事项
- Next.js 12.2.5 完全支持自定义 locale 标识,用地区码作为
locales值不会有兼容性问题。 - 如果需要同一地区支持多语言(比如印度的英文和印地语),可以调整配置为
['au', 'in-en', 'in-hi'],再通过中间件将/in重定向到默认语言的子路由(如/in-en)。 - 静态生成(SSG)或服务器端渲染(SSR)时,
getStaticProps/getServerSideProps的context.locale会返回配置的地区码,直接使用即可。
内容的提问来源于stack exchange,提问作者Gurkirat Sardana
相关产品推荐
相关产品推荐

