You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

i18next语言检测问题:首次加载时组件渲染异常

问题描述

使用Next.js + React构建作品集网站,通过i18next实现国际化,仅支持英语(en)和德语(de)。核心问题:首次访问(如无痕窗口)时,当浏览器语言为不支持的语言(如西班牙语es-ES),Projects组件无法正常渲染;手动切换语言后恢复正常;但浏览器语言为en/de时,组件能正常加载。

Projects组件代码

"use client";
import React, { Fragment, useEffect, useState } from "react";
import SectionHeading from "./Section-heading";
import { projectsData } from "@/lib/data";
import { projectsDataDe } from "@/lib/dataDe";
import { useSectionInView } from "@/lib/hooks";
import { useTranslation } from "react-i18next";

export default function Projects() {
  const { ref } = useSectionInView("Projects");
  const { t, i18n } = useTranslation();
  const [projects, setProjects] = useState<any>();

  useEffect(() => {
    switch (i18n.language) {
      case "en":
        setProjects(projectsData);
        break;
      case "de":
        setProjects(projectsDataDe);
    }
  }, [i18n.language]);

  return (
    <section id="projects" ref={ref} className="mb-28 max-w-[53rem] scroll-mt-28 text-center sm:mb-40">
      <SectionHeading title={t("my_projects_title")} />
      <div>
        {projects &&
          projects.map((project: any) => (
            <Fragment key={project.id}>
              <Project {...project} />
            </Fragment>
          ))}
      </div>
      <h2 className="mb-28 max-w-[53rem] scroll-mt-28 text-center sm:mb-40">
        {t("more_projects")}
      </h2>
    </section>
  );
}

LanguageSwitch组件代码

"use client";
import React from "react";
import { useTranslation } from "react-i18next";

export default function LanguageSwitch() {
  const { i18n } = useTranslation();

  const changeLanguage = (lang: string) => {
    i18n.changeLanguage(lang);
  };

  return (
    <div className="relative" style={{ zIndex: 9999 }}>
      <select
        className="fixed top-5 right-5 bg-white w-[3rem] h-[3rem] bg-opacity-80 backdrop-blur-[0.5rem] border border-gray-950 border-opacity-40 shadow-2x1 rounded-full flex items-center justify-center hover:scale-[1.15] active:scale-105 transition-all dark:bg-gray-950 dark:border-white"
        onChange={(e) => changeLanguage(e.target.value)}
      >
        <option value="en">🇪🇳</option>
        <option value="de">🇩🇪</option>
      </select>
    </div>
  );
}

i18next配置代码

"use client";
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";

i18next
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    fallbackLng: "en",
    debug: true,
    resources: {
      en: {
        translation: {
          // English translations...
        },
      },
      de: {
        translation: {
          // German translations...
        },
      },
    },
    detection: {
      order: ['localStorage', 'cookie', 'navigator'],
      caches: ['localStorage', 'cookie'],
      checkWhitelist: true,
    },
  });

控制台信息

i18next: languageChanged es-ES

核心问题
  1. 为何Projects等组件首次加载渲染异常,切换语言后却能正常显示?
  2. 如何确保首次加载时正确检测语言并让组件正常渲染?
  3. 是否是语言检测导致的问题?若是,如何确保es-ES这类不支持的语言能正确回退到en?
解决方案与回答

问题1:首次加载异常、切换后正常的原因

Projects组件的useEffect仅在i18n.language为en或de时调用setProjects。首次加载时,语言检测器识别到es-ES,此时i18n.language为es-ES,不匹配switch的任何分支,导致projects始终为undefined,组件中{projects && ...}的渲染条件不满足,因此项目列表无法显示。

手动切换语言时,i18n.language变为en或de,触发useEffect执行,setProjects被调用,组件拿到数据后正常渲染。

问题2:确保首次加载正确渲染的方法

有两种可行方案:

  • 方案1:初始化状态设置默认值
    给projects状态设置初始值,默认使用英文数据:

    const [projects, setProjects] = useState<any>(projectsData);
    

    即使首次语言不匹配,组件也能先显示英文项目,后续语言切换时再更新数据。

  • 方案2:在useEffect中添加默认分支
    在switch中增加default分支,处理不支持的语言场景:

    useEffect(() => {
      switch (i18n.language) {
        case "en":
          setProjects(projectsData);
          break;
        case "de":
          setProjects(projectsDataDe);
          break;
        default:
          // 回退到英文数据
          setProjects(projectsData);
      }
    }, [i18n.language]);
    

问题3:语言检测的问题与回退修复

确实是语言检测环节的问题。当前配置缺少supportedLngs项,i18next无法识别你支持的语言列表,因此不会自动将不支持的语言回退到fallbackLng。

修复步骤:

  1. 在i18next初始化配置中添加supportedLngs,明确声明支持的语言:

    i18next.init({
      fallbackLng: "en",
      supportedLngs: ["en", "de"], // 新增配置
      debug: true,
      // 其他原有配置...
    });
    

    结合已开启的checkWhitelist: true,i18next会自动将不支持的语言(如es-ES)回退到fallbackLng(en),此时i18n.language会变为en,useEffect能匹配到case "en"并正确设置项目数据。

  2. (可选)处理带区域的语言
    若需要兼容en-US、de-DE这类带区域后缀的语言,可开启load: "languageOnly"配置,让i18next忽略区域后缀,只识别基础语言代码:

    i18next.init({
      // 其他配置...
      load: "languageOnly", // 新增,仅加载en/de,忽略区域后缀
    });
    

内容的提问来源于stack exchange,提问作者Bilbit Bolson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 06:55:57