React i18next报错:文本内容与服务端渲染HTML不匹配
问题:React + i18next 服务端渲染文本不匹配错误
我在React项目中集成i18next时遇到了text content does not match server-rendered html错误。翻译功能本身正常,能获取正确译文也能切换语言,但这个错误始终无法解决,查了大量同类问题都没找到有效方案。
相关代码
i18n.ts 文件
import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import Backend from 'i18next-http-backend'; import translations_de_DE from '../../public/locales/de_DE/translation.json'; import translations_en_US from '../../public/locales/en_US/translation.json'; const resources = { // 后续可改为远程获取 de_DE: { translation: translations_de_DE }, en_US: { translation: translations_en_US }, }; i18n .use(initReactI18next) // 将i18n实例传递给react-i18next .use(LanguageDetector) .use(Backend) .init({ resources, // lng: "de_DE", fallbackLng: 'de_DE', keySeparator: false, // 不使用类似messages.welcome的键结构 interpolation: { escapeValue: false }, // React已处理XSS防护 }); export default i18n;
简化后的 index.tsx
import './i18n'; import { useTranslation } from 'next-i18next'; const Home = () => { const { t } = useTranslation(); return ( <div> {t<string>('project_plural')} </div> ); }; export default Home;
语言切换组件 Settings.tsx
import React, { useEffect, useState } from 'react'; import i18n from 'i18next'; import { useTranslation } from 'next-i18next'; const Settings = () => { const { t } = useTranslation(); const [language, setLanguage] = useState(''); const changeLanguage = (event: any) => { // 原拼写错误修正:changeLanugage -> changeLanguage i18n.changeLanguage(event.target.value); setLanguage(event.target.value); }; useEffect(() => { // 注:原代码中currentTheme、setDarkMode未定义,此处保留原代码结构 if (currentTheme === 'dark') { setDarkMode(true); } const localLanguage = localStorage.getItem('i18nextLng'); setLanguage(localLanguage ? localLanguage : 'de_DE'); }, []); return ( <select value={language} onChange={changeLanguage} > <option value="en_US">English</option> <option value="de_DE">Deutsch</option> </select> ); }; export default Settings;
解决方案
这个错误的核心原因是服务端渲染时的语言环境和客户端初始化后的语言环境不一致,导致首次渲染的DOM内容不匹配。
1. 统一服务端与客户端初始语言
服务端无法访问浏览器的localStorage或navigator信息,不能依赖客户端的LanguageDetector获取初始语言。需区分环境初始化i18n:
// i18n.ts 修改后的代码 import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import Backend from 'i18next-http-backend'; import translations_de_DE from '../../public/locales/de_DE/translation.json'; import translations_en_US from '../../public/locales/en_US/translation.json'; const resources = { de_DE: { translation: translations_de_DE }, en_US: { translation: translations_en_US }, }; // 封装初始化方法,支持传入服务端获取的语言 const initI18n = (lng?: string) => { const i18nInstance = i18n.createInstance(); return i18nInstance .use(initReactI18next) // 仅客户端使用LanguageDetector .use(typeof window !== 'undefined' ? LanguageDetector : Backend) .init({ resources, lng: lng || 'de_DE', fallbackLng: 'de_DE', keySeparator: false, interpolation: { escapeValue: false }, }); }; // 客户端自动初始化 if (typeof window !== 'undefined') { initI18n(); } export default initI18n;
2. 用Suspense等待翻译加载
客户端渲染时,等待i18n完成初始化再渲染内容,避免hydration不匹配:
// index.tsx 修改后的代码 import { Suspense } from 'react'; import initI18n from './i18n'; import { useTranslation } from 'next-i18next'; const HomeContent = () => { const { t } = useTranslation(); return <div>{t<string>('project_plural')}</div>; }; const Home = () => { return ( <Suspense fallback={<div>Loading...</div>}> <HomeContent /> </Suspense> ); }; // Next.js服务端预渲染时传递语言参数 export async function getServerSideProps(context: any) { // 从请求头或Cookie获取用户语言 const lng = context.req.headers['accept-language']?.split(',')[0] || 'de_DE'; await initI18n(lng); return { props: { lng } }; } export default Home;
3. 修正语言切换组件的拼写错误
原Settings.tsx中changeLanugage拼写错误,改为changeLanguage,确保切换逻辑正常执行。
内容的提问来源于stack exchange,提问作者TGDev
相关产品推荐
相关产品推荐

