当前位置:首页 > 新闻动态 > 网站文章

为你的Next.js静态网站国际化(使用App Router)

来源: 浏览:141 时间:2023-08-24

Next.js提供的一个令人惊叹的功能是静态导出(Static Export)。启用静态导出后,Next.js会基于你的整个React应用程序生成静态的HTML/CSS/JS文件。
关注我带你了解科技领域最新的技术与产品。
这种方法有很多好处,尤其是对于性能和SEO方面。这也意味着你的应用程序可以部署和托管在任何可以提供HTML/CSS/JS静态资源的Web服务器上,比如一个简单而实惠的nginx配置。

在使用静态导出时,我遇到了一个问题,即如何进行国际化(i18n)并将我的应用程序内容翻译成多种语言。我发现在线资源关于这个主题的文章非常少,特别是在使用Next.js 13版本引入的App Router时。

让我们一起创建一个基本的国际化应用程序,演示如何实现这一点!
你可以在这里找到工作演示项目:
https://github.com/RockyStrongo/next-i18n-static/

第一步:初始化项目
运行以下命令创建一个新的Next.js项目,并按照提示进行操作。
npx create-next-app@latest
我们将在这个示例中使用TypeScript、Tailwind和App Router。

现在,我们可以开始用我们应用程序的内容替换默认项目。

我们的要求如下:

一个带有两个链接(Home和About)的导航栏
一个包含文本“Hello World”的主页
一个包含文本“这是一个完全翻译的静态网站”的关于页面
所有文本都应该用英语和法语翻译
导航栏中应该有一个语言切换器
1.1 创建一个导航栏组件:
创建一个components文件夹和一个Header组件
// components/Header.tsx

import Link from "next/link";

export default function Header() {
return (




)
}
1.2 在主页上更新为'Hello World'
// app/page.tsx

export default function Home() {
return (

Hello World!

)
}
1.3 在应用程序布局中包含导航栏:
// app/layout.tsx

import './globals.css'
import type { Metadata } from 'next'
import Header from '@/components/Header'

export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (




{children}



)
}1.4 创建关于页面:

// app/about/page.tsx



export default function AboutPage() {


return (



这个应用是一个完全翻译的静态网站



)


}


1.5 更新 next.config.js 文件以启用静态导出


通过这个配置,在运行 npm run build 时,Next.js 将在 out 文件夹中生成静态的 HTML/CSS/JS 文件。


/** @type {import('next').NextConfig} */


const nextConfig = {


output: 'export',


}



module.exports = nextConfig


到目前为止,我们已经实现了应用的基本功能,但是还没有加入任何翻译或国际化逻辑。所有的文本目前都是硬编码的。



步骤2:国际化项目


我们将使用 next-intl 库,该库在 Next.js 社区中得到广泛维护和使用。它在 Next.js 的官方文档中的国际化部分中有提到。


npm install next-intl


2.1 创建翻译文件


文件 messages/en.json


{


"Homepage": {


"helloWorld": "Hello World !"


},


"AboutPage": {


"aboutText": "This is a fully translated static website"


},


"Header": {


"home": "Home",


"about": "About"


}


}


文件 messages/fr.json


{


"HomePage": {


"helloWorld": "Bonjour tout le monde !"


},


"AboutPage": {


"aboutText": "Ceci est un site statique complètement traduit."


},


"Header": {


"home": "Accueil",


"about": "A propos"


}


}


2.2 更新文件结构


├── messages


│ ├── en.json


│ └── fr.json


└── app


└── [locale]


├── layout.tsx


└── page.tsx


└── layout.tsx


└── page.tsx


└── not-found.tsx


首先创建 [locale] 文件夹,并将现有的 page.tsx 文件、layout.tsx 文件和 about 文件夹移动到其中。不要忘记更新导入语句。



创建一个新的 /app/not-found.tsx 文件,这将是我们在用户输入错误的 URL 时显示的错误页面。


// app/not-found.tsx



export default function NotFound() {


return (



自定义404页面



)


}


创建一个新的 /app/layout.tsx 文件:


// app/layout.tsx



import {ReactNode} from 'react';



type Props = {


children: ReactNode;


};



// 因为根目录上有一个 not-found.tsx 页面,所以需要一个布局文件,


// 即使它只是简单地传递子元素。


export default function RootLayout({children}: Props) {


return children;


}



创建一个新的 /app/page.tsx 文件:


在这个页面中,我们将用户重定向到默认语言,对于我们来说是英语。



注意:使用静态导出,不能使用没有前缀的默认语言。我们必须将传入的请求重定向到默认语言。如文档中所述。


