platforms
platforms copied to clipboard
i18n locales 404 issues
Hello. I have issues with i18n locales. I currently have only 2 locales, but when turned on in next.config all paths renders as 404 when deployed to Vercel. Locally everything works as expected.
I have tried several approaches, tried to add basePath as someone suggested like for example:
url.pathname = `${basePath}/_sites/${currentHost}${pathname}`;
return NextResponse.rewrite(url);
It did nothing, basically.
Tried to add locale too as someone suggested, for example:
url.pathname = `${basePath}/${locale}/_sites/${currentHost}${pathname}`;
return NextResponse.rewrite(url);
and it somewhat works. Default locale works, but on some pages secondary locale gives 404 still, like:
subdomain.domain.something/secondarylocale subdomain.domain.something/secondarylocale/somepage
if I add en, which is default locale it works:
subdomain.domain.something/en subdomain.domain.something/en/somepage
Full _middleware:
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export default function middleware(req: NextRequest) {
// Clone the request url
const url = req.nextUrl.clone();
// Get pathname of request (e.g. /blog-slug)
const { pathname, basePath } = req.nextUrl;
const locale = req.nextUrl.locale;
// Get hostname of request (e.g. demo.xy.com)
const hostname = req.headers.get("host");
if (!hostname)
return new Response(null, {
status: 400,
statusText: "No hostname found in request headers",
});
// Only for demo purposes – remove this if you want to use your root domain as the landing page
// if (
// hostname === "xy.com" ||
// hostname === "platforms.vercel.app"
// ) {
// return NextResponse.redirect("https://demo.xy.com");
// }
const PUBLIC_FILE = /\.(.*)$/;
const currentHost =
process.env.NODE_ENV === "production" && process.env.VERCEL === "1"
? // You have to replace ".xy.com" with your own domain if you deploy this example under your domain.
// You can use wildcard subdomains on .vercel.app links that are associated with your Vercel team slug
// in this case, our team slug is "platformize", thus *.platformize.vercel.app works
hostname.replace(`.xy.com`, "")
: hostname.replace(`.localhost:3000`, "");
console.log(
"req",
locale,
// "end",
"basePath",
basePath,
"end",
process.env.NODE_ENV,
process.env.VERCEL,
"host",
req.headers.get("host"),
"current host",
currentHost
);
if (pathname.startsWith(`/_sites`))
return new Response(null, {
status: 404,
});
if (
!pathname.includes(".") &&
!pathname.startsWith("/api") &&
!PUBLIC_FILE.test(req.nextUrl.pathname)
) {
if (currentHost == "app") {
if (
pathname === "/login" &&
(req.cookies["next-auth.session-token"] ||
req.cookies["__Secure-next-auth.session-token"])
) {
url.pathname = `${basePath}/${locale}`;
return NextResponse.redirect(url);
} else if (!pathname) {
url.pathname = `${basePath}/${locale}/_sites/${currentHost}`;
return NextResponse.rewrite(url);
}
url.pathname = `${basePath}/${locale}/app${pathname}`;
return NextResponse.rewrite(url);
}
if (hostname === "localhost:3000" || hostname === "xy.com") {
url.pathname = `${basePath}/${locale}/home${pathname}`;
return NextResponse.rewrite(url);
}
url.pathname = `${basePath}/${locale}/_sites/${currentHost}${pathname}`;
return NextResponse.rewrite(url);
}
}
im having the exact same issue when using i18n
Well if you log stuff, you will see strange behavior, it does not add locale to the URL for default locale, but does for other ones.
If you do:
url.pathname = `/${locale}/_sites/${currentHost}${pathname}`;
then your default one will work, but you'll get 404 on all others. And reason is that other locales are added twice, once by you, and once by system. I solved it by adding this:
const { pathname, locale, defaultLocale } = req.nextUrl;
.
.
.
if (currentHost == "app") {
if (
pathname === "/login" &&
(req.cookies["next-auth.session-token"] ||
req.cookies["__Secure-next-auth.session-token"])
) {
url.pathname = `/${locale}`;
return NextResponse.redirect(url);
}
url.pathname = `/${locale}/app${pathname}`;
return NextResponse.rewrite(url);
}
if (hostname === "localhost:3000" || hostname === "yourdomain.something") {
url.pathname = `/${locale}/home${pathname}`;
return NextResponse.rewrite(url);
}
if (locale === defaultLocale) {
url.pathname = `/${locale}/_sites/${currentHost}${pathname}`;
return NextResponse.rewrite(url);
}
url.pathname = `/_sites/${currentHost}${pathname}`;
return NextResponse.rewrite(url);
}
Hope it helps
Hey guys! Sorry for the late response but this should've been fixed in the latest version of Next.js. Feel free to reference this issue here: https://github.com/vercel/next.js/issues/36563
The problem still exists:
nextjs version
"next": "13.2.4",
middleware code:
import { NextRequest, NextResponse } from "next/server";
export const config = {
matcher: [
"/((?!api/|_next/|_static/|/|[\\w-]+\\.\\w+).*)",
],
};
export default async function middleware(req: NextRequest) {
const url = req.nextUrl;
const hostname = req.headers.get("host") || "demo.localhost:3000";
const path = url.pathname;
return NextResponse.rewrite(
new URL(`/_sites/${currentHost}${path}`, req.url)
);
}
nextconfig code
/**
* @format
* @type {import('next').NextConfig}
*/
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
const nextConfig = {
reactStrictMode: true,
poweredByHeader: false,
i18n: {
localeDetection: false,
locales: ['en', 'cn', 'jp', 'it', 'tw', 'kr', 'hk', 'fr'],
defaultLocale: 'cn',
}
};
module.exports = withBundleAnalyzer(nextConfig);
The problem still exists