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

react-i18next多语言切换失效,无法读取翻译JSON文件

react-i18next 翻译不生效问题排查与解决

我在应用中实现react-i18next用于英法双语切换,但功能异常。{t("submit")}直接渲染为字符串"submit",没有读取翻译文件中对应的"Login"值。我怀疑是JSON翻译文件的识别问题,已经检查过路径和拼写但未解决,附上相关代码:


相关代码

index.jsx

import { createRoot } from "react-dom/client";
import {
 createBrowserRouter,
 RouterProvider,
 Outlet,
} from "react-router-dom";
import "./i18n";
import {Suspense} from "react";
import MonitoringOverview from "./routes/MonitoringOverview";
import PerformanceQuality from "./routes/PerformanceQuality";
import Finance from "./routes/Finance";
import Navbar from "./components/Navbar/Navbar";
import "./App.css";
import LoginScreen from "./routes/LoginScreen/LoginScreen";
import UserConfig from "./routes/UserConfig/UserConfig.js";
import Simulation from "./routes/Simulation";
import Fraud from "./routes/Fraud";

const AppLayout = () => {
 return (
   <Suspense fallback={null}>
 <>
   <Navbar />
   <Outlet />
 </>
 </Suspense>
);

}

const router = createBrowserRouter([
 {
   path: '/',
   element: <LoginScreen />
 },
 {
   element: <AppLayout />,
   children: [
     {
       path: "monitoringoverview",
       element: <MonitoringOverview />,
     },
 
     {
       path: "performancequality",
       element: <PerformanceQuality />,
     },

     {
       path: "finance",
       element: <Finance />,
     },
     {
       path: "simulation",
       element: <Simulation />,
     },
     {
       path: 'userconfig',
       element: <UserConfig />
     },
     {
       path: 'fraud',
       element: <Fraud />
     },
   ],
 },
]);

createRoot(document.getElementById("root")).render(
 <RouterProvider router={router} />
 
);

i18n.js

import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next';

i18n.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
    backend: {
        //translation file path
        loadPath: "/public/assets/i18n/{{ns}}/{{lng}}.json",
    },
    fallbackLng: "en",
    //disableed in production
    debug: false,

    // can have multiple namespaces to divide translation into smaller pieces and load them on demand
    ns: ["login","navbar"],
    interpolation: {
        escapeValue: false,
        formatSeperator: ",",
    },
    react: {
        wait: true,
    },
})

export default i18n;

LoginScreen.js

import React, {useState} from 'react'
import "./LoginScreen.css"
import {Navigate} from "react-router-dom";
import pangeaLogo from "./images/pangealogosmall.png"

// i18n implementation
import { useTranslation } from 'react-i18next';
function LoginScreen() {
// React States
  const [errorMessages, setErrorMessages] = useState({});
  const [isSubmitted, setIsSubmitted] = useState(false);

  const { t } = useTranslation(["login"]);
//Database for demo authentication
  const database = [
    {
      username: "admin",
      password: "pangea123",
    },
    {
      username: "admin2",
      password: "Pangea1234$",
    }
  ];

  const errors = {
    uname: "invalid username",
    pass: "invalid password",
  };

//Submit handling
const handleSubmit = (event) => {
  //Prevent page reload
  event.preventDefault();
  var { uname, pass } = document.forms[0];

  // Find user login info
  const userData = database.find((user) => user.username === uname.value);

  // Compare user info
  if (userData) {
    if (userData.password !== pass.value) {
      // Invalid password
      setErrorMessages({ name: "pass", message: errors.pass });
    } else {
      setIsSubmitted(true);
    }
  } else {
    // Username not found
    setErrorMessages({ name: "uname", message: errors.uname });
  }
};

  //Error messages handling
  const renderErrorMessage = (name) =>
    name === errorMessages.name && (
      <div className="error">{errorMessages.message}</div>
    );

  //Login Form
  const renderForm = (
    <div className="form">
      <form action="" onSubmit={handleSubmit}>
        <div className="input-container">
        <label for="inp" class="inp">
          <input type="text" id="inp" placeholder="&nbsp;"  name="uname" required/>
          <span class="label">Username</span>
          <span class="focus-bg"></span>
        </label>
          {renderErrorMessage("uname")}
        </div>
        <div className="input-container">
        <label for="inp" class="inp">
          <input  id="inp" placeholder="&nbsp;" type="password" name="pass" required />
          <span class="label">Password</span>
          <span class="focus-bg"></span>
        </label>
          {renderErrorMessage("pass")}
        </div>
        <div className="button-container">
        <input type="submit" value={t("submit")} />
        </div>
      </form>
    </div>

);

return(
  <div className="app">
      <div className="login-form">
        <img className='pangeaLogo' src={pangeaLogo} alt="pangeaLogo" />
        <div className="title">Welcome to Pangea Insights Application</div>
        <div className='project-name'>Congo DRC Operational Process</div>
        <div className='login-please'>Please {t("submit")}</div>
        {isSubmitted ? <Navigate to="/monitoringoverview" />: renderForm }
      </div>
    </div>
);
}

export default LoginScreen

en.js(翻译文件)

{
    "submit": "Login"
}

问题排查与解决

1. 修正翻译文件路径配置

React项目中public是静态资源根目录,请求路径无需包含/public,修改i18n.js中的loadPath:

loadPath: "/assets/i18n/{{ns}}/{{lng}}.json"

2. 确认文件实际存放位置

确保翻译文件路径与配置完全匹配:

  • 英文翻译文件:public/assets/i18n/login/en.json
  • 法文翻译文件:public/assets/i18n/login/fr.json

3. 启用debug模式排查

将i18n.js中debug设为true,查看控制台日志,确认翻译文件是否成功加载:

debug: true,

4. 包裹LoginScreen组件到Suspense中

当前LoginScreen作为根路径组件,未被Suspense包裹,修改路由配置:

{
  path: '/',
  element: (
    <Suspense fallback={null}>
      <LoginScreen />
    </Suspense>
  )
},

开启react.wait: true时,组件必须被Suspense包裹才能等待翻译加载完成,否则会直接显示key值。


内容的提问来源于stack exchange,提问作者Noam TheLoreFnatic Hadad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:37:51