Next.js (Internationalization): How to Use next-intl to Keep Search Parameters While Changing Language

393 Views Asked by At

I tried to create a simple Next.js 14 with Internationalization using next-intl, and everything was going well. However, I noticed a hiccup: when I had a URL with searchParams, like for example http://localhost:3000/de/books?type=2&amount=4, and I tried to change the language to en, the URL changed to http://localhost:3000/en/books instead of http://localhost:3000/en/books?type=2&amount=4. Seeking a solution, I experimented with the useSearchParams() hook, attempting something like this:`

// ...
const searchParams = useSearchParams()

const handleLanguageChange = (locale: string) => {
  startTransition(() => {
    router.replace(`${pathname}?${searchParams.toString()}`, { locale });
  });
}
// ...full source code bellow

And it works well, but again, I'm not sure if it's the best practice or not. I'm curious about using middleware, but I haven't seen any results yet.

full source code

Header.tsx

"use client"

import { useTransition } from 'react'
import { usePathname, useRouter } from '@/navigation'

export const Header = () => {
  const [isPending, startTransition] = useTransition();
  const router = useRouter();
  const pathname = usePathname();

  const handleLanguageChange = (locale: string) => {
    startTransition(() => {
      router.replace(pathname, { locale });
    });
  }

  return (
    <div>
      <button
        disabled={isPending}
        onClick={() => handleLanguageChange("de")}
      >
        DE
      </button>
      <button
        disabled={isPending}
        onClick={() => handleLanguageChange("en")}
      >
        ENG
      </button>
    </div>
  )
}

export default Header

navigation.ts

import { createSharedPathnamesNavigation } from 'next-intl/navigation';

export const { Link, redirect, usePathname, useRouter } = createSharedPathnamesNavigation({
  locales: ["en", "de"]
});

middleware.ts

import createMiddleware from 'next-intl/middleware';
import { cookies } from 'next/headers';
import { NextResponse, NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const locale = cookies().get("NEXT_LOCALE")

  if (request.nextUrl.pathname === "/") return NextResponse.redirect(new URL(locale ? `/${locale.value}` : "/de", request.url))

  return NextResponse.next()
}

export default createMiddleware({
  locales: ['en', 'de'],
  defaultLocale: 'de',
})

export const config = {
  matcher: [
    '/',
    '/(de|en)/:path*',
    '/((?!_next|_vercel|.*\\..*).*)'
  ]
}

Thank you in advance! Any suggestions will be greatly appreciated!

1

There are 1 best solutions below

0
Hamid Mohamadi On

I had the same issue. The point we must motivate is: search params are your strings, so you could do like this:

 <Link href={`/books`} as={`/books?${t('type')}=2&${t('amount')}=100`}>