skip to Main Content

I’m using Next.js 13 and I have a middleware function set up for Multilanguage. I want to add another middleware function, but it’s not working for me. I guess I made a mistake in writing the middleware, but I’m not sure where. I don’t get any error, it just doesn’t work.

Here’s my code:

import { NextResponse, NextRequest } from 'next/server'

import acceptLanguage from 'accept-language'
import { fallbackLng, languages } from './app/i18n/settings'

acceptLanguage.languages(languages)

const cookieName = 'i18next'

export function middleware(req: any) {
let lng
if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value)

    // automatic detect language with browser
    // if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'))
    
    if (!lng) lng = fallbackLng
    
    // Redirect if lng in path is not supported
    if (
        !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) &&
        !req.nextUrl.pathname.startsWith('/_next')
    ) {
        return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url))
    }
    
    if (req.headers.has('referer')) {
        const refererUrl = new URL(req.headers.get('referer'))
        const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`))
        const response = NextResponse.next()
        if (lngInReferer) response.cookies.set(cookieName, lngInReferer)
        return response
    }
    
    return NextResponse.next()

}

export function middleware2(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/about')){
return NextResponse.redirect(new URL('/home', request.url))
}

}

export const config = {
api: {
bodyParser: false,
},
matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)']

}

2

Answers


  1. You can only export one middleware function.

    From Next.js 13 document

    import { NextResponse } from 'next/server'
    import type { NextRequest } from 'next/server'
     
    export function middleware(request: NextRequest) {
      if (request.nextUrl.pathname.startsWith('/about')) {
        return NextResponse.rewrite(new URL('/about-2', request.url))
      }
     
      if (request.nextUrl.pathname.startsWith('/dashboard')) {
        return NextResponse.rewrite(new URL('/dashboard/user', request.url))
      }
    }
    

    In your case, you should move the condition in middleware2 to middleware

    export function middleware(req: any) {
       // From middleware2
        
        if (request.nextUrl.pathname.startsWith('/about')){
            return NextResponse.redirect(new URL('/home', request.url))
        }
    
        let lng
        if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value)
    
        // automatic detect language with browser
        // if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'))
        
        if (!lng) lng = fallbackLng
        
        // Redirect if lng in path is not supported
        if (
            !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) &&
            !req.nextUrl.pathname.startsWith('/_next')
        ) {
            return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url))
        }
        
        if (req.headers.has('referer')) {
            const refererUrl = new URL(req.headers.get('referer'))
            const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`))
            const response = NextResponse.next()
            if (lngInReferer) response.cookies.set(cookieName, lngInReferer)
            return response
        }
    
        return NextResponse.next()
    
    }
    
    

    In addition, the config does not have the api property. The matcher property gives you the option to run the middleware on specific routes. The config you have below will prevent your middleware from running if the request path is any of /api, /_next/static, /_next/image, /assets, /favicon.ico and /sw

    export const config = {
        matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)']
    }
    
    Login or Signup to reply.
  2. It seems like you are trying to use two middleware functions (middleware and middleware2) in the same file. However, Next.js only allows one exported middleware function per file.

    If you want to use multiple middleware functions, you should create separate files for each middleware function. For example, you could have a middleware1.js file for your first middleware function and a middleware2.js file for your second middleware function.

    Here’s how you could separate your middleware functions into two files:

    middleware1.js

    import { NextResponse, NextRequest } from 'next/server'
    import acceptLanguage from 'accept-language'
    import { fallbackLng, languages } from './app/i18n/settings'
    
    acceptLanguage.languages(languages)
    
    const cookieName = 'i18next'
    
    export function middleware(req: any) {
      let lng
      if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value)
    
      if (!lng) lng = fallbackLng
    
      if (
        !languages.some(loc => req.nextUrl.pathname.startsWith(`/${loc}`)) &&
        !req.nextUrl.pathname.startsWith('/_next')
      ) {
        return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url))
      }
    
      if (req.headers.has('referer')) {
        const refererUrl = new URL(req.headers.get('referer'))
        const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`))
        const response = NextResponse.next()
        if (lngInReferer) response.cookies.set(cookieName, lngInReferer)
        return response
      }
    
      return NextResponse.next()
    }
    
    export const config = {
      api: {
        bodyParser: false,
      },
      matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)']
    }
    

    middleware2.js

    import { NextResponse, NextRequest } from 'next/server'
    
    export function middleware(request: NextRequest) {
      if (request.nextUrl.pathname.startsWith('/about')){
        return NextResponse.redirect(new URL('/home', request.url))
      }
    }
    

    Remember to import and use these middleware functions in the appropriate places in your application.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search