Next.js Discord

Discord Forum

Issue with Auth api routes working alongside localizaztion

Answered
Spectacled bear posted this in #help-forum
Open in Discord
Spectacled bearOP
OK, here's my weird question but I don't understand how this works, here's part of my current app structure:
src
app/[lang]
api
(auth)/[...nextauth]/route.ts

(see img)

the way it woirks is, it appends /en or /el to the url depending on the locale (so instead of /portfolio, it's now /en/portfolio || /el/portfolio)
Should I be keeping the api routes like that though? for example, for nextauth, the route becomes /en/api/auth/providers instead of being /api/auth/providers
the above route should eb returning json with my providers, but it doesnt, instead it returns "bad request".
Should I be excluding api routes from that locale rule?
Answered by Spectacled bear
added
if (request.url.includes("/api/")) {
            return;
        }

to stop middleware from redirecting /[locale]/api/ urls, moved api routes outside of /[lang] (/app/[lang]/api -> /app/api and /app/[locale]
View full answer

2 Replies

Spectacled bearOP
middleware.ts:
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

import { i18n } from '../i18n-config';

import { match as matchLocale } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';

function getLocale(request: NextRequest): string | undefined {
    // Negotiator expects plain object so we need to transform headers
    const negotiatorHeaders: Record<string, string> = {};
    request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));

    // Use negotiator and intl-localematcher to get best locale
    let languages = new Negotiator({ headers: negotiatorHeaders }).languages();
    // @ts-ignore locales are readonly
    const locales: string[] = i18n.locales;
    return matchLocale(languages, locales, i18n.defaultLocale);
}

export function middleware(request: NextRequest) {
    const pathname = request.nextUrl.pathname;

    // `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually.
    // If you have one
    if (
        [
            '/manifest.json',
            '/favicon.ico',
            // Your other files in `public`
        ].includes(pathname)
    )
        return;

    // Check if there is any supported locale in the pathname
    const pathnameIsMissingLocale = i18n.locales.every(
        (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
    );

    // Redirect if there is no locale
    if (pathnameIsMissingLocale) {
        const locale = getLocale(request);

        // e.g. incoming request is /products
        // The new URL is now /en-US/products
        return NextResponse.redirect(new URL(`/${locale}/${pathname}`, request.url));
    }
}

import { auth } from './auth';

export default auth((request: NextRequest) => {
    console.log("ROUTE: ", request.nextUrl.pathname);
})

export const config = {
    matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
Spectacled bearOP
added
if (request.url.includes("/api/")) {
            return;
        }

to stop middleware from redirecting /[locale]/api/ urls, moved api routes outside of /[lang] (/app/[lang]/api -> /app/api and /app/[locale]
Answer