Vercel部署Next.js应用:getServerSideProps无法加载i18nexus翻译值
开发环境下用next-i18next配合i18nexus做多语言完全正常,但部署到Vercel后,所有翻译内容都只显示键名,加载不出实际翻译值。当前项目用getServerSideProps获取翻译数据,因为[id]组件的需求,没法改用getStaticProps(不需要配置getStaticPaths)。
相关配置代码
next-i18next.config.js
module.exports = { i18n: { locales: ['en', 'ru', 'ar', 'es'], defaultLocale: 'en' } }
next.config.js
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: false, swcMinify: true, images: { domains: ["cdn.worldota.net"] }, i18n: { locales: ['en', 'ru', 'ar', 'es'], defaultLocale: 'en', }, env: { API_HOST: 'http://localhost:3000/api' }, } module.exports = nextConfig
_app.tsx
function App({ Component, pageProps }: AppProps) { //code return ( <> <ReactReduxContext.Consumer> {({ store }) => ( <PersistGate persistor={(store as any).__persistor} loading={<LoadingRouter />}> <Head> <link rel="icon" href={'./favicon.svg'} type="image/svg" /> </Head> <div className='wrapper'> {loading && <LoadingRouter />} <Component {...pageProps} /> </div> </PersistGate> )} </ReactReduxContext.Consumer> </> ) } App.getInitialProps = wrapper.getInitialAppProps(store => async ({ ctx, Component }) => { // store.dispatch(getUserData(userData.data.user)) и т.д. return { pageProps: Component.getInitialProps ? await Component.getInitialProps({ ...ctx, store }) : {}, } })
index.tsx
const Home: NextPage<HomeType> = ({ locale }) => { const dispatch = useAppDispatch() useEffect(() => { dispatch(languageFunction(locale)) }, []) return ( <div className='shelters_housing'> <MainScreen /> <div className='shelters_housing_flex'> <div className='shelters_housing_flex_container'> <TravelToEarn /> <SearchByPlacementType /> <PopularPlacesInRussia /> <SubscribeNewsletter /> <PopularHouses /> <OurFavoriteDestinations /> </div> </div> <SaveTimeAndMoney /> <Footer /> </div> ) } export const getServerSideProps: GetStaticProps = async ({ locale }) => { return { props: { ...(await serverSideTranslations(locale!, ['main', 'footer', 'header', 'common', 'regions', 'discover'])), locale } } }
解决方案
1. 确认翻译文件未丢失
i18nexus生成的翻译文件默认在public/locales目录,检查:
- 目录下是否包含所有语言的子文件夹(en、ru、ar、es),每个子文件夹内是否有对应翻译JSON文件(如main.json)
.gitignore是否忽略了public/locales,若忽略会导致Vercel拉取代码时丢失翻译文件,直接显示键名
2. 统一i18n配置,避免重复定义
当前next-i18next.config.js和next.config.js均定义了i18n配置,易引发冲突。修改next.config.js,直接引入next-i18next.config的配置:
/** @type {import('next').NextConfig} */ const { i18n } = require('./next-i18next.config') const nextConfig = { reactStrictMode: false, swcMinify: true, images: { domains: ["cdn.worldota.net"] }, i18n, // 复用next-i18next的配置 env: { API_HOST: 'http://localhost:3000/api' }, } module.exports = nextConfig
3. 用appWithTranslation包裹App组件
你的_app.tsx未使用next-i18next的appWithTranslation高阶组件,导致全局翻译上下文未初始化,无法加载翻译。修改_app.tsx:
import { appWithTranslation } from 'next-i18next' // 其他导入保持不变 function App({ Component, pageProps }: AppProps) { // 原代码无需修改 } App.getInitialProps = wrapper.getInitialAppProps(store => async ({ ctx, Component }) => { return { pageProps: Component.getInitialProps ? await Component.getInitialProps({ ...ctx, store }) : {}, } }) // 关键:用appWithTranslation包裹App组件后导出 export default appWithTranslation(App)
4. 修正getServerSideProps的类型错误
index.tsx中错误地将getServerSideProps标注为GetStaticProps类型,改为GetServerSideProps:
import { GetServerSideProps } from 'next' // 其他导入不变 export const getServerSideProps: GetServerSideProps = async ({ locale }) => { return { props: { ...(await serverSideTranslations(locale!, ['main', 'footer', 'header', 'common', 'regions', 'discover'])), locale } } }
5. 核对翻译键名完全匹配
检查i18nexus生成的JSON文件中的键名,与代码中useTranslation调用的键名是否完全一致(包括大小写、层级结构)。例如代码中使用t('main.welcome.title'),则JSON文件中需对应存在"welcome": {"title": "xxx"}的结构。
6. 动态拉取翻译需配置Vercel环境变量
若通过i18nexus API动态拉取翻译而非使用本地文件,需在Vercel环境变量中配置i18nexus的API密钥,并确保生产环境可正常访问该API。更推荐提前将翻译文件下载至本地public/locales,避免部署时网络问题导致翻译加载失败。
内容的提问来源于stack exchange,提问作者Стас Лабанов

