我正在分享我的
middleware.ts
和 i18n.ts
。
这是我第一次在
next.js
中进行本地化,我成功了,但现在我正在与 URL
作斗争,因为我不希望在默认版本中使用 "cs"
,并且正在添加 "cs"
URL
,即使我不输入它。
next-intl
中是否有任何设置可以防止这种情况发生?
我什至不知道从哪里开始,我试图从
"cs"
中删除matcher
,但我相信这对“向URL添加cs”没有影响。
还尝试将
localeDetection: false,
添加到 return
的
i18n.ts
值
所以安装了
http://localhost:3000/
我每次都会得到http://localhost:3000/cs
。
感谢您的任何建议。
Middleware.ts
export default createMiddleware({
// A list of all locales that are supported
locales: ["cs", "en"],
// Used when no locale matches
defaultLocale: "cs",
});
export const config = {
// Match only internationalized pathnames
matcher: ["/", "/(cs|en)/:path*"],
};
i18n.ts
import { notFound } from "next/navigation";
import { getRequestConfig } from "next-intl/server";
// Can be imported from a shared config
const locales = ["cs"];
export default getRequestConfig(async ({ locale }) => {
// Validate that the incoming `locale` parameter is valid
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
if (!locales.includes(locale as any)) notFound();
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
messages: (await import(`/i18n/${locale}.json`)).default,
};
});
根据文档,在页面路由器中,当我们将所有页面放置在 /pages 中时,从 URL 中隐藏默认语言版本是标准行为。不幸的是,App Router 中的情况并非如此。我搜索了各种解决方案,但没有任何效果,所以我只是将 /app/[locale]/ 中的所有内容复制到 /app/ 。这是一个丑陋的解决方案,因为我们必须两次维护所有文件,但至少它有效。遗憾的是 Vercel 还没有解决这个问题。这是我的 middleware.ts 工作代码。
import { NextResponse } from 'next/server';
import type { NextRequest } 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 {
const negotiatorHeaders: Record<string, string> = {};
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
const locales: string[] = i18n.locales;
const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
const locale = matchLocale(languages, locales, i18n.defaultLocale);
return locale;
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
if (pathname.startsWith('/en')) {
const newPathname = pathname.replace(/^\/en/, '');
return NextResponse.redirect(new URL(newPathname || '/', request.url));
}
const pathnameIsMissingLocale = i18n.locales.every(
locale => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
);
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
if (locale === i18n.defaultLocale) {
return NextResponse.next();
}
return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url));
}
return NextResponse.next();
}
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico|public|img|fonts).*)',
],
};