next-auth 和 i18n 的中间件(带有应用程序路由器的 next.js 13)

JJ7*_*J77 5 javascript next.js next-auth

我已经设置了 next-auth(在带有应用程序路由器的 next.js 13 项目中),它正在工作。现在我想向我的应用程序添加国际化,如 next.js 文档中所述。但是,我不知道如何将两者结合起来。

用于下一个身份验证的中间件

/user/ 中的每条路由都应该受到保护。

export { default } from "next-auth/middleware"
export const config = { matcher: ["/(user/.*)"] }
Run Code Online (Sandbox Code Playgroud)

用于 next-auth 和 i18n 的中间件

这就是我到目前为止所想到的。I18n 似乎可以工作,但路由 /user/... 不受保护。

import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextResponse } from 'next/server'

export { default } from "next-auth/middleware"

let locales = ['en', 'de']
let defaultLocale = 'en'

function getLocale(request) {
    let headers = { 'accept-language': 'en' }
    let languages = new Negotiator({ headers }).languages()
    return match(languages, locales, defaultLocale) // -> 'en'
}

export function middleware(request) {
    // Check if there is any supported locale in the pathname
    const pathname = request.nextUrl.pathname
    const pathnameIsMissingLocale = locales.every(
        (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
    )

    // Redirect if there is no locale
    if (pathnameIsMissingLocale) {
        const locale = getLocale(request)

        // e.g. incoming request is /products
        // The new URL is now /en/products
        return NextResponse.redirect(
            new URL(`/${locale}/${pathname}`, request.url)
        )
    }
}

export const config = {
    // '/(\w{2}/user/.*)' from nextauth (\w{2} because of /en/ or /de/); '/((?!_next).*)' from i18n
    matcher: ['/(\w{2}/user/.*)', '/((?!_next).*)'],
}
Run Code Online (Sandbox Code Playgroud)

我如何将两者结合起来?

JJ7*_*J77 0

感谢 @mateen-kiani 和 phind.com 的帮助,我才弄清楚了!这就是我组合两个中间件的方式:

import { NextResponse } from 'next/server'
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import nextAuthMiddleware from "next-auth/middleware"

let locales = ['en', 'de']
let defaultLocale = 'en'

function getLocale(request) {
    let headers = { 'accept-language': 'en' }
    let languages = new Negotiator({ headers }).languages()
    return match(languages, locales, defaultLocale) // -> 'en'
}

export function middleware(request) {
    // cancel if exception
    const pathname = request.nextUrl.pathname
    const isException = ['/img', '/preview', '/icons', '/logo.svg', '/api', '/manifest.json', '/sw.js'].some((allowedPath) =>
        pathname.startsWith(`${allowedPath}`),
    );
    if (isException) return;

    // Check if there is any supported locale in the pathname
    const pathnameIsMissingLocale = locales.every(
        (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
    )

    // Redirect if there is no locale
    if (pathnameIsMissingLocale) {
        const locale = getLocale(request)
        return NextResponse.redirect(
            new URL(`/${locale}/${pathname}`, request.url)
        )
    }

    // check if auth is required
    if (pathname.includes("/user")) {
        // check & handle if logged in
        const nextAuthResponse = nextAuthMiddleware(request)
        if (nextAuthResponse) {
            return nextAuthResponse
        }
    }

    // Continue if no NextAuth middleware response
    return NextResponse.next()
}

export const config = {
    matcher: [
        '/((?!_next).*)',
    ],
}
Run Code Online (Sandbox Code Playgroud)