QuiiBz / next-international

Type-safe internationalization (i18n) for Next.js
https://next-international.vercel.app
MIT License
1.25k stars 59 forks source link

Questions about middleware #224

Closed iStorry closed 11 months ago

iStorry commented 11 months ago
import { type NextRequest } from "next/server";
import { getToken } from "next-auth/jwt";
import { createI18nMiddleware } from "next-international/middleware";

const I18nMiddleware = createI18nMiddleware({
  locales: ["en", "ja"],
  defaultLocale: "en",
  urlMappingStrategy: "rewrite",
});

export async function middleware(req: NextRequest) {
  const session = await getToken({ req });

  const { role, profile } = session?.user ?? {};

  if (role === "user" && !profile) {
    const url = req.nextUrl.clone();
    url.pathname = `/user/profile`;
    return NextResponse.rewrite(url);
  }

  return I18nMiddleware(req);
}

The NextResponse return 404 page. I think it's because of I18nMiddleware

QuiiBz commented 11 months ago

Please send a complete reproduction, I can't help with only this middleware file.

gustaveWPM commented 11 months ago

Well, I think it is not the good way to nest middlewares.

Ping @iStorry

Maybe something like this? (In terms of code structure. It is up to you to adapt this base to see if you can solve your problem with this way to nest middlewares.)

import { DEFAULT_LANGUAGE, LANGUAGES } from '@/config/i18n';
import { getPathnameWithoutI18nFlag } from '@/lib/i18n';
import { withAuth } from 'next-auth/middleware';
import { createI18nMiddleware } from 'next-international/middleware';
import { NextRequest, NextResponse } from 'next/server';

const PROTECTED_ROUTES = ['/dashboard'];
export const config = {
  matcher: ['/((?!api|static|_next|.*\\..*).*)']
};

const I18nMiddlewareInstance = createI18nMiddleware({
  locales: LANGUAGES,
  defaultLocale: DEFAULT_LANGUAGE,
  urlMappingStrategy: 'rewrite'
});

function i18nMiddleware(request: NextRequest) {
  const i18nResponse: NextResponse = I18nMiddlewareInstance(request);
  return i18nResponse;
}

const authMiddleware = withAuth(
  function onSuccess(req) {
    return i18nMiddleware(req);
  },
  {
    pages: {
      signIn: '/sign-up'
    }
  }
);

export default function middleware(req: NextRequest) {
  const currentRoute = getPathnameWithoutI18nFlag(req.nextUrl.pathname);
  const isProtectedRoute = PROTECTED_ROUTES.find((r) => currentRoute.startsWith(r));

  return isProtectedRoute ? (authMiddleware as any)(req) : i18nMiddleware(req);
}

See also: https://next-intl-docs.vercel.app/docs/routing/middleware#example-auth-js

(It's the documentation for next-intl instead of Next International, but the principle remains more or less the same.)

iStorry commented 11 months ago

Thanks @gustaveWPM i will look into it tomorrow

QuiiBz commented 11 months ago

See also https://github.com/QuiiBz/next-international/issues/187 - closing as it isn't directly related to next-international.

gustaveWPM commented 11 months ago

See also #187 - closing as it isn't directly related to next-international.

Omg, it looks like a better way to solve the problem than mine. To be honest, I'm also struggling with something similar, haha!

Thank you.