// app/page.tsx



import {redirect} from 'next/navigation';



export default function RootPage() {


redirect('/en');


}



2.3 更新 app/[locale]/layout.tsx


// app/[locale]/layout.tsx



import '../globals.css'


import type { Metadata } from 'next'


import Header from '@/components/Header'


import { ReactNode } from 'react'


import { notFound } from 'next/navigation'


import { NextIntlClientProvider } from 'next-intl'



type Props = {


children: ReactNode


params: { locale: string }


}



export const metadata: Metadata = {


title: 'Create Next App',


description: 'Generated by create next app',


}



// 获取翻译的函数


async function getMessages(locale: string) {


try {


return (await import(../../messages/${locale}.json)).default


} catch (error) {


notFound()


}


}



// 生成所有语言的路由的函数


export async function generateStaticParams() {


return ['en', 'fr'].map((locale) => ({ locale }))


}



export default async function RootLayout({


children,


params: { locale },


}: Props) {


const messages = await getMessages(locale)



return (







{children}






)


}


我们在这里做了以下工作:



添加了一个名为getMessages的函数,用于获取翻译信息。


添加了一个名为generateStaticParams的函数,用于为所有的语言环境生成静态路由。


添加了上下文提供者NextIntlClientProvider,使得我们的翻译能够在应用的所有页面中使用。


更新了页面和组件,以使用翻译信息。


具体代码如下所示:



tsx


// app/page.tsx



'use client'


import { useTranslations } from 'next-intl'



export default function HomePage() {


const t = useTranslations('HomePage')



return (



{t('helloWorld')}



)


}


tsx


// app/[locale]/about/page.tsx



'use client'


import { useTranslations } from 'next-intl'



export default function AboutPage() {


const t = useTranslations('AboutPage')



return (



{t('aboutText')}



)


}


tsx


// components/Header.tsx



'use client'


import Link from "next/link";


import { useTranslations } from 'next-intl'



export default function Header() {


const t= useTranslations('Header')


return (





)


}


更新链接以考虑语言环境前缀,使用'next-intl/link'组件替代Next.js提供的Link组件。


tsx


// components/Header.tsx



'use client'


import Link from 'next-intl/link';


import { useTranslations } from 'next-intl'



export default function Header() {


const t= useTranslations('Header')


return (





)


}


如果你运行应用程序,你会注意到你会立即从 http://localhost/3000 被重定向到 http://localhost/3000/en ,头部的链接已经考虑到了'en'前缀。如果你将它从'en'改为'fr',你会看到你的网站被翻译成法语。



现在我们几乎完成了!我们需求列表中只剩下语言切换器!



第3步 - 添加一个语言切换器



创建必要的翻译文件。


messages/en.json:



json


"LocaleSwitcher": {


"locale": "{locale, select, fr {French} en {English} other {Unknown}}"


}


messages/fr.json:



json


"LocaleSwitcher": {


"locale": "{locale, select, fr {français} en {anglais} other {inconnu}}"


}


创建语言切换器组件。


tsx


// components/LocaleSwitcher.tsx



'use client'


import { useLocale, useTranslations } from 'next-intl';


import { usePathname, useRouter } from 'next-intl/client';



export default function LocaleSwitcher() {


const t = useTranslations('LocaleSwitcher')


const locale = useLocale();


const router = useRouter();


const pathname = usePathname();



const onLocaleChange = (e: React.ChangeEvent) => {


const newLocale = e.target.value;


router.replace(pathname, { locale: newLocale });


}



return (



defaultValue={locale}


onChange={onLocaleChange}


>


{['en', 'fr'].map((lang) => (



{t('locale', { locale: lang })}



))}



)


}


最后一步,在Header组件中添加语言切换器,工作完成!我们的静态应用程序已经国际化了



要构建应用程序,请运行:



npm run build


静态导出将生成在out文件夹中。



通过运行以下命令测试生成的输出:



npx serve@latest out


通过Next.js的特性、App Router和next-intl库的组合,您可以创建出高性能、对SEO友好且多语言友好的Web应用程序,触达全球用户。拥抱国际化,将您的Next.js项目推向新的高度!





地址 · ADDRESS

地址:建邺区新城科技园嘉陵江东街18号2层

邮箱:309474043@qq.Com

点击查看更多案例

联系 · CALL TEL

400-8793-956

售后专线:025-65016872

业务QQ:309474043    售后QQ:1850555641

©南京安优网络科技有限公司 版权所有   苏ICP备12071769号-4  网站地图