Next.js Discord

Discord Forum

NEXT_LOCALE cookie is being ignored

Unanswered
Britannia Petite posted this in #help-forum
Open in Discord
Britannia PetiteOP
i set the cookie NEXT_LOCALE once a user changes the language on my website
i have a middleware for this and a locale-updater component

middleware.ts
import { defaultLocale, locales } from '@/config/i18n' // Import from config
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

function getLocale(request: NextRequest) {
  const pathname = request.nextUrl.pathname

  // Check if the pathname already has a locale
  const pathnameHasLocale = locales.some(
    (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
  )

  if (pathnameHasLocale) return null

  // Check for saved locale in cookies
  const savedLocale = request.cookies.get('NEXT_LOCALE')?.value
  if (savedLocale && locales.includes(savedLocale as any)) {
    return savedLocale
  }

  // Fallback to default locale
  return defaultLocale
}

export function middleware(request: NextRequest) {
  const locale = getLocale(request)
  if (!locale) return

  // Redirect to the same url but with locale
  request.nextUrl.pathname = `/${locale}${request.nextUrl.pathname}`
  const response = NextResponse.redirect(request.nextUrl)

  // Set cookie with better security and longer expiration
  response.cookies.set('NEXT_LOCALE', locale, {
    path: '/',
    sameSite: 'lax', // Changed from 'strict' to 'lax' for better compatibility
    secure: true, // Always use secure in production
    httpOnly: true, // Prevent JavaScript access
    expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30 days
  })

  return response
}

export const config = {
  matcher: [
    // Skip all internal paths (_next, api, etc)
    '/((?!api|_next/static|_next/image|images|favicon.ico|images|dot-texture.svg|map.svg|map2.svg|robots.txt|sitemap.xml|umami.js).*)',
  ],
}

3 Replies

Britannia PetiteOP
locale-updater.tsx
'use client'

import Cookies from 'js-cookie'
import { usePathname } from 'next/navigation'
import { useEffect } from 'react'

export function LocaleUpdater() {
  const pathname = usePathname()

  useEffect(() => {
    // Extract locale from pathname (e.g., /en/about -> en)
    const locale = pathname.split('/')[1]
    if (locale) {
      // Set cookie with 30 days expiration
      Cookies.set('NEXT_LOCALE', locale, {
        expires: 30, // 30 days
        path: '/',
        secure: true,
        sameSite: 'lax',
      })
    }
  }, [pathname])

  return null
}
any ideas why this doesn't work?
it's being ignored in production, but it works on dev localhost