nextjs i18n 实现原理

Oct 15, 2024

在 Next.js 中,i18n(国际化)的实现原理基于框架内的多语言支持功能。Next.js 从 10.x 版本开始原生 支持国际化,这使得多语言路由、翻译文件管理、动态内容加载等更加高效。下面详细解释 Next.js 中 i18n 的实现原理及其工作机制:

1. Next.js 的内置 i18n 支持

Next.js 的国际化功能通过配置文件 next.config.js 中的 i18n 字段实现,主要用于指定支持的语言、默认 语言、域名映射等。Next.js 自动处理根据用户语言的路由跳转和静态页面的语言切换。

示例:next.config.js 配置

// next.config.js
module.exports = {
	i18n: {
		locales: ['en', 'fr', 'de'], // 支持的语言列表
		defaultLocale: 'en', // 默认语言
		localeDetection: true, // 是否根据用户偏好检测语言
	},
};

locales:定义支持的语言列表。defaultLocale:设置应用的默认语言,当没有明确指定语言时使用。 localeDetection:自动检测用户的浏览器语言,并根据语言设置跳转。

2. 路由国际化

Next.js 的国际化特性支持自动地为每个语言生成不同的 URL 路径。这意味着每个页面会为每种语言生成独 立的静态页面。例如:

/about 是默认语言(如 en)的页面。/fr/about 是法语版本的页面。/de/about 是德语版本的页面。

实现原理:

路径前缀:Next.js 会根据 i18n 配置自动为不同语言添加前缀(例如 /fr、/de 等),然后将对应的翻译内 容加载到页面中。语言检测:通过浏览器设置或 URL 前缀来检测用户语言,并将用户定向到适合的语言版 本。例如:

访问 /about 时,Next.js 会根据浏览器语言(如果启用 localeDetection),或根据 defaultLocale 跳转 到适合的语言页面。如果启用了多个域名,Next.js 还可以根据域名映射到不同的语言。

3. 翻译文件的管理

Next.js 并不强制使用某种特定的 i18n 库来管理翻译文件,但常用的库是 i18next 或 react-intl。这些库 配合 Next.js 的 i18n 路由功能可以高效地进行国际化管理。

翻译文件结构通常,每个语言都有一个独立的翻译文件,这些文件通常存储在 public 文件夹或项目中的某个 模块文件夹里。

示例:翻译文件

// /locales/en/common.json
{
  "welcome": "Welcome",
  "logout": "Logout"
}

// /locales/fr/common.json
{
  "welcome": "Bienvenue",
  "logout": "Déconnexion"
}

在页面或组件中,你可以根据当前语言选择对应的翻译文本。

4. 语言切换机制

Next.js 的 i18n 通过路由前缀和 URL 实现语言切换。可以在应用中添加语言切换按钮,调用 Next.js 提供 的路由 API 来实现语言跳转。

使用 next/link 实现语言切换:

import Link from 'next/link';
import { useRouter } from 'next/router';

const LanguageSwitcher = () => {
	const router = useRouter();
	const { locale, locales } = router;

	return (
		<div>
			<p>Current locale: {locale}</p>
			<ul>
				{locales.map(loc => (
					<li key={loc}>
						<Link href={router.asPath} locale={loc}>
							{loc}
						</Link>
					</li>
				))}
			</ul>
		</div>
	);
};

export default LanguageSwitcher;

上面的代码中,useRouter 提供了当前语言(locale)、支持的语言列表(locales)等信息,点击不同的链 接即可切换语言。

nextjs 多语言切换路由 getServerSideProps 会重新执行么

在 Next.js 中,当你使用 getServerSideProps 并切换语言时,getServerSideProps 会重新执行。

这是因为 getServerSideProps 是在每次请求时执行的,负责在服务端获取数据。当你切换多语言时,通常 会发生页面路由的变化,这会触发新的请求。因此,getServerSideProps 会在路由变化时重新运行。

多语言切换的过程:

