使用 next-intl 在 Next.js 应用中开启国际化

4 个月前(已编辑)
/ , , ,
18
这篇文章上次修改于 4 个月前,可能部分内容已经不适用,如有疑问可询问作者。

目前 Next.js 推荐的路由方式是 App Router,所以本文不再介绍 Pages Router,感兴趣的请阅读官方文档 next-intl Pages Router

next-intl 为 App Router 提供了两种配置选项:

  • 带有路由:使用路由片段 locale 或者域名,例如 /en/abouten.example.com/about
  • 不带路由:基于用户设置。

由于第一种方式在后续的路由跳转必须携带 locale 参数,比较不方便,因此本文选择介绍第二种不带路由的方式。

一、准备工作

使用 pnpm 创建项目

pnpm create next-app
项目选项

项目选项

运行项目,本文在此页面上进行配置

初始页面

初始页面

二、安装和配置

1. 安装 next-intl

pnpm add next-intl

2. 在根目录创建 messages 文件夹,并在此文件夹下创建 zh.jsonen.json

Home 为命名空间,后面需要用到,可以在 json 中声明多个,表示不同场景。

  • en.json
  • zh.json

3. 配置 next.config.mjs

4. 创建 i18n/config.js,保存配置

5. 创建 i18n/service.js,获取、设置区域

next-intl 在 cookie 中设置了 NEXT_LOCALE 字段,用来保存区域配置。

获取区域配置优先级如下:

  • 从 cookies 中读取 NEXT_LOCALE,有值则直接返回
  • 从 headers 中读取解析 accept-language,并判断是否在系统支持的语言中

6. 创建 i18n/request.js,返回国际化配置

7. 修改 app/layout.js

使用 getLocalegetMessages 可以获取 i18n/request.js 返回的语言配置,将 locale 设置到 html 的 lang 属性,将 messages 传递给 NextIntlClientProvider

三、使用

同步服务端组件与客户端组件

文本数量较少的情况下,建议将文本通过 props 传递给客户端组件。在客户端组件中调用 useTranslations 会将 next-intl 代码打包进客户端 js 中,导致 bundle 体积增大,影响加载性能。

  1. 调用 useTranslations,传入命名空间 js const t = useTranslations('Home')
  2. 在 jsx 中调用 js <p>{t('docs')}</p>

异步服务端组件

关于其他更多用法,例如插值语法、富文本、HTML 标记、数组、数字格式、日期时间格式等,请参考文档 https://next-intl.dev/docs/usage/messages

四、语言切换

创建 components/LocaleSwitcher.js 组件,并在 app/page.js 中引入

由于我们之前在 Server Action setUserLocale 中通过 cookies 设置了语言区域,Next.js 会将新的 cookie 和 DOM 返回给客户端。

RSC Payload

RSC Payload

效果如下:

切换语言效果图

切换语言效果图

五、最后

在线预览地址:https://next-intl-study.vercel.app/

完整代码仓库:https://github.com/zb81/next-intl-study

  • Loading...
  • Loading...
  • Loading...
  • Loading...