import type { I18nConfig } from '../i18n/index.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 = { nextUrl: { pathname: string; search: string; clone: () => URL; }; cookies: { get: (name: string) => { value: string; } | undefined; }; headers: { get: (name: string) => string | null; }; 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 = { type: 'next'; cookie?: { name: string; value: string; }; } | { type: 'redirect'; location: string; cookie?: { name: string; value: string; }; }; type CreateLocaleMiddlewareArgs = { config: I18nConfig; /** Cookie name for the locale choice. Defaults to LOCALE_COOKIE_NAME. */ cookieName?: string; /** * 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?: 'necessary' | 'functional'; /** Name of the consent cookie to read. Defaults to CONSENT_COOKIE. */ consentCookieName?: 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) * // Both results may carry an optional cookie — 'next' when the visitor * // switched language (URL locale differs from the stored one) and consented, * // 'redirect' on the initial locale negotiation. Set it whenever present. * const res = r.type === 'next' ? NextResponse.next() : NextResponse.redirect(r.location) * if (r.cookie) res.cookies.set(r.cookie.name, r.cookie.value) * return res * } */ export declare function createLocaleMiddleware({ config, cookieName, consentCategory, consentCookieName, }: 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 {};