Next.js 实战 (四):i18n 国际化的最优方案实践

简介: 这篇文章介绍了Next.js国际化方案,作者对比了网上常见的方案并提出了自己的需求:不破坏应用程序的目录结构和路由。文章推荐使用next-intl库来实现国际化,并提供了详细的安装步骤和代码示例。作者实现了国际化切换时不改变路由,并把当前语言的key存储到浏览器cookie中,使得刷新浏览器后语言不会失效。最后,文章总结了这种国际化方案的优势,并提供Github仓库链接供读者参考。

前言

有关 Next.js 国际化的方案网上很多,而且各部相同,但大部分的方案都是在 /app 目录下添加动态路由 [lang] 这样的形式,这不是我想要的效果。

我希望国际化的实现不能破坏应用程序的目录结构和路由,在经过一段时间摸索后,发现 next-intl
有提供现成的方案:
y0cbqfwghovy5x67t2vq8uzezsic9xt9.png

更多详细文档:next-intl

如果官方文档打不开的伙伴,可以到 Github 上克隆代码,本地运行根目录的 docs 文件夹

具体步骤

1、安装依赖

pnpm add next-intl

2、根目录新建 messages 文件夹,并写入对应的国际化文件:

// en.json
{
   
  "Route":{
   
    "about":"About",
    "dashboard":"Dashboard",
    "system-manage":"System Manage",
    "internationalization":"Internationalization"
  }
}

// zh.json
{
   
  "Route":{
   
    "about":"关于",
    "dashboard":"仪表盘",
    "system-manage":"系统管理",
    "internationalization":"国际化"
  }
}

3、根目录的 next.config.ts 文件设置插件:

import type {
    NextConfig } from "next";
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin();

const nextConfig: NextConfig = {
   };

export default withNextIntl(nextConfig);

4、新建 src/i18n/config.ts 文件,写入配置:

export type Locale = (typeof locales)[number];

export const locales = ['zh', 'en'] as const;
export const defaultLocale: Locale = 'zh';

5、新建 src/i18n/request.ts 文件,创建一个请求范围的配置对象:

import {
    getRequestConfig } from 'next-intl/server';

import {
    getLocale } from '@/i18n';

export default getRequestConfig(async () => {
   
  const locale = await getLocale();

  return {
   
    locale,
    messages: (await import(`../../messages/${
     locale}.json`)).default,
  };
});

6、新建 src/i18n/index.ts 文件,用于服务端获取和设置语言

'use server';

import {
    cookies } 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 getLocale() {
   
  return (await cookies()).get(COOKIE_NAME)?.value || defaultLocale;
}

export async function setLocale(locale: Locale) {
   
  (await cookies()).set(COOKIE_NAME, locale);
}

7、app/layout.tsx 文件配置 NextIntlClientProvider

import {
   NextIntlClientProvider} from 'next-intl';
import {
   getLocale, getMessages} from 'next-intl/server';

export default async function RootLayout({
   
  children
}: {
   
  children: React.ReactNode;
}) {
   
  const locale = await getLocale();

  // Providing all messages to the client
  // side is the easiest way to get started
  const messages = await getMessages();

  return (
    <html lang={
   locale}>
      <body>
        <NextIntlClientProvider messages={
   messages}>
          {
   children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}

8、在文件中使用:

import {
    useTranslations } from 'next-intl';
export default function Dashboard() {
   
  const t = useTranslations('Route');
  return (
    <h1>
      {
   t('dashboard')}
    </h1>
  );
}

切换语言

1、新建 src/components/LangSwitch/index.tsx 文件:

'use client';

import { useLocale } from 'next-intl';

import { Button } from '@/components/ui/button';
import { setLocale } from '@/i18n';
import { type Locale, locales } 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 variant="ghost" size="icon" onClick={() => onChangeLang(locale === ZH ? EN : ZH)}>
      {locale === ZH ? '中' : 'EN'}
      <span className="sr-only">Toggle Lang</span>
    </Button>
  );
}

