86 lines
3.2 KiB
TypeScript
86 lines
3.2 KiB
TypeScript
import type { I18nConfig } from './types.js';
|
|
/**
|
|
* Minimal request shape the middleware reads. Kept structural so the plugin
|
|
* doesn't hard-depend on next/server types; a Next.js `NextRequest` satisfies it.
|
|
*/
|
|
type MiddlewareRequest = {
|
|
cookies: {
|
|
get: (name: string) => {
|
|
value: string;
|
|
} | undefined;
|
|
};
|
|
headers: {
|
|
get: (name: string) => null | string;
|
|
};
|
|
nextUrl: {
|
|
clone: () => URL;
|
|
pathname: string;
|
|
search: string;
|
|
};
|
|
url: string;
|
|
};
|
|
/**
|
|
* What the factory returns — the caller (in Next middleware.ts) decides how to
|
|
* act: `redirect` means send a 307 to `location` and set the locale cookie;
|
|
* `next` means let the request pass through untouched.
|
|
*/
|
|
export type LocaleMiddlewareResult = {
|
|
cookie?: {
|
|
name: string;
|
|
value: string;
|
|
};
|
|
location: string;
|
|
type: 'redirect';
|
|
} | {
|
|
type: 'next';
|
|
};
|
|
type CreateLocaleMiddlewareArgs = {
|
|
config: I18nConfig;
|
|
/**
|
|
* Consent category that gates *persisting* the locale cookie. The locale is
|
|
* always detected (routing works regardless), but the choice is only written
|
|
* to a cookie once the visitor has consented to this category. Defaults to
|
|
* 'functional'. Pass 'necessary' to always persist (treat locale as strictly
|
|
* necessary), which restores the pre-consent behaviour.
|
|
*/
|
|
consentCategory?: 'functional' | 'necessary';
|
|
/** Name of the consent cookie to read. Defaults to CONSENT_COOKIE. */
|
|
consentCookieName?: string;
|
|
/** Cookie name for the locale choice. Defaults to LOCALE_COOKIE_NAME. */
|
|
cookieName?: string;
|
|
};
|
|
/**
|
|
* Builds locale-routing logic for Next.js middleware.
|
|
*
|
|
* Behavior:
|
|
* - path already starts with a valid locale (/pl/...) → pass through
|
|
* - any other path (/, /o-nas) → redirect to /{locale}{path}, where locale
|
|
* comes from negotiateLocale (cookie → Accept-Language → default)
|
|
* - the chosen locale is written to a cookie so the next visit is stable
|
|
*
|
|
* The plugin returns a decision; the thin middleware.ts in the client project
|
|
* turns it into a NextResponse. This keeps all logic in the plugin while
|
|
* respecting that middleware.ts must physically live in the client app.
|
|
*
|
|
* @example
|
|
* // middleware.ts (client project) — one wiring file, no logic:
|
|
* import { NextResponse } from 'next/server'
|
|
* import { localeMiddleware } from './ipal.middleware' // created from this factory
|
|
* export function proxy(req) {
|
|
* const r = localeMiddleware(req)
|
|
* if (r.type === 'next') return NextResponse.next()
|
|
* const res = NextResponse.redirect(r.location)
|
|
* // cookie is optional: only present when the visitor consented to the
|
|
* // gating category (functional by default). Guard before setting.
|
|
* if (r.cookie) res.cookies.set(r.cookie.name, r.cookie.value)
|
|
* return res
|
|
* }
|
|
*/
|
|
export declare function createLocaleMiddleware({ config, consentCategory, consentCookieName, cookieName, }: CreateLocaleMiddlewareArgs): (request: MiddlewareRequest) => LocaleMiddlewareResult;
|
|
/**
|
|
* Default Next.js middleware matcher: run on everything except API routes, the
|
|
* admin panel, Next internals, and files with an extension (static assets).
|
|
*/
|
|
export declare const DEFAULT_MIDDLEWARE_MATCHER: string[];
|
|
export {};
|