feat(i18n): detect browser language as default locale
On first visit (no PARAGLIDE_LOCALE cookie), parse the Accept-Language request header and set the cookie to the best matching supported locale (de/en/es). The user's manual choice via the switcher always takes precedence since the detection is skipped when the cookie exists. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,9 +2,34 @@ import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit';
|
|||||||
import { paraglideMiddleware } from '$lib/paraglide/server';
|
import { paraglideMiddleware } from '$lib/paraglide/server';
|
||||||
import { sequence } from '@sveltejs/kit/hooks';
|
import { sequence } from '@sveltejs/kit/hooks';
|
||||||
import { env } from 'process';
|
import { env } from 'process';
|
||||||
|
import { cookieName, cookieMaxAge, locales } from '$lib/paraglide/runtime';
|
||||||
|
|
||||||
const PUBLIC_PATHS = ['/login', '/logout'];
|
const PUBLIC_PATHS = ['/login', '/logout'];
|
||||||
|
|
||||||
|
function detectLocale(acceptLanguage: string): string | null {
|
||||||
|
const preferred = acceptLanguage
|
||||||
|
.split(',')
|
||||||
|
.map((part) => {
|
||||||
|
const [lang, q] = part.trim().split(';q=');
|
||||||
|
return { lang: lang.trim().split('-')[0].toLowerCase(), q: q ? parseFloat(q) : 1 };
|
||||||
|
})
|
||||||
|
.sort((a, b) => b.q - a.q);
|
||||||
|
for (const { lang } of preferred) {
|
||||||
|
if ((locales as readonly string[]).includes(lang)) return lang;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLocaleDetection: Handle = ({ event, resolve }) => {
|
||||||
|
if (!event.cookies.get(cookieName)) {
|
||||||
|
const locale = detectLocale(event.request.headers.get('accept-language') ?? '');
|
||||||
|
if (locale) {
|
||||||
|
event.cookies.set(cookieName, locale, { path: '/', sameSite: 'lax', maxAge: cookieMaxAge });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resolve(event);
|
||||||
|
};
|
||||||
|
|
||||||
const handleAuth: Handle = async ({ event, resolve }) => {
|
const handleAuth: Handle = async ({ event, resolve }) => {
|
||||||
const isPublic = PUBLIC_PATHS.some((p) => event.url.pathname.startsWith(p));
|
const isPublic = PUBLIC_PATHS.some((p) => event.url.pathname.startsWith(p));
|
||||||
if (!isPublic && !event.locals.user) {
|
if (!isPublic && !event.locals.user) {
|
||||||
@@ -74,4 +99,4 @@ export const handleFetch: HandleFetch = async ({ event, request, fetch }) => {
|
|||||||
return fetch(request);
|
return fetch(request);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handle = sequence(userGroup, handleAuth, handleParaglide);
|
export const handle = sequence(userGroup, handleAuth, handleLocaleDetection, handleParaglide);
|
||||||
|
|||||||
Reference in New Issue
Block a user