如何强制 Next.js 始终重定向到首选用户语言?

问题描述 投票:0回答:4

目前,Next.js 仅从根目录重定向到用户的语言,因此“/”变为“/fr-FR”。但是如果用户访问例如“/profile”路由,它不会将他重定向到“/fr-FR/profile”。

有没有办法强制 Next 做这些类型的重定向?

javascript internationalization next.js i18next
4个回答
1
投票

对我来说,关键是按照以下方式设置我的

_middleware.ts

const PUBLIC_FILE = /\.(.*)$/ // anything having a file extension.
const getIsInternalRoute = (url: string) => {
    if (url.startsWith('/_next')) return true // next internal routes
    if (url.includes('/api/')) return true // nextjs api routes
    return PUBLIC_FILE.test(url) // static files
}

const handleLocaleRedirects = (req: NextRequest) => {
    const { pathname } = req.nextUrl
    const isPreloadRequest = req.method === 'HEAD'
    /*
    Due to several bugs with prefetching/middleware/i18n combination
    https://github.com/vercel/next.js/issues/35648
    https://github.com/vercel/next.js/issues/36100
    https://github.com/vercel/next.js/issues/40678

    we cannot redirect any prefetch requests. They get cached with the current locale which then causes
    infinite loop redirect when we click a link to change the locale.
    Possibly might be fixed in later NextJs versions (>=13), but I'd be really careful & skeptical here.
     */
    if (isPreloadRequest || getIsInternalRoute(pathname)) return

    const locale = req.cookies.NEXT_LOCALE || req.nextUrl.defaultLocale // locale you're supposed to have
    if (locale && req.nextUrl.locale !== locale) {
        req.nextUrl.locale = locale
        return NextResponse.redirect(req.nextUrl)
    }
}

export function middleware(req: NextRequest) {
    const maybeRedirectResponse = handleLocaleRedirects(req)
    if (maybeRedirectResponse) return maybeRedirectResponse

    const response = NextResponse.next()

    // perhaps other middleware logic here...

    return response
}

并设置切换器链接以在重定向到新路由之前设置 cookie,因此中间件已经具有新的 NEXT_LOCALE 值。

function LocaleSwitcher({ locale, children, ...props }) {
    const router = useRouter()
    const { pathname, asPath, query } = router

    const handleClick = e => {
        e.preventDefault()

        /*
        The locale cookie needs to be set before the page redirect, so the nextjs middleware already knows which locale is correct.
         */
        setCookie({}, 'NEXT_LOCALE', locale, {
            maxAge: 100 * 365 * 24 * 60 * 60, // 100 yrs
        })
        // change just the locale and maintain all other route information including href's query
        router.push({ pathname, query }, asPath, { locale })
    }

    return (
        <Link {...props} locale={locale} to={asPath} onClick={handleClick}>
            {children}
        </Link>
    )
}

此设置从每条路线上的 cookie 中检查用户的语言环境,并将他们重定向到站点的正确语言环境版本。


0
投票

从官方 NextJS 文档查看此页面:

为默认语言环境添加前缀

它通过将 domain.com/example 重定向到 domain.com/en/example 来解决您的问题


0
投票

您可以使用 middlewareNEXT_LOCALE cookie,当您更改语言时,您应该设置这个 cookie

document.cookie = `NEXT_LOCALE=${langugage};path=/`;

中间件.js

import { NextResponse } from "next/server";

export function middleware(request) {
  const localeCookie = request.cookies.get("NEXT_LOCALE");
  if (localeCookie !== undefined && request.nextUrl.locale !== localeCookie) {
    return NextResponse.redirect(new URL(`/${localeCookie}${request.nextUrl.pathname}`, request.url));
  }
}
export const config = { 
  matcher: ["/", "/about"], // paths on which middleware will work
};

https://nextjs.org/docs/advanced-features/i18n-routing#leveraging-the-next_locale-cookie

https://nextjs.org/docs/advanced-features/i18n-routing#prefixing-the-default-locale

https://nextjs.org/docs/advanced-features/middleware

https://nextjs.org/docs/messages/middleware-upgrade-guide

https://nextjs.org/docs/api-reference/next/server


-1
投票
Sub-path Routing
Sub-path Routing puts the locale in the url path.

With the above configuration en-US, fr, and nl-NL will be available to be routed to, and en-US is the default locale. If you have a pages/blog.js the following urls would be available:

//next.config.js
module.exports = {
  i18n: {
    locales: ['en-US', 'fr', 'nl-NL'],
    defaultLocale: 'en-US',
  },
}

/blog
/fr/blog
/nl-nl/blog
The default locale does not have a prefix.

from Nextjs docs
© www.soinside.com 2019 - 2024. All rights reserved.