迁移至Next.js时React-i18next报错:文本与服务端渲染HTML不匹配
解决Next.js与react-i18next服务端渲染内容不匹配问题
核心问题分析
你遇到的Text content does not match server-rendered HTML错误,本质是服务端渲染时使用的语言和客户端hydrate时的语言不一致:
- 服务端无法读取客户端的
localStorage或cookie,只能用fallbackLng(en)渲染页面 - 客户端加载后,通过
LanguageDetector读取到用户之前选择的语言,切换后导致页面内容和服务端输出的HTML不匹配 - 另外,你将i18n初始化代码放到
next.config.js是错误的,该文件是Next.js的配置文件,不能用来初始化i18next
分步解决方案
1. 恢复i18n初始化文件
将原来的i18n代码恢复到单独的i18n.js文件,不要修改next.config.js:
import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import Backend from 'i18next-http-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; const Languages = ['ar', 'en', 'fr'] i18n .use(Backend) .use(LanguageDetector) .use(initReactI18next) .init({ fallbackLng: "en", react: { useSuspense: true, }, supported: ["en", "fr", "ar"], detection: { // 调整检测顺序,服务端优先从请求头/路由获取,客户端用localStorage/cookie order: ['path', 'cookie', 'htmlTag', 'localStorage', 'subdomain'], caches: ['localStorage'], }, debug: false, whitelist: Languages, interpolation: { escapeValue: false, }, nsSeparator: false, keySeparator: false, backend: { loadPath: '/static/locales/{{lng}}/{{ns}}.json', }, }); export default i18n;
2. 修改_app.js,确保服务端与客户端语言一致
在_app.js中,从服务端请求中获取语言并传递给客户端,保证两端语言统一:
import React from 'react'; import { Provider } from 'react-redux'; import { useStore } from '../store'; import '../styles/globals.css'; import Layout from '../hocs/Layout'; import '../i18n'; // 引入正确的i18n初始化文件 import i18n from '../i18n'; import cookies from 'js-cookie'; function App({Component, pageProps, initialLanguage}) { const store = useStore(pageProps.initialReduxState); // 客户端初始化时同步服务端传递的语言 React.useEffect(() => { if (initialLanguage) { i18n.changeLanguage(initialLanguage); cookies.set('i18next', initialLanguage); } }, [initialLanguage]); return ( <Provider store={store}> <Layout> <Component {...pageProps} /> </Layout> </Provider> ); }; // 服务端获取用户语言,传递给客户端 App.getInitialProps = async ({ ctx }) => { let initialLanguage = 'en'; // 从cookie读取用户已选择的语言 const cookieLanguage = ctx.req?.cookies?.i18next; if (cookieLanguage && ['en', 'fr', 'ar'].includes(cookieLanguage)) { initialLanguage = cookieLanguage; } return { initialLanguage }; }; export default App;
3. 调整LoginHeader的语言切换逻辑
修改语言切换按钮,确保切换时同步更新cookie,让服务端能正确识别:
// 在LoginHeader的语言按钮点击事件中 <button onClick={() => { i18next.changeLanguage(code); cookies.set('i18next', code); }} className='loginHeader__lang__btn' > {name} </button>
4. 配置Next.js国际化路由(可选但推荐)
在next.config.js中添加国际化配置,让服务端能通过路由参数直接获取语言:
module.exports = { i18n: { locales: ['en', 'fr', 'ar'], defaultLocale: 'en', }, };
额外注意事项
- 确保
react-i18next和i18next的版本与Next.js兼容 - 开启
useSuspense: true后,需要用Suspense组件包裹使用t()的组件,或者在页面级别添加加载状态 - 服务端渲染时避免直接操作
document,可以在_document.js中根据服务端传递的语言设置dir属性
内容的提问来源于stack exchange,提问作者Moammer
相关产品推荐
相关产品推荐

