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!
I had the same issue. The point we must motivate is: search params are your strings, so you could do like this: