我使用 Sanity CMS 在 Next js 上开发了一个网站。 AppRouter技术。我的网站支持英语和德语。问题是主域上没有主页,因为文件夹结构如下:app/[lang]/page.tsx.
因此,主页始终位于 mysite.com/en 或 mysite.com/de。是否可以以某种方式重新配置项目,以便主页位于 mysite.com 而不带斜线?你知道我如何将地址“/en”切换为“/”吗?
我已经这样设置了内化:
// i18n.config.ts
const languages = [
{ id: 'de', title: 'German' },
{ id: 'en', title: 'English', isDefault: true },
];
const i18n = {
languages,
base: languages.find((item) => item.isDefault)?.id,
};
export { i18n };
// 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.languages.map(lang => lang.id);
const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
const locale = matchLocale(languages, locales, i18n.base || "id");
return locale;
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
const pathnameIsMissingLocale = i18n.languages.every(
locale =>
!pathname.startsWith(`/${locale.id}/`) && pathname !== `/${locale.id}`
);
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
request.url
)
);
}
}
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher: [
"/((?!api|_next/static|admin|structure|robots|sitemap|_next/image|favicon.ico).*)"
]
};
如果您的网站主页重定向到带有区域设置的路径,那是没有问题的,因为这支持国际化,但我会尝试根据我的理解提供解决方案。 您可以更改您的
if
语句,以便当路径名是主页时,您不会向其添加区域设置,但这会带来不便,您必须在 app/page.tsx
创建一个单独的页面(请注意,没有 [lang]
),您可以使用该页面的默认语言:英语。
if (pathnameIsMissingLocale && pathname !== "/") {
const locale = getLocale(request);
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
request.url
)
);
}
还有另一种解决方法,即使在没有区域设置的主页中也可以使用国际化,但你必须在主页中使用 negotiator,例如:
// app/page.tsx
import { headers } from 'next/headers'
// You can declare this in a separate file and use it in both this page and middleware
function getLocale(request: NextRequest): string | undefined {
const negotiatorHeaders: Record<string, string> = {};
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
const locales: string[] = i18n.languages.map(lang => lang.id);
const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
const locale = matchLocale(languages, locales, i18n.base || "id");
return locale;
}
export function HomePage(): JSX.Element {
const acceptLanguage = headers().get("accept-language");
const req = {
"accept-language": acceptLanguage
}
const locale = getLocale(req);
// You can render content dynamically depending on locale value (en or de);
return(
...
)
}