feat(i18n): make language a user profile attribute (register/profile/login)
All checks were successful
Build and Push / build (push) Successful in 1m47s
All checks were successful
Build and Push / build (push) Successful in 1m47s
This commit is contained in:
@@ -6,6 +6,20 @@ import { routing } from "@/i18n/routing";
|
||||
|
||||
const intlMiddleware = createIntlMiddleware(routing);
|
||||
|
||||
// One-time marker: set after we've applied the user's profile language
|
||||
// once following sign-in, cleared whenever the login page is shown (so
|
||||
// the next sign-in re-applies it). Keeps the header switcher a
|
||||
// per-session override rather than forcing the profile locale on every
|
||||
// navigation.
|
||||
const LOCALE_INIT_COOKIE = "pieced_locale_init";
|
||||
|
||||
const LOCALE_INIT_OPTS = {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
sameSite: "lax" as const,
|
||||
maxAge: 8 * 60 * 60,
|
||||
};
|
||||
|
||||
const publicPaths = ["/login", "/register", "/api/auth", "/api/register"];
|
||||
|
||||
function isPublicPath(pathname: string): boolean {
|
||||
@@ -26,6 +40,17 @@ export default async function middleware(request: NextRequest) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
const stripped = pathname.replace(/^\/(de|fr|it|en)(?=\/|$)/, "") || "/";
|
||||
|
||||
// Showing the login page resets the one-time locale marker so the
|
||||
// next sign-in re-applies the user's profile language. Logout
|
||||
// redirects here, which makes this the natural reset point.
|
||||
if (stripped === "/login") {
|
||||
const res = intlMiddleware(request);
|
||||
res.cookies.delete(LOCALE_INIT_COOKIE);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Auth guard for protected paths
|
||||
if (!isPublicPath(pathname)) {
|
||||
const session = await auth();
|
||||
@@ -34,6 +59,32 @@ export default async function middleware(request: NextRequest) {
|
||||
loginUrl.searchParams.set("callbackUrl", pathname);
|
||||
return NextResponse.redirect(loginUrl);
|
||||
}
|
||||
|
||||
// One-time apply of the user's preferred language after sign-in.
|
||||
// Gated by LOCALE_INIT_COOKIE (cleared on the /login view), so it
|
||||
// fires at most once per login; afterwards the URL and the header
|
||||
// switcher control the locale freely.
|
||||
const applied = request.cookies.get(LOCALE_INIT_COOKIE)?.value === "1";
|
||||
const pref = (session as { platformUser?: { locale?: string } })
|
||||
.platformUser?.locale;
|
||||
const base = pref?.split("-")[0];
|
||||
if (!applied && base && routing.locales.includes(base as never)) {
|
||||
const target =
|
||||
base === routing.defaultLocale
|
||||
? stripped
|
||||
: `/${base}${stripped === "/" ? "" : stripped}`;
|
||||
if (target !== pathname) {
|
||||
const url = new URL(target, request.url);
|
||||
url.search = request.nextUrl.search;
|
||||
const res = NextResponse.redirect(url);
|
||||
res.cookies.set(LOCALE_INIT_COOKIE, "1", LOCALE_INIT_OPTS);
|
||||
return res;
|
||||
}
|
||||
// Already on the right locale — mark applied and continue.
|
||||
const res = intlMiddleware(request);
|
||||
res.cookies.set(LOCALE_INIT_COOKIE, "1", LOCALE_INIT_OPTS);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return intlMiddleware(request);
|
||||
|
||||
Reference in New Issue
Block a user