我的 Next.js 14 项目有问题,该项目使用应用程序路由器。我使用 [lang] 文件夹来本地化我的应用程序。因此,我拥有所有页面,包括 [lang] 文件夹内的 page.tsx 和 layout.tsx。这样,我就可以将语言环境传递到我的所有页面,如下所示:
export default function Home({ params }: { params: { lang: string } }) {
const s = dictionary[params.lang];
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<p>{s.home.title}</p>
</main>
);
}
这是我的 middleware.ts 文件:
let locales = ["en", "de"];
export let defaultLocale = "en";
function getLocale(request: Request): string {
const headers = new Headers(request.headers);
const acceptLanguage = headers.get("accept-language");
if (acceptLanguage) {
headers.set("accept-language", acceptLanguage.replaceAll("_", "-"));
}
const headersObject = Object.fromEntries(headers.entries());
const languages = new Negotiator({ headers: headersObject }).languages();
return match(languages, locales, defaultLocale);
}
// Without /locale in path
export function middleware(request: NextRequest) {
let locale = getLocale(request) ?? defaultLocale;
const pathname = request.nextUrl.pathname;
const newUrl = new URL(`/${locale}${pathname}`, request.nextUrl);
return NextResponse.rewrite(newUrl);
}
export const config = {
matcher: [
// Skip all internal paths (_next)
"/((?!_next|api|favicon.ico|robots.txt|sitemap.xml).*)",
// Optional: only run on root (/) URL
// '/'
],
};
我的文件夹结构是:
my-app/
├─ ...
├─ public/
│ ├─ favicon.ico
│ ├─ robots.txt
├─ src/
│ ├─ app/
│ │ ├─ [lang]/
│ │ │ ├─ page.tsx
│ │ │ ├─ layout.tsx
│ │ │ ├─ not-found.tsx
│ ├─ api/
├─ ...
问题是,当我将 not-found.tsx 放入 [lang] 文件夹中时,它不起作用。在未知的路线上我得到默认的 404 页面。但是,当我将它直接放在 [lang] 之外的应用程序文件夹中时,它确实可以工作,但我没有获得语言环境,并且获得没有布局的页面。解决方法是在应用程序目录中创建另一个layout.tsx,但同样无法对其进行本地化,这只是糟糕的用户体验。
我尝试将 not-found.tsx 复制到 [lang] 文件夹中,以便能够获取应用程序区域设置来本地化我的内容。根据 Next.js 文档,这应该是开箱即用的。
有人遇到过这样的问题吗
这个答案记录了我对同一问题的解决方案,您可能会发现它合适或不合适。
首先,将
not-found.tsx
定位在app/[lang]/not-found.tsx
。
在根目录下,创建一个
app/layout.tsx
,除了返回其 children
属性之外,不执行任何操作:
import { type ReactNode } from "react";
export default function GlobalLayout({ children }: { children: ReactNode }) {
return children;
}
not-found.tsx
:这里您有两个选择:
"use client";
import { redirect, usePathname } from "next/navigation";
import { defaultLocale } from "@/config/constants";
export default function NotFound() {
const pathname = usePathname();
redirect(`/${defaultLocale}${pathname}`);
}