路由变更:使用 Next.js 的 i18n 特性,你可以为不同语言配置不同的路由路径。比如,/en/about 对应英 语页面,/fr/about 对应法语页面。切换语言时,路由也会随之更改。

getServerSideProps 执行:当你从 /en/about 切换到 /fr/about,这是一次新的路由请 求getServerSideProps 会为新的路由(例如 /fr/about)重新执行,获取相关的数据并传递给页面。

服务器端获取语言参数:你可以在 getServerSideProps 中通过 context.locale 获取当前的语言,从而根 据语言加载不同的内容。

例子:

export async function getServerSideProps(context) {
	const { locale } = context; // 获取当前语言
	const res = await fetch(`https://example.com/api/data?lang=${locale}`);
	const data = await res.json();

	return {
		props: {
			data,
		},
	};
}

function Page({ data }) {
	return (
		<div>
			<h1>{data.title}</h1>
			<p>{data.content}</p>
		</div>
	);
}

export default Page;

在这个例子中,每当用户切换语言并更改路由(例如从 /en 切换到 /fr),getServerSideProps 都会根据新 的语言参数重新获取数据并渲染页面。

总结:当你使用 getServerSideProps 时,切换语言通常意味着路由发生了变化,而这会触发 getServerSideProps 的重新执行。你可以在 getServerSideProps 中根据 locale 来动态获取与语言 相关的数据。

5.国际化数据获取 (getStaticProps 和 getServerSideProps)

Next.js 中的静态生成和服务端渲染(如 getStaticProps 和 getServerSideProps)在国际化中起到了关键 作用,帮助加载特定语言的内容。使用这些方法时,Next.js 会为每个语言的页面调用一次数据获取方法。

getStaticProps 示例:

export async function getStaticProps({ locale }) {
	const translations = await import(`../locales/${locale}/common.json`);

	return {
		props: {
			translations,
		},
	};
}

在这个例子中,locale 是当前语言,Next.js 会根据 locale 值自动加载对应的翻译文件。

6.动态加载与按需加载

Next.js 支持按需加载翻译文件,避免所有翻译数据在页面初次加载时被加载,提升性能。例如,当用户切换 到新的语言时,只加载所需的语言文件。

动态加载示例:

import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';

const Page = () => {
	const { locale } = useRouter();
	const [translations, setTranslations] = useState(null);

	useEffect(() => {
		const loadTranslations = async () => {
			const translations = await import(`../locales/${locale}/common.json`);
			setTranslations(translations);
		};

		loadTranslations();
	}, [locale]);

	if (!translations) {
		return <p>Loading...</p>;
	}

	return <div>{translations.welcome}</div>;
};

export default Page;

在这个例子中,每当 locale 变化时,Next.js 会异步加载对应的翻译文件,而不是在初次加载时将所有语言 文件加载到页面中。

7.服务端渲染与静态生成

Next.js 支持在服务端渲染或静态生成时处理多语言内容。例如,在使用 getStaticPaths 时,可以为不同语 言生成多个版本的静态页面。

示例:getStaticPaths 和 getStaticProps

export async function getStaticPaths() {
	return {
		paths: [
			{ params: { slug: 'about' }, locale: 'en' },
			{ params: { slug: 'about' }, locale: 'fr' },
		],
		fallback: false,
	};
}

export async function getStaticProps({ params, locale }) {
	const translations = await import(`../locales/${locale}/common.json`);

	return {
		props: {
			translations,
			slug: params.slug,
		},
	};
}

这段代码为每个支持的语言生成静态页面,例如 /en/about 和 /fr/about,并根据 locale 加载相应的翻译 内容。

8.回退机制

Next.js i18n 支持语言的回退机制。如果用户选择的语言在某些页面没有提供完整的翻译,系统会回退到默 认语言以保证页面可用性。

总结 Next.js 的 i18n 实现原理包括通过配置 next.config.js 来管理多语言支持、基于动态路由的语言切 换、以及利用 getStaticProps 和 getStaticPaths 等机制为不同语言生成静态页面。开发者可以通过使用翻 译文件、按需加载以及路由的语言前缀来高效地实现国际化。

K