next.js app目录 i18n国际化简单实现

这篇具有很好参考价值的文章主要介绍了next.js app目录 i18n国际化简单实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在用next写一个多语言的项目,找了好久没找到简单实现的教程,实践起来感觉都比较复杂,最后终于是在官方文档找到了,结合网上找到的代码demo,终于实现了,在这里简单总结一下。

此教程适用于比较简单的项目实现,如果你是刚入门next,并且不想用太复杂的方式去实现一个多语言项目,那么这个教程就挺适合你的。

此教程适用于app目录的next项目。

先贴一下参阅的连接:

官方教程: next i18n 文档

可参阅的代码demo

实现思路

结合文件结构解说一下大致逻辑:

next.js app目录 i18n国际化简单实现

  • i18n-config.ts只是一个全局管理多语言简写的枚举文件,其他文件可以引用这个文件,这样就不会出现不同文件对不上的情况。
  • middleware.ts做了一层拦截,在用户访问localhost:3000的时候能通过请求头判断用户常用的语言,配合app目录多出来的[lang]目录,从而实现跳转到localhost:3000/zh这样。
  • dictionaries文件夹下放各语言的json字段,通过字段的引用使页面呈现不同的语种。
    事实上每个页面的layout.tsxpage.tsx都会将语言作为参数传入,在对应的文件里,再调用get-dictionaries.ts文件里的方法就能读取到对应的json文件里的内容了。

大致思路是这样,下面贴对应的代码。

/i18n-config.ts

export const i18n = {
    defaultLocale: "en",
    // locales: ["en", "zh", "es", "hu", "pl"],
    locales: ["en", "zh"],
} as const;

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

/middleware.ts,需要先安装两个依赖,这两个依赖用于判断用户常用的语言:

npm install @formatjs/intl-localematcher
npm install negotiator

然后才是/middleware.ts的代码:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

import { i18n } from "./i18n-config";

import { match as matchLocale } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";

function getLocale(request: NextRequest): string | undefined {
  // Negotiator expects plain object so we need to transform headers
  const negotiatorHeaders: Record<string, string> = {};
  request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));

  // @ts-ignore locales are readonly
  const locales: string[] = i18n.locales;

  // Use negotiator and intl-localematcher to get best locale
  let languages = new Negotiator({ headers: negotiatorHeaders }).languages(
    locales,
  );

  const locale = matchLocale(languages, locales, i18n.defaultLocale);

  return locale;
}

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  // // `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually.
  // // If you have one
  // if (
  //   [
  //     '/manifest.json',
  //     '/favicon.ico',
  //     // Your other files in `public`
  //   ].includes(pathname)
  // )
  //   return

  // Check if there is any supported locale in the pathname
  const pathnameIsMissingLocale = i18n.locales.every(
    (locale) =>
      !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`,
  );

  // Redirect if there is no locale
  if (pathnameIsMissingLocale) {
    const locale = getLocale(request);

    // e.g. incoming request is /products
    // The new URL is now /en-US/products
    return NextResponse.redirect(
      new URL(
        `/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
        request.url,
      ),
    );
  }
}

export const config = {
  // Matcher ignoring `/_next/` and `/api/`
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};

/dictionaries下的因项目而异,可以看个参考:
next.js app目录 i18n国际化简单实现

文件以语言简写命名,/i18n-config.ts里的locales有什么语言,这里就有多少个对应的文件就行了。

/get-dictionaries.ts

import "server-only";
import type { Locale } from "./i18n-config";

// We enumerate all dictionaries here for better linting and typescript support
// We also get the default import for cleaner types
const dictionaries = {
  en: () => import("./dictionaries/en.json").then((module) => module.default),
  zh: () => import("./dictionaries/zh.json").then((module) => module.default),
};

export const getDictionary = async (locale: Locale) => dictionaries[locale]?.() ?? dictionaries.en();

实际使用可以做个参考:
next.js app目录 i18n国际化简单实现

到这里其实就实现了,但是下面的事情需要注意:

如果你的项目有集成了第三方需要配知道middleware的地方,比如clerk,需要调试一下是否冲突。

如果你不知道clerk是什么,那么下面可以不用看,下面将以clerk为例,描述一下可能遇到的问题和解决方案。

Clerk适配

clerk是一个可以快速登录的第三方库,用这个库可以快速实现用户登录的逻辑,包括Google、GitHub、邮箱等的登录。

clerk允许你配置哪些页面是公开的,哪些页面是需要登录之后才能看的,如果用户没登录,但是却访问了需要登录的页面,就会返回401,跳转到登录页面。

就是这里冲突了,因为我们实现多语言的逻辑是,用户访问localhost:3000的时候判断用户常用的语言,从而实现跳转到localhost:3000/zh这样。

这两者实现都在middleware.ts文件中,上面这种配置会有冲突,这两者只有一个能正常跑通,而我们想要的效果是两者都能跑通,既能自动跳转到登录页面,也能自动跳转到常用语言页面。

技术问题定位:这是因为你重写了middleware方法,导致不会执行Clerk的authMiddleware方法,视觉效果上,就是多语言导致了Clerk不会自动跳转登录。

所以要把上面的middleware方法写到authMiddleware方法里的beforeAuth里去,Clerk官方有说明: Clerk authMiddleware说明

next.js app目录 i18n国际化简单实现

所以现在/middleware.ts文件内的内容变成了:

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { authMiddleware } from "@clerk/nextjs";
import { i18n } from "./i18n-config";
import { match as matchLocale } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";

function getLocale(request: NextRequest): string | undefined {
  // Negotiator expects plain object so we need to transform headers
  const negotiatorHeaders: Record<string, string> = {};
  request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));

  // @ts-ignore locales are readonly
  const locales: string[] = i18n.locales;

  // Use negotiator and intl-localematcher to get best locale
  let languages = new Negotiator({ headers: negotiatorHeaders }).languages(
    locales,
  );

  const locale = matchLocale(languages, locales, i18n.defaultLocale);

  return locale;
}

export const config = {
  // Matcher ignoring `/_next/` and `/api/`
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
  // matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};

export default authMiddleware({
  publicRoutes: ['/anyone-can-visit-this-route'],
  ignoredRoutes: ['/no-auth-in-this-route'],
  beforeAuth: (request) => {
    const pathname = request.nextUrl.pathname;

    // // `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually.
    // // If you have one
    if (
      [
        '/manifest.json',
        '/favicon.ico',
        '/serviceWorker.js',
        '/en/sign-in'
        // Your other files in `public`
      ].includes(pathname)
    )
      return

    // Check if there is any supported locale in the pathname
    const pathnameIsMissingLocale = i18n.locales.every(
      (locale) =>
        !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`,
    );

    // Redirect if there is no locale
    if (pathnameIsMissingLocale) {
      const locale = getLocale(request);

      // e.g. incoming request is /products
      // The new URL is now /en-US/products
      return NextResponse.redirect(
        new URL(
          `/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
          request.url,
        ),
      );
    }
  }
});

这样就OK了,大功告成。文章来源地址https://www.toymoban.com/news/detail-855083.html

到了这里,关于next.js app目录 i18n国际化简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot - SpringBoot整合i18n实现消息国际化

    在我们开发WEB项目的时候,项目可能涉及到在国外部署或者应用,也有可能会有国外的用户对项目进行访问,那么在这种项目中, 为客户展现的页面或者操作的信息就需要根据客户系统的环境来使用不同的语言,这就是我们所说的项目国际化。 1. MessageSource源码 Spring中定义了

    2024年02月03日
    浏览(51)
  • spring6-国际化:i18n | 数据校验:Validation

    1.1、i18n概述 国际化也称作i18n,其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数。由于软件发行可能面向多个国家,对于不同国家的用户,软件显示不同语言的过程就是国际化。通常来讲,软件中的国际化是通过配置文件来实现的,假设要支撑两种语言,

    2024年02月08日
    浏览(49)
  • 微信小程序-切换语言(国际化i18n)的方法封装

    最近做的一个小程序的项目, 涉及到了 多语言的切换 , 就想到了之前vue用的多语言插件i18n, 就尝试着在微信开放社区搜了一下, 没有具体的实现, 但是提供了大致的实现思路, 如下: 又结合了很多大佬的分享经验, 试着去封装了一个微信的i18n方法 首先, 我们需要明确一下需要实

    2024年02月05日
    浏览(47)
  • 如何在Vue3中配置国际化语言i18n

    1. 安装 vue-i18n 2. 创建一个i8n的配置文件 如:i18nConfig.js 3. 新建语言文件 zh-CN.js 和 en-US.js zh-CN.js 文件 en-US.js 文件 CONFIG.js 文件 4. 在 main.js 里面全局配置 通过上面四步即可配置完毕 下面说一下如何使用,分三种情况 在 .vue 组件中的 template 使用 在 .vue 组件中的 script 中使用 在

    2024年02月09日
    浏览(56)
  • SpringBoot 国际化(i18n) 支持中文键(KEY)的解决方法

    前言: 项目中要解决“中英文”切换的问题,想法是输入key例如“你好”,然后去国际化文件找对应的中文key,然后进行输出,如果没有定义这个key,则输出“你好”。但是中文key在properties文件中会已unicode编码输出,使用中文key时获取不到对应的value。 解决方法: 重构$.

    2024年02月16日
    浏览(44)
  • 用i18n 实现vue2+element UI的国际化多语言切换详细步骤及代码

    这个地方要注意自己的vue版本和i1n8的匹配程度,如果是vue2点几,记得安装i18n的@8版本,不然会自动安装的最新版本,后面会报错哦,查询了下资料,好像最新版本是适配的vue3。 在src下面新建i18n文件夹,然后在里面新建index.js,里面的内容如下 新建i18n文件夹里面新建config文

    2024年02月14日
    浏览(46)
  • Vue3中,国际化插件vue-i18n使用记录,配合VSCode自动化翻译插件i18n Ally

    说明文档: vue-i18n 版本说明: vue: 3.0.0+ vue-i18n: 9.x版 src 目录下新建目录 lang ,存放 i18n 的配置。 新建目录名称: lang (语言)、 locales (语系设定)、 i18n ,这些名称都可被VSCode图标插件( vscode-icons )检测到并美化。 lang 目录下,新建 index.js 文件,引入 vue-i18n 。 语言的配置信

    2024年02月12日
    浏览(42)
  • 用i18next使你的应用国际化-React

    ref: https://www.i18next.com/ i18next是一个用JavaScript编写的国际化框架。 i18next为您提供了一个完整的解决方案,本地化您的产品从web端到移动端和桌面端。 在react项目中安 i18next 依赖: i18next react-i18next i18next-browser-languagedetector,用于检测用户语言 创建 i18n.js 文件: 在 index.js 中导

    2024年02月15日
    浏览(33)
  • React18.x + i18next + antd 国际化正确使用姿势及避坑指南

    如果你使用这个教程还不能够解决你的问题的话,直接私信我,免费一对一给你解决。 具体的创建方法大家参考vite官方文档,大概的操作如下,如果需要更详细的,大家去自行搜索即可 因为我这里使用的是ts版本,所以,你自己看着办吧。 其中 i18next-browser-languagedetector i1

    2024年02月05日
    浏览(61)
  • Next实现 i18n 传递 locales 给 getStaticPaths

    在 Next.js 中实现国际化( i18n )时,可以通过配置 next.config.js 文件来传递 locales 给 getStaticPaths 函数。下面是一个示例代码,演示如何在 next.config.js 中配置 locales ,并在 getStaticPaths 中获取并使用这些 locales : 1、配置 next.config.js 文件: 2、在页面组件中使用 getStaticPaths : 在

    2024年04月24日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包