安装插件
npm install i18next react-i18next i18next-resources-to-backend
1. 目录结构
.
└── app
└── [lng]
├── second-page
| └── page.js
├── layout.js
└── page.js
app/[lng]/page.js
文件:
import Link from 'next/link'
export default function Page({ params: { lng } }) {
return (
<>
<h1>Hi there!</h1>
<Link href={`/${lng}/second-page`}>
second page
</Link>
</>
)
}
app/[lng]/second-page/page.js
文件:
import Link from 'next/link'
export default function Page({ params: { lng } }) {
return (
<>
<h1>Hi from second page!</h1>
<Link href={`/${lng}`}>
back
</Link>
</>
)
}
app/[lng]/layout.js
文件:
import { dir } from 'i18next'
const languages = ['en', 'de']
export async function generateStaticParams() {
return languages.map((lng) => ({ lng }))
}
export default function RootLayout({
children,
params: {
lng
}
}) {
return (
<html lang={lng} dir={dir(lng)}>
<head />
<body>
{children}
</body>
</html>
)
}
2. 语言识别
现在导航到http://localhost:3000/en
或http://localhost:3000/de
应该显示一些东西,并且到第二页和返回的链接也应该生效,但是导航到http://localhost:3000
将返回404错误。
为了解决这个问题,我们将创建一个Next.js中间件并重构一些代码:
创建app/i18n/settings.js
文件:
export const fallbackLng = 'en'
export const languages = [fallbackLng, 'de']
修改app/[lng]/layout.js
文件:
import { dir } from 'i18next'
import { languages } from '../i18n/settings'
export async function generateStaticParams() {
return languages.map((lng) => ({ lng }))
}
export default function RootLayout({
children,
params: {
lng
}
}) {
return (
<html lang={lng} dir={dir(lng)}>
<head />
<body>
{children}
</body>
</html>
)
}
创建middleware.js
文件:
npm install accept-language
import {
NextResponse } from 'next/server'
import acceptLanguage from 'accept-language'
import {
fallbackLng, languages } from './app/i18n/settings'
acceptLanguage.languages(languages)
export const config = {
// matcher: '/:lng*'
matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)']
}
const cookieName = 'i18next'
export function middleware(req) {
let lng
if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName).value)
if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'))
if (!lng) lng = fallbackLng
// Redirect if lng in path is not supported
if (
!languages.some(loc => req.nextUrl.pathname.startsWith(`/${
loc}`)) &&
!req.nextUrl.pathname.startsWith('/_next')
) {
return NextResponse.redirect(new URL(`