fix(i18n): stop Farsi links bouncing to /en; locale-aware nav links
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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({
|
||||
))}
|
||||
</nav>
|
||||
<div className="border-t border-[#1e2235] p-3">
|
||||
<a href="/dashboard" className="block rounded-lg px-3 py-1.5 text-sm text-gray-400 hover:bg-[#161a2e] hover:text-white">
|
||||
<Link href="/dashboard" className="block rounded-lg px-3 py-1.5 text-sm text-gray-400 hover:bg-[#161a2e] hover:text-white">
|
||||
← {back}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -88,7 +86,7 @@ export function AdminShell({
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 6h18M3 12h18M3 18h18" /></svg>
|
||||
</button>
|
||||
<h2 className="text-sm font-semibold text-white">{current?.label ?? brand}</h2>
|
||||
<a href="/dashboard" className="ms-auto text-xs text-gray-500 transition-colors hover:text-gray-300">{back}</a>
|
||||
<Link href="/dashboard" className="ms-auto text-xs text-gray-500 transition-colors hover:text-gray-300">{back}</Link>
|
||||
</header>
|
||||
<main className="mx-auto max-w-7xl px-5 py-7">{children}</main>
|
||||
</div>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user