在nextjs15当中使用next-intl可以轻松实现国际化,本文将着重阐述,如何在nextjs15使用next-intl。
一、创建项目安装依赖
1、创建nextjs项目
pnpm dlx create-next-app my-app
2、安装next-intl
pnpm add next-intl
二、创建组件文件
1、项目结构
2、配置 next.config.mjs
import createNextIntlPlugin from 'next-intl/plugin';const withNextIntl = createNextIntlPlugin();/** @type {import('next').NextConfig} */
const nextConfig = {};export default withNextIntl(nextConfig);
2、创建多语言
在lang文件夹下创建en.json:
{"HomePage": {"title": "Hello world!"}
}
同理创建zh.json;
3、配置文件config.ts
export type Locale = (typeof locales)[number];export const locales = ['zh', 'en'] as const;
export const defaultLocale: Locale = 'zh';
4、创建 i18n/request.js
,返回国际化配置
import { getRequestConfig } from 'next-intl/server';import { getLocale } from '@/i18n';export default getRequestConfig(async () => {const locale = await getLocale();console.log('🚀 ~ getRequestConfig ~ locale:', locale);return {locale,messages: (await import(`./lang/${locale}.json`)).default};
});
5、创建 i18n/index.js
,获取、设置语言环境
next-intl 在 cookie 中设置了 NEXT_LOCALE
字段,用来保存区域配置。
获取区域配置优先级如下:
- 从 cookies 中读取
NEXT_LOCALE
,有值则直接返回 - 从 headers 中读取解析
accept-language
,并判断是否在系统支持的语言中
'use server';import { cookies, headers } from 'next/headers';import { defaultLocale, Locale } from '@/i18n/config';// In this example the locale is read from a cookie. You could alternatively
// also read it from a database, backend service, or any other source.
const COOKIE_NAME = 'NEXT_LOCALE';
// 这是从请求头里面获取语言环境的方法,本文采用的不是从请求当中获取,这个函数只是个展示,告诉你如何从请求当中获取语言环境
export async function getUserLocale() {// 读取 cookieconst locale = (await cookies()).get(COOKIE_NAME)?.valueif (locale) return locale// 读取请求头 accept-languageconst acceptLanguage = (await headers()).get('accept-language')// 解析请求头const parsedLocale = acceptLanguage?.split(',')[0].split('-')[0]// 如果不在系统支持的语言列表,使用默认语言return locales.includes(parsedLocale) ? parsedLocale : defaultLocale;
}// 获取当前语言环境
export async function getLocale() {return (await cookies()).get(COOKIE_NAME)?.value || defaultLocale;
}
// 设置语言环境
export async function setLocale(locale: Locale) {(await cookies()).set(COOKIE_NAME, locale);
}
6. 修改 app/layout.tsx
import { Geist, Geist_Mono } from "next/font/google";
import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getMessages } from 'next-intl/server';import "./globals.css";const geistSans = Geist({variable: "--font-geist-sans",subsets: ["latin"],
});const geistMono = Geist_Mono({variable: "--font-geist-mono",subsets: ["latin"],
});export const metadata = {title: "Create Next App",description: "Generated by create next app",
};export default async function RootLayout({ children }) {const locale = await getLocale()const messages = await getMessages()return (<html lang={locale}><bodyclassName={`${geistSans.variable} ${geistMono.variable} antialiased`}><NextIntlClientProvider messages={messages}>{children}</NextIntlClientProvider></body></html>);
}
8、调用 useTranslations
传入命名空间
import Image from 'next/image';
import Typography from '@mui/material/Typography';
import { useTranslations } from 'next-intl';import LangSwitch from '@/components/LangSwitch';export default function Home() {const t = useTranslations('HomePage');return (<div className="grid min-h-screen grid-rows-[20px_1fr_20px] items-center justify-items-center gap-16 p-8 pb-20 font-[family-name:var(--font-geist-sans)] sm:p-20"><LangSwitch></LangSwitch><Typography variant="h1" color="initial">{t('title')}</Typography></div>);
}
三、切换语言
在compoents下创建一个LangSwitch.tsx组件
'use client';import { Button } from '@mui/material';
import { useLocale } from 'next-intl';import { setLocale } from '@/i18n';
import { locales, type Locale } from '@/i18n/config';export default function LangSwitch() {const [ZH, EN] = locales;const locale = useLocale();// 切换语言function onChangeLang(value: Locale) {const locale = value as Locale;setLocale(locale);}return (<Button onClick={() => onChangeLang(locale === ZH ? EN : ZH)} variant="contained">{locale === ZH ? '中' : 'EN'}<span className="sr-only">Toggle Lang</span></Button>);
}
以上是next-intl在不使用 i18n 路由的 App Router 设置,如果你想使用i18n 路由设置 App Router,那就请去next-intl官网进行查询,这里不做赘述。