admin管理员组

文章数量:1326332

Currently, Next.js makes a redirect to the user's language only from the root, so "/" bees "/fr-FR". But if a user accesses for example "/profile" route, it won't redirect him to the "/fr-FR/profile".

Is there a way to force Next to do these kinds of redirects?

Currently, Next.js makes a redirect to the user's language only from the root, so "/" bees "/fr-FR". But if a user accesses for example "/profile" route, it won't redirect him to the "/fr-FR/profile".

Is there a way to force Next to do these kinds of redirects?

Share Improve this question edited Jun 21, 2021 at 10:17 Gucal 9231 gold badge12 silver badges22 bronze badges asked May 12, 2021 at 10:40 Bohdan KontsedalBohdan Kontsedal 1513 silver badges12 bronze badges 2
  • 1 This is a highly rated feature request, github./vercel/next.js/discussions/18419 – AviKKi Commented Aug 9, 2021 at 23:59
  • Does this answer your question: How to enforce i18n locale slugs and achieve i18n consistency upon reload in Next.js?? – juliomalves Commented Jul 24, 2022 at 6:03
Add a ment  | 

5 Answers 5

Reset to default 1

For me the key was to set up my _middleware.ts the following way:

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 bination
    https://github./vercel/next.js/issues/35648
    https://github./vercel/next.js/issues/36100
    https://github./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
}

and set up the switcher link to set the cookie before redirecting to the new route, so the middleware already has the new NEXT_LOCALE value.

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>
    )
}

This setup checks the user's locale from the cookie on every route and redirects them to the correct locale version of the site.

Check out this Page from the official NextJS Documentation:

Prefixing the Default Locale

It solves your problem by redirecting domain./example to domain./en/example

You can do it with middleware and NEXT_LOCALE cookie, when you change language you should set this cookie

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

middleware.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/docs/advanced-features/i18n-routing#leveraging-the-next_locale-cookie

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

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

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

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

This reference https://nextjs/docs/advanced-features/i18n-routing#transition-between-locales:

router.push(router.asPath, router.asPath, { locale: language });
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

本文标签: javascriptHow to force Nextjs to always redirect to a preferred user languageStack Overflow