Learn how to build multilingual websites in Next.js 15 without changing URLs. Master automatic language detection, cookies, and next-intl for 2026.
This documentation demonstrates how to implement multi-language support in a Next.js 15 application without changing the URL structure. Unlike traditional implementations (e.g., /en/page), this approach maintains clean URLs while providing full translation capabilities.
/en prefix.next-intlpnpm add next-intl
next.config.tsimport type { NextConfig } from "next";
const createNextIntlPlugin = require("next-intl/plugin");
const withNextIntl = createNextIntlPlugin();
const nextConfig: NextConfig = {};
export default withNextIntl(nextConfig);i18n/request.ts (New for Next.js 15)In Next.js 15, request cookies are async. You must await them.
import { getRequestConfig } from "next-intl/server";
import { cookies } from "next/headers";
export default getRequestConfig(async () => {
// Await cookies in Next.js 15
const cookieStore = await cookies();
const cookieLocale = cookieStore.get("NEXT_LOCALE")?.value;
const locale = cookieLocale || "en";
return {
locale,
messages: (await import(`../messages/${locale}.json`)).default,
};
});Create a messages folder in root.
messages/en.json{
"HomePage": {
"title": "Welcome to Desishub",
"subtitle": "Building for 2026"
}
}messages/fr.json{
"HomePage": {
"title": "Bienvenue à Desishub",
"subtitle": "Construire pour 2026"
}
}app/layout.tsx)import { NextIntlClientProvider } from "next-intl";
import { getMessages, getLocale } from "next-intl/server";
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const locale = await getLocale();
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}app/page.tsx)import { useTranslations } from "next-intl";
export default function Home() {
const t = useTranslations("HomePage");
return (
<main>
<h1>{t("title")}</h1>
<p>{t("subtitle")}</p>
</main>
);
}We use a simple Client Component LanguageSwitcher to detect the browser language on first load and set a cookie.
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
export default function LanguageSwitcher() {
const router = useRouter();
useEffect(() => {
// Check if cookie exists
const hasCookie = document.cookie.includes("NEXT_LOCALE");
if (!hasCookie) {
// Detect and set
const browserLang = navigator.language.slice(0, 2);
document.cookie = `NEXT_LOCALE=${browserLang}; path=/`;
router.refresh();
}
}, []);
return null; // Logic only
}This setup is ideal for SAAS platforms and Dashboards where you want to keep the URL clean (e.g., app.desishub.com/dashboard) but still offer localized content based on user preference.
Check out our full Next.js Course where we build a multi-language E-commerce store from scratch.