如何在NextJS中实现动态本地化?按需配置路由语言支持
Next.js动态路由实现差异化语言支持方案
Next.js默认的全局i18n配置没法给单个路由指定支持的语言,导致像/en/route2这种本不该支持的路由也能访问。结合你用getServerSideProps的场景,按下面的步骤来解决:
1. 保留全局i18n基础配置
先在next.config.js里把所有可能用到的语言都列进去,全局配置是基础,后续在路由层面做拦截:
// next.config.js module.exports = { i18n: { locales: ['en', 'zh-CN'], defaultLocale: 'zh-CN', }, }
2. 定义路由-语言权限映射
新建一个配置文件(比如src/utils/localeRouteRules.js),明确每个路由能支持的语言列表:
// src/utils/localeRouteRules.js export const allowedLocalesByRoute = { '/route1': ['zh-CN', 'en'], // route1支持中英文 '/route2': ['zh-CN'], // route2仅支持中文 // 其他路由按需添加 }
3. 用getServerSideProps做路由语言校验
封装一个公共校验函数,在每个页面的getServerSideProps里先执行校验,不匹配就重定向到默认语言路由或者返回404:
封装公共校验逻辑
// src/utils/checkLocaleAccess.js import { allowedLocalesByRoute } from './localeRouteRules' import { redirect } from 'next/navigation' export function checkLocaleAccess(ctx) { const { locale, asPath, i18n } = ctx // 提取不带语言前缀和查询参数的基础路由 const baseRoute = asPath.split('?')[0].replace(`/${locale}`, '') || '/' // 获取当前路由允许的语言列表,未配置则默认允许所有语言 const allowedLocales = allowedLocalesByRoute[baseRoute] || i18n.locales if (!allowedLocales.includes(locale)) { // 不支持当前语言,直接重定向到默认语言的对应路由 redirect(`/${i18n.defaultLocale}${baseRoute}`) // 若需直接返回404,替换为: // return { notFound: true } } }
在页面中使用校验函数
比如pages/route1.js:
export async function getServerSideProps(ctx) { // 先校验语言权限,不通过直接重定向 checkLocaleAccess(ctx) // 正常编写数据获取逻辑 const data = await fetch('your-api-url/route1').then(res => res.json()) return { props: { data } } }
pages/route2.js同理,调用checkLocaleAccess(ctx)后,访问/en/route2会自动跳转到/zh-CN/route2。
4. 动态路由的适配处理
如果是动态路由(比如pages/posts/[id].js),调整配置和校验逻辑:
// src/utils/localeRouteRules.js export const allowedLocalesByRoute = { '/posts/[id]': ['zh-CN', 'en'], // 所有文章详情页支持中英文 // ...其他路由 }
修改校验函数里的路由匹配逻辑,用正则匹配动态路由模板:
// src/utils/checkLocaleAccess.js function matchDynamicRoute(baseRoute) { return Object.keys(allowedLocalesByRoute).find(routePattern => { // 将动态路由模板转为正则,比如/posts/[id] → /posts/[^/]+ const regexPattern = routePattern.replace(/\[.*?\]/g, '[^/]+') return new RegExp(`^${regexPattern}$`).test(baseRoute) }) } // 替换原allowedLocales获取逻辑 const matchedRoute = matchDynamicRoute(baseRoute) const allowedLocales = matchedRoute ? allowedLocalesByRoute[matchedRoute] : ctx.i18n.locales
5. 导航链接的优化
确保前端生成的导航链接只包含当前路由支持的语言,比如在语言切换组件中:
import { useRouter } from 'next/router' import { allowedLocalesByRoute } from '../utils/localeRouteRules' function LanguageSwitcher() { const router = useRouter() const baseRoute = router.asPath.split('?')[0].replace(`/${router.locale}`, '') || '/' const allowedLocales = allowedLocalesByRoute[baseRoute] || router.locales return ( <div className="lang-switch"> {allowedLocales.map(lang => ( <a key={lang} href={router.pathname} locale={lang} className={router.locale === lang ? 'active' : ''} > {lang === 'en' ? 'English' : '中文'} </a> ))} </div> ) }
这样用户看不到当前路由不支持的语言选项,从源头避免错误访问。
内容的提问来源于stack exchange,提问作者Caner
相关产品推荐
相关产品推荐

