Next.js中从Pages路由迁移至App路由时的getStaticProps({locale})适配问题
Next.js 13 App Router 中获取 locale 并适配 next-i18n 的问题
我正尝试将Next.js项目从Pages路由迁移至App Router,在适配Next 13的App Router页面时遇到了getStaticProps({locale})的问题。原Pages路由中getStaticProps默认会接收locale参数,但在App Router中不清楚该如何获取这个locale参数。
原Pages路由代码
import React from 'react'; import {message} from 'antd'; import {TFunction, I18n, useTranslation} from 'next-i18next'; import {NextPage} from 'next'; import {NextSeo} from 'next-seo'; import {useRouter} from 'next/navigation'; import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; import Layout from '../../components/Layout'; import AuthorForm, {FormFields} from '../../components/Author/Form'; import {useCreateAuthor} from '../../service-hooks/resourceAuthor'; type InitialProps = Promise<{ namespacesRequired: string[]; }>; type Props = { t: TFunction; i18n: I18n; }; const NewAuthor: NextPage<Props, InitialProps> = () => { const {t, i18n} = useTranslation(['common', 'form', 'admin', 'resource-types']); const router = useRouter(); const {mutate: create, isLoading} = useCreateAuthor(); return ( <Layout defaultLanguage={i18n.language} tFunc={t}> <NextSeo title={t('form:new', {entity: t('admin:authors.label')})}/> <div className="pt-4"> <AuthorForm tFunc={t} processLoading={isLoading} texts={AuthorFormTexts} onFinish={handleFinish}/> </div> </Layout> ); }; const getStaticProps = async function({locale}) { return { ...(await serverSideTranslations(locale, ['common', 'form', 'admin', 'resource-types'])), // 传递给页面组件的props }; } export default NewAuthor;
尝试的App Router代码(无法获取locale)
我尝试使用异步函数替代,但无法获取locale参数:
import React from 'react'; import {message} from 'antd'; import {TFunction, I18n, useTranslation} from 'next-i18next'; import {NextPage} from 'next'; import {NextSeo} from 'next-seo'; import {useRouter} from 'next/navigation'; import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; import Layout from '../../components/Layout'; import AuthorForm, {FormFields} from '../../components/Author/Form'; import {useCreateAuthor} from '../../service-hooks/resourceAuthor'; type InitialProps = Promise<{ namespacesRequired: string[]; }>; type Props = { t: TFunction; i18n: I18n; }; // 按照文档,这个函数应该和getStaticProps作用类似 async function getLocale({locale}) { return { ...(await serverSideTranslations(locale, ['common', 'form', 'admin', 'resource-types'])), // 传递给页面组件的props }; } // 因为异步函数报错,所以移除了类型 const NewAuthor = async () => { const {t, i18n} = useTranslation(['common', 'form', 'admin', 'resource-types']); const router = useRouter(); const {mutate: create, isLoading} = useCreateAuthor(); return ( <Layout defaultLanguage={i18n.language} tFunc={t}> <NextSeo title={t('form:new', {entity: t('admin:authors.label')})}/> <div className="pt-4"> <AuthorForm tFunc={t} processLoading={isLoading} texts={AuthorFormTexts} onFinish={handleFinish}/> </div> </Layout> ); }; export default NewAuthor;
解决方案
App Router中获取locale的逻辑和Pages路由完全不同,需要结合服务器组件特性和国际化配置来实现,同时适配next-i18next的翻译加载:
1. 服务器组件中获取locale(推荐方案)
App Router的页面默认是服务器组件,可以直接从路由参数params中获取locale(前提是已配置国际化路由),并在服务器端预加载翻译:
import React from 'react'; import {NextSeo} from 'next-seo'; import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; import Layout from '../../components/Layout'; import AuthorClientComponent from './AuthorClientComponent'; // 服务器组件接收路由params async function NewAuthor({params}: { params: { locale: string } }) { // 在服务器端预加载对应locale的翻译 const {t, i18n} = await serverSideTranslations(params.locale, ['common', 'form', 'admin', 'resource-types']); return ( <Layout defaultLanguage={i18n.language} tFunc={t}> <NextSeo title={t('form:new', {entity: t('admin:authors.label')})}/> <div className="pt-4"> {/* 将需要客户端交互的逻辑抽离为客户端组件 */} <AuthorClientComponent t={t} locale={params.locale} /> </div> </Layout> ); } export default NewAuthor;
抽离的客户端组件(AuthorClientComponent.tsx)
'use client'; import React from 'react'; import {message} from 'antd'; import {useRouter} from 'next/navigation'; import AuthorForm, {FormFields} from '../../components/Author/Form'; import {useCreateAuthor} from '../../service-hooks/resourceAuthor'; type Props = { t: any; locale: string; }; function AuthorClientComponent({t, locale}: Props) { const router = useRouter(); const {mutate: create, isLoading} = useCreateAuthor(); const handleFinish = async (values: FormFields) => { try { await create(values); message.success(t('common:success')); router.push(`/${locale}/admin/authors`); } catch (err) { message.error(t('common:error')); } }; return ( <AuthorForm tFunc={t} processLoading={isLoading} texts={AuthorFormTexts} onFinish={handleFinish}/> ); } export default AuthorClientComponent;
2. 客户端组件中获取locale
如果需要在纯客户端组件中获取当前locale,可以使用useRouter钩子的locale属性:
'use client'; import {useRouter} from 'next/navigation'; function SomeClientComponent() { const router = useRouter(); const currentLocale = router.locale; // 获取当前语言环境 // ...后续逻辑 }
关键注意点
- App Router不再支持
getStaticProps,服务器组件可直接异步获取数据和翻译 serverSideTranslations必须在服务器组件中调用,不能在客户端组件使用- 包含客户端钩子(如
useRouter、useMutation)的组件必须添加'use client'指令
内容的提问来源于stack exchange,提问作者Baigeldy Sultanov
相关产品推荐
相关产品推荐

