我想创建一个多语言网站。我已经遵循了官方文档。
我创建了这样的中间件:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
let headers = { 'accept-language': 'en-US,en;q=0.5' }
let languages = new Negotiator({ headers }).languages()
let locales = ['en', 'nl', 'fr']
let defaultLocale = 'nl'
// Get the preferred locale, similar to above or using a library
function getLocale(request: any): string {
return match(languages, locales, defaultLocale) // -> 'en-US'
}
export default function middleware(request: NextRequest) {
// Check if there is any supported locale in the pathname
console.log("Middleware is executed");
const pathname = request.nextUrl.pathname
const pathnameIsMissingLocale = locales.every(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
console.log(locale);
console.log(request);
// e.g. incoming request is /products
// The new URL is now /en-US/products
return NextResponse.redirect(
new URL(`/${locale}/${pathname}`, request.url)
)
}
return NextResponse.next();
}
export const config = {
matcher: [
// Skip all internal paths (_next)
'/((?!_next).*)',
// Optional: only run on root (/) URL
// '/'
],
}
结构是这样的
我有一个语言切换器:
import Link from "next/link";
export default function LanguageSwitcher() {
return (
<ul>
<li><Link href="/" locale="en">EN</Link></li>
<li><Link href="/" locale="nl">NL</Link></li>
<li><Link href="/" locale="fr">FR</Link></li>
</ul>
)
}
我有几个问题:
我检查了多个博客,但首先他们谈论页面路由(旧系统),+它们包含一些其他包,为了简单起见,我实际上并不需要这些包。 虽然我已经尝试过这些库,但无论如何都无法正常工作。
在中间件函数中,有一行检查路径名是否丢失,如下所示:
const pathnameIsMissingLocale = locales.every(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
但是通过这样做,您要求它检查路径名是否具有每个语言环境,并且您应该寻找 .some() 因为如果它与其中一个语言环境匹配,就足以知道它是正确的。
所以改成:
const pathnameIsMissingLocale = locales.some(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
这应该可以处理未重定向到正确位置的链接。现在关于保留默认语言,更改中间件以包含此:
//...
const url = req.nextUrl.clone()
const pathnameIsMissingLocale = locales.some(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
const isDefaultLocale = !pathNameIsMissingLocale || pathname.startsWith(`/${defaultLocale}/`)
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
locale === defaultLocale
? url.pathname = `/${pathname}`
: url.pathname = `/${locale}/${pathname}`
return NextResponse.redirect(url)
}
if(isDefaultLocale) {
url.pathname = `/${pathname}`
return NextResponse.redirect(url)
}
//...
此更改应检查链接是否为 defaultLocale 并相应地更改路径名
测试人员通常使用 Locale 来更改站点中的语言。