2、在需要的位置引入组件:

import LangSwitch from '@/components/LangSwitch';

<LangSwitch />

最终效果

etz3e3pi4xobn897h8inafbcsevk2lr3.gif

总结

这样的国际化方案切换语言的时候,路由就不会发生变化,更好地保留应用程序的原样,并且将当前语言的 key 存储到浏览器 cookie 中,刷新浏览器当前语言并不会失效,可以达到我们想要的效果。

Github 仓库next-admin

相关文章
|
2天前
|
存储 安全 API
Next.js 实战 (九):使用 next-auth 完成第三方身份登录验证
这篇文章介绍了next-auth,一个为Next.js设计的身份验证库,支持多种认证方式,如电子邮件和密码、OAuth2.0提供商(如Google、GitHub、Facebook等)以及自定义提供商。文章包含了如何配置Github Provider以及会话管理,并提到了适配器Adapters在next-auth中的作用。最后,文章强调了next-auth的强大功能值得进一步探索。
24 10
|
12天前
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
66 33
|
3天前
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
17 10
|
1月前
|
JavaScript 前端开发 测试技术
在 golang 中执行 javascript 代码的方案详解
本文介绍了在 Golang 中执行 JavaScript 代码的四种方法:使用 `otto` 和 `goja` 嵌入式 JavaScript 引擎、通过 `os/exec` 调用 Node.js 外部进程以及使用 WebView 嵌入浏览器。每种方法都有其适用场景,如嵌入简单脚本、运行复杂 Node.js 脚本或在桌面应用中显示 Web 内容。
103 15
在 golang 中执行 javascript 代码的方案详解
|
19天前
|
前端开发 API 开发者
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
这篇文章介绍了Framer Motion,一个为React设计的动画库,提供了声明式API处理动画和页面转换,适合创建响应式用户界面。文章包括首屏加载动画、路由加载Loading、路由进场和退场动画等主题,并提供了使用Framer Motion和next.js实现这些动画的示例代码。最后,文章总结了这些效果,并邀请读者探讨更好的实现方案。
|
17天前
|
JavaScript 前端开发 API
Next.js 实战 (六):如何实现文件本地上传
这篇文章介绍了在Next.js中如何实现文件上传到本地的方法。文章首先提到Next.js官方文档中没有提供文件上传的实例代码,因此开发者需要自行实现,通常有两种思路:使用Node.js原生上传或使用第三方插件如multer。接着,文章选择了使用Node.js原生上传的方式来讲解实现过程,包括如何通过哈希值命名文件、上传到指定目录以及如何分类文件夹。然后,文章展示了具体的实现步骤,包括编写代码来处理文件上传,并给出了代码示例。最后,文章通过一个效果演示说明了如何通过postman模拟上传文件,并展示了上传后的文件夹结构。
|
1月前
Next.js 实战 (二):搭建 Layouts 基础排版布局
本文介绍了作者在Next.js v15.x版本发布后,对一个旧项目的重构过程。文章详细说明了项目开发规范配置、UI组件库选择(最终选择了Ant-Design)、以及使用Ant Design的Layout组件实现中后台布局的方法。文末展示了布局的初步效果,并提供了GitHub仓库链接供读者参考学习。
Next.js 实战 (二):搭建 Layouts 基础排版布局
|
1月前
Next.js 实战 (三):优雅的实现暗黑主题模式
这篇文章介绍了在Next.js中实现暗黑模式的具体步骤。首先,需要安装next-themes库。然后,在/components/ThemeProvider/index.tsx文件中新增ThemeProvider组件,并在/app/layout.tsx文件中注入该组件。如果想要加入过渡动画,可以修改代码实现主题切换时的动画效果。最后,需要在需要的位置引入ThemeModeButton组件,实现暗黑模式的切换。
|
2月前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
2月前
|
JavaScript 前端开发 API
Vue.js 3:深入探索组合式API的实践与应用
Vue.js 3:深入探索组合式API的实践与应用