Multi Tenant with NextIntl
Unanswered
Bull Arab posted this in #help-forum
Bull ArabOP
Any guide integrate Next Intl into multi-tenant app with custom domain
20 Replies
What did you try, what didn't work?
Bull ArabOP
Currently I have setup NextIntl with NextAuth in my NextJs project that all pages is require to wrap in [locale], it works well.
https://vercel.com/guides/nextjs-multi-tenant-application
My question is how to setup Localizing into NextJs Multiple Tenant Application
I have no idea how to setup, do I have to wrap the [domain] under [locale] and how do I config the next auth matches on the Url ?
https://vercel.com/guides/nextjs-multi-tenant-application
My question is how to setup Localizing into NextJs Multiple Tenant Application
I have no idea how to setup, do I have to wrap the [domain] under [locale] and how do I config the next auth matches on the Url ?
Asian black bear
You'll need to combine the middleware from your i18n package and implement the multi-tenant rewrites yourself. The Vercel platforms middleware is a good start: https://github.com/vercel/platforms/blob/main/middleware.ts
I'm using next-international but it should be somewhat similar: https://gist.github.com/kylekz/b698239da2ea94045fbe3d40b46f31e7
I'm using next-international but it should be somewhat similar: https://gist.github.com/kylekz/b698239da2ea94045fbe3d40b46f31e7
Bull ArabOP
Do you have experience share the sample code of it ?
@Bull Arab Do you have experience share the sample code of it ?
you'd rather want to give it a try, and then share more specific questions to us
Bull ArabOP
Alright.
Before I give it a try. May I know the [domain] is wrap under [locale] or [locale] wrap into [domain]?
you can encode both into the same param, if you want them to invisible
if you want the locale to be visible though, I would do /domain -> /locale
because there are chances that the local is visible in the url like "foo.com/fr/hello"
and you want to add the domain, invisible via a rewrite adding it as the first part of the path
"domain/fr"
and locales are also easy to identify if you want to tell if the path contains a locale already or not (they are always 2 chars long and known in advance)
Bull ArabOP
Folder Structure
- app
- [locale]
- [domain]Bull ArabOP
Middleware.ts
const intlMiddleware = createIntlMiddleware({
locales,
localePrefix: "never",
defaultLocale: "en",
});
const authMiddleware = withAuth(
function onSuccess(req) {
return intlMiddleware(req);
},
{
callbacks: {
authorized: ({ token }) => token != null,
},
pages: {
signIn: "/login",
},
}
);
export default function middleware(req: NextRequest) {
const url = req.nextUrl;
const publicPathnameRegex = RegExp(
`^(/(${locales.join("|")}))?(${publicPages
.flatMap((p) => (p === "/" ? ["", "/"] : p))
.join("|")})/?$`,
"i"
);
const isPublicPage = publicPathnameRegex.test(req.nextUrl.pathname);
const hostname = req.headers
.get("host")!
.replace(".localhost:3000", `.${process.env.NEXT_PUBLIC_HOSTNAME_URL}`);
const searchParams = req.nextUrl.searchParams.toString();
const path = `${url.pathname}${
searchParams.length > 0 ? `?${searchParams}` : ""
}`;
if (
hostname === "localhost:3000" ||
hostname === process.env.NEXT_PUBLIC_ROOT_DOMAIN
) {
return NextResponse.rewrite(
new URL(`/home${path === "/" ? "" : path}`, req.url),
);
}
return NextResponse.rewrite(new URL(`/en/${hostname}${path}`, req.url));
} This work multi tenant with subdomain. But useTranslations is not work with on pagesimport { localesConfig } from "constants/locale";
import { withAuth } from "next-auth/middleware";
import createIntlMiddleware from "next-intl/middleware";
import { NextRequest, NextResponse } from "next/server";
const locales = localesConfig;
const publicPages = [
"/",
"/login",
"/register",
"/forgot-password",
"/products/*",
"/home/*",
];
const intlMiddleware = createIntlMiddleware({
locales,
localePrefix: "never",
defaultLocale: "en",
});
const authMiddleware = withAuth(
// Note that this callback is only invoked if
// the `authorized` callback has returned `true`
// and not for pages listed in `pages`.
function onSuccess(req) {
return intlMiddleware(req);
},
{
callbacks: {
authorized: ({ token }) => token != null,
},
pages: {
signIn: "/login",
},
}
);
export default function middleware(req: NextRequest) {
const url = req.nextUrl;
const publicPathnameRegex = RegExp(
`^(/(${locales.join("|")}))?(${publicPages
.flatMap((p) => (p === "/" ? ["", "/"] : p))
.join("|")})/?$`,
"i"
);
// Test Public Page List
const isPublicPage = publicPathnameRegex.test(req.nextUrl.pathname);
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
const hostname = req.headers
.get("host")!
.replace(".localhost:3000", `.${process.env.NEXT_PUBLIC_HOSTNAME_URL}`);
const searchParams = req.nextUrl.searchParams.toString();
// Get the pathname of the request (e.g. /, /about, /blog/first-post)
const path = `${url.pathname}${
searchParams.length > 0 ? `?${searchParams}` : ""
}`;
if (isPublicPage) {
return intlMiddleware(req);
} else {
return (authMiddleware as any)(req);
}
}Require to use intlMiddleware to get useTranslations to get work.
Could you give me an advice how to make intlMiddleware work with your multi tenant NextResponse.rewrite ?
Bull ArabOP
This project i have implement NextAuth & Next-Intl with this multi tenant