From d955d951b50e2c86135ea3f3c65855f4e11e3897 Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Wed, 3 Jun 2026 23:31:53 +0330 Subject: [PATCH] fix(i18n): stop Farsi links bouncing to /en; locale-aware nav links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - routing: localeDetection:false — a non-prefixed URL always serves fa (default); English only via explicit /en/ prefix. Browser Accept-Language no longer redirects fa pages to /en on every click. - AdminShell + DashboardSidebarNav: use next-intl Link + usePathname (from @/i18n/navigation) instead of plain next/link, so links preserve the current locale and active-state matches the prefix-stripped path. Co-Authored-By: Claude Opus 4.8 --- src/components/admin/AdminShell.tsx | 16 +++++++--------- src/components/dashboard/DashboardSidebarNav.tsx | 4 ++-- src/i18n/routing.ts | 6 ++++++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/components/admin/AdminShell.tsx b/src/components/admin/AdminShell.tsx index dc29dfb..2268aa2 100644 --- a/src/components/admin/AdminShell.tsx +++ b/src/components/admin/AdminShell.tsx @@ -1,9 +1,9 @@ "use client"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; import { useState } from "react"; +import { Link, usePathname } from "@/i18n/navigation"; + export interface NavItem { href: string; label: string } export interface NavGroup { title: string; items: NavItem[] } @@ -18,12 +18,10 @@ export function AdminShell({ back: string; children: React.ReactNode; }) { - const pathname = usePathname() ?? ""; + const pathname = usePathname() ?? ""; // next-intl: already without the locale prefix const [open, setOpen] = useState(false); - // Strip a leading locale segment (e.g. /en) so fa (no prefix) and en both match. - const clean = pathname.replace(/^\/[a-z]{2}(?=\/)/, ""); - const isActive = (href: string) => clean === href || clean.startsWith(href + "/"); + const isActive = (href: string) => pathname === href || pathname.startsWith(href + "/"); const current = groups.flatMap((g) => g.items).find((i) => isActive(i.href)); return ( @@ -68,9 +66,9 @@ export function AdminShell({ ))}
- + ← {back} - +
@@ -88,7 +86,7 @@ export function AdminShell({

{current?.label ?? brand}

- {back} + {back}
{children}
diff --git a/src/components/dashboard/DashboardSidebarNav.tsx b/src/components/dashboard/DashboardSidebarNav.tsx index 48da88e..aee86ec 100644 --- a/src/components/dashboard/DashboardSidebarNav.tsx +++ b/src/components/dashboard/DashboardSidebarNav.tsx @@ -1,8 +1,8 @@ "use client"; -import Link from "next/link"; -import { usePathname } from "next/navigation"; import { useTranslations } from "next-intl"; + +import { Link, usePathname } from "@/i18n/navigation"; import { FolderOpen, LayoutTemplate, diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts index 6fd2f49..7adb71a 100644 --- a/src/i18n/routing.ts +++ b/src/i18n/routing.ts @@ -7,6 +7,12 @@ export const routing = defineRouting({ defaultLocale: "fa", /** Default locale gets no /fa/ prefix; English is under /en/ */ localePrefix: "as-needed", + /** + * Never auto-switch locale from the browser's Accept-Language. A non-prefixed + * URL always serves Farsi (the default); English is reached only via an + * explicit /en/ prefix — so clicking Farsi links no longer bounces to /en. + */ + localeDetection: false, }); export type Locale = (typeof routing.locales)[number];