nextjs15使用next-intl实现国际化多语言

在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() {
  // 读取 cookie
  const locale = (await cookies()).get(COOKIE_NAME)?.value
  if (locale) return locale
  // 读取请求头 accept-language
  const 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}>
      <body
        className={`${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官网进行查询,这里不做赘述。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

住在河边的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值