You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{defineRouting}from'next-intl/routing';import{createNavigation}from'next-intl/navigation';exportconstrouting=defineRouting({// A list of all locales that are supportedlocales: ['en','zh'],// Used when no locale matchesdefaultLocale: 'en'});// Lightweight wrappers around Next.js' navigation APIs// that will consider the routing configurationexportconst{Link, redirect, usePathname, useRouter}=createNavigation(routing);
再然后,创建中间件 src/middleware.ts:
importcreateMiddlewarefrom'next-intl/middleware';import{routing}from'./i18n/routing';exportdefaultcreateMiddleware(routing);exportconstconfig={// Match only internationalized pathnamesmatcher: ['/','/(zh|en)/:path*']};
import{getRequestConfig}from'next-intl/server';import{routing}from'./routing';exportdefaultgetRequestConfig(async({requestLocale})=>{// This typically corresponds to the `[locale]` segmentletlocale=awaitrequestLocale;// Ensure that a valid locale is usedif(!locale||!routing.locales.includes(localeasany)){locale=routing.defaultLocale;}return{
locale,messages: (awaitimport(`../../messages/${locale}.json`)).default};});
接下来,创建 src/app/[locale]/layout.tsx布局组件:
import{routing}from'@/i18n/routing';import{NextIntlClientProvider}from'next-intl';import{getMessages}from'next-intl/server';importlocalFontfrom"next/font/local";import{notFound}from'next/navigation';import"../globals.css";importSiteHeaderfrom'../view/SiteHeader';constgeistSans=localFont({src: "../fonts/GeistVF.woff",variable: "--font-geist-sans",weight: "100 900",});constgeistMono=localFont({src: "../fonts/GeistMonoVF.woff",variable: "--font-geist-mono",weight: "100 900",});exportdefaultasyncfunctionLocaleLayout({
children,
params
}: {children: React.ReactNode;params: Promise<{locale: string}>;}){const{ locale }=awaitparams;// Ensure that the incoming `locale` is validif(!routing.locales.includes(localeasany)){notFound();}// Providing all messages to the client// side is the easiest way to get startedconstmessages=awaitgetMessages();return(<htmllang={locale}><bodyclassName={`${geistSans.variable} ${geistMono.variable} antialiased`}><NextIntlClientProvidermessages={messages}><SiteHeader/>{children}</NextIntlClientProvider></body></html>);}
import{redirect}from'next/navigation';// This page only renders when the app is built statically (output: 'export')exportdefaultfunctionRootPage(){redirect('/en');}
importenfrom"./messages/en.json";typeMessages=typeofen;declare global {// Use type safe message keys with `next-intl`typeIntlMessages=Messages;}
后续使用t()的时候编辑器就能提供候选补全了。
编写切换语言功能
首先,我们创建一个 SiteHeader组件:
import{useLocale,useTranslations}from"next-intl";importLinkfrom"next/link";import{PiGoogleChromeLogoDuotone}from"react-icons/pi";import{routing}from'../../../i18n/routing';importLanguageSwitchfrom"./LanguageSwitch";exportdefaultfunctionSiteHeader(){constt=useTranslations('HomePage');constlocale=useLocale();return(<divclassName="mx-auto"><divclassName='flex items-center gap-4 2xl:w-[1360px] p-4'>{/* add website header here */}<Linkhref={'/'}locale={locale}className="flex items-center gap-1"><PiGoogleChromeLogoDuotoneclassName=' text-xl 2xl:text-3xl text-blue-600'/><h1className="mr-auto">{t('title')}</h1></Link><divclassName="mr-auto">{/* add other nav */}</div>{/* select to switch language */}<LanguageSwitchlocales={routing.localesasunknownasstring[]}/></div></div>)}
description: 我需要为我的 nextjs 项目添加 i18n 功能,从而更好地进行推广和服务。于是我尝试使用next-intl库来完成这个功能,本文记录了我接入这个库的整个过程。
cover: https://de4965e.webp.li/blog-images/2024/10/bed7636024f5a408164690e71b83e63f.jpg
我需要为我的 nextjs 项目添加 i18n 功能,从而更好地进行推广和服务。于是我尝试使用
next-intl
库来完成这个功能,本文记录了我接入这个库的整个过程。版本信息
起步
首先安装依赖
next-intl
,在根目录下创建对应的目录:其次,创建翻译文件
messages/en.json
和其他语言的翻译文件:再次,配置
next.config.ts
文件:然后,配置
i18n
的路由文件src/i18n/routing.ts
:再然后,创建中间件
src/middleware.ts
:由
next-intl
提供的创建中间件的函数配合多语言的路由,即可创建一个中间件。与此同时,导出的config
对象限定了这个中间件的匹配范围。然后,我们还需要创建一个
src/i18n/request.ts
文件来提供一个函数来获取语言和对应语言的翻译文件。接下来,创建
src/app/[locale]/layout.tsx
布局组件:这里我们提供了一个
NextIntlClientProvider
组件,将翻译信息传递了下去。其中
<SiteHeader>
单独拆成一个组件,是因为useTranslations
钩子必须在非异步组件内使用。这里我将默认的
src/app/layout.tsx
删掉了,然后在src/app/page.tsx
中做了重定向:访问根目录时自动重定向到
/en
路由下,并且经过中间件的处理。编写页面
现在来编写
src/app/[locale]/page.tsx
:此时,我们进入
/en
和/zh
两个路由下的页面如下:中文:
英文:
静态渲染
目前版本的
next-intl
仅在服务器组件中使用useTranslations
来实现多语言,未来将会消除这个限制,让客户端组件也能自由切换多语言。在静态渲染时,
next-intl
提供了一个临时的 api 来启用多语言功能。由于我们使用了
[locale]
动态路由,因此我们需要通过generateStaticParams
函数,将所有可能的语言路由传给nextjs
,以便于在构建时渲染。在
app/[locale]/layout.tsx
组件中添加代码:显然
routing
来源于我们的i18n/routing
,声明了我们支持的哪些语言。此外,我们还需要在布局组件中显式地声明启用静态渲染多语言:
setRequestLocale
函数让nextjs
知悉当前页面的语言。这听起来有点模糊,目前
nextjs
并没有提供任何 API 来从路由参数中读取类似 locale 这样的内容。而语言是next-intl
的关键信息,这部分功能只能通过next-intl
来增强。关键点:
举个例子:
在 metadata 中使用多语言
在完成了上述的配置后,我们可以在
generateMetadata
函数的参数中得到locale
,在此函数内部使用getTranslations
函数获取翻译功能的t
函数。如此一来便可以在不同语言录音下的页面添加多语言的 metadata 信息了。
启用 TypeScript 支持
next-intl
仅需要我们在根目录创建一个global.d.ts
文件,声明类型即可:后续使用
t()
的时候编辑器就能提供候选补全了。编写切换语言功能
首先,我们创建一个
SiteHeader
组件:以及一个核心切换的客户端组件:
最后的效果如下,在鼠标移动到上面时通过
tailwindcss
控制切换标签的显示和隐藏,语言数组从配置文件中导出,再使用Link
组件配合locale
属性就能在点击的时候切换到不同的语言路由下了:最后
好了,今天分享就到这里。
我预计需要一些时间完成这个网站,我打算把自己开发的所有浏览器插件全部放到这上面,再加上用户体系控制,分享一些我开发的免费的简单插件和部分预计可以收费的核心插件。
为了记录这个过程,我会把遇到的问题和解决方案都发布在公众号上,欢迎阅读和分享。
再会。
The text was updated successfully, but these errors were encountered: