reactjs - i18next + react 路由器 : My URL isn't changing correctly when language is switched

标签 reactjs typescript react-router react-router-dom react-i18next

我试图在切换语言时更改应用程序 URL。当我在 URL 中手动添加所选语言(如 "http://localhost:3001/es/forgot-password")时,组件会使用所选语言正确加载,但是当我使用changeLanguage 事件,翻译工作正常,但 URL 中的语言没有更改,并且组件无法正确加载。

我已经坚持了很长时间,也研究了很多,尝试了不同的东西;没有任何东西可以帮助我正确解决问题。

这是我的代码:

i18n.tsx

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

i18n.use(XHR)
  .use(LanguageDetector)
  .use(HttpApi)
  .use(initReactI18next)
  .init({
    supportedLngs: ['en', 'es', 'pt', 'fr', 'gr', 'pl'],
    fallbackLng: 'en',
    detection: {
        order: ['querystring','path','cookie','htmlTag','localStorage','sessionStorage','subdomain'],
        caches: ['cookie', 'localStorage'],
        lookupQuerystring: 'lng',
        lookupCookie: 'i18next',
        lookupLocalStorage: 'i18nextLng',
        lookupSessionStorage: 'i18nextLng'
    },
    backend: {
        loadPath: "/locales/{{lng}}/translation.json"
    },
    interpolation: {escapeValue: false},
    debug: true,
    react: {useSuspense: false}
  });

export default i18n;

语言切换.tsx

import './LanguageSwitch.scss';
import { useState } from 'react';
import { useTranslation } from "react-i18next";

type LanguateSwitchProps = {
    passLanguageChange: (str: string) => void
};

const LanguageSwitch = (props: LanguateSwitchProps) => {
    const { t, i18n } = useTranslation(['home']);

    const [lang, setLang] = useState('en');

    const onClickLanguageChange = (e: any) => {
        const language = e.target.value;
        i18n.changeLanguage(language); //change the language
        props.passLanguageChange(language); //<---Sending the change language event to App with chosen language
    }

    return (
        <div className="language-switch">
            <select className="custom-select" onChange={onClickLanguageChange}>
                <option value="en">English</option>
                <option value="es">Español</option>
            </select>
            
        </div> 
  );
}

export default LanguageSwitch;

应用程序.tsx

import './App.scss';
import { useState } from 'react';
import { Routes, Route} from 'react-router-dom';
import { AuthProvider } from './auth';
import ChangePassword from './components/ChangePassword/ChangePassword';
import ForgotPassword from './components/ForgotPassword/ForgotPassword';
import Login from './components/Login/Login';
import ResetPassword from './components/ResetPassword/ResetPassword';
import Dashboard from './components/Dashboard/Dashboard';
import PrivateRoutes from './components/PrivateRoutes';
import LanguageSwitch from './components/LanguageSwitch/LanguageSwitch';
import  i18n from './i18n';

const App = () => {
  const [language, setLanguage] = useState(i18n.language);

  const handleLanguageChange = (lang: string) => {
    setLanguage(lang); //<---Capturing the switch language event and language from switch component
  }

  return (
    <AuthProvider>
      <div className="App"> 
        <div className="container">
        <LanguageSwitch passLanguageChange={handleLanguageChange}></LanguageSwitch>
          <div className="row">
            {language}
            <Routes>
              <Route path={`/${language}`} element={<Login/>}></Route> //<---passing the selected language in the path
              <Route path={`${language}/forgot-password`} element={<ForgotPassword/>}></Route>
              <Route element={<PrivateRoutes/>}>
                <Route path={`${language}/dashboard`} element={<Dashboard/>}></Route>
                <Route path={`${language}/change-password`} element={<ChangePassword/>}></Route>
              </Route> 
              <Route path="reset-password" element={<ResetPassword/>}></Route>
            </Routes>
          </div>
        </div>
      </div>
    </AuthProvider>
  );
}

export default App;

最佳答案

除了更新存储在状态中的语言之外,代码还应该使用新语言对路线进行导航更改,以便更新地址栏中的 URL。由于了解应用程序可能呈现的每条/所有路线有点不切实际,因此我建议使用一些字符串操作和一组已知的语言缩写来仅更新一个语言路径段。

示例:

const languages = {
  en: "English",
  es: "Español"
};
type LanguageSwitchProps = {
  language: string;
  passLanguageChange: (str: string) => void;
};

const LanguageSwitch = (props: LanguageSwitchProps) => {
  const { t, i18n } = useTranslation(['home']);

  const onClickLanguageChange = (e: any) => {
    const language = e.target.value;
    i18n.changeLanguage(language); // change the language
    props.passLanguageChange(language); // Send the change to App
  };

  return (
    <div className="language-switch">
      <select
        className="custom-select"
        value={props.language}
        onChange={onClickLanguageChange}
      >
        {Object.entries(languages).map(([value, label]) => (
          <option key={value} value={value}>
            {label}
          </option>
        ))}
      </select>
    </div>
  );
};
...
import {
  Routes,
  Route,
  Navigate,
  useLocation,
  useNavigate
} from 'react-router-dom';
...

const App = () => {
  const location = useLocation();
  const navigate = useNavigate();

  const [language, setLanguage] = useState(i18n.language);

  const handleLanguageChange = (lang: string) => {
    setLanguage(lang);
    const [language, ...path] = location.pathname.slice(1).split("/");

    if (language in languages) {
      navigate(
        {
          ...location,
          pathname: `/${[lang, ...path].join("/")}`
        },
        { replace: true }
      );
    }
  };

  return (
    <AuthProvider>
      <div className="App"> 
        <div className="container">
          <LanguageSwitch
            language={language}
            passLanguageChange={handleLanguageChange}
          />
          <div className="row">
            {language}

            <Routes>
              <Route path=":language">
                <Route index element={<Login />} />
                <Route path="forgot-password" element={<ForgotPassword />} />
                <Route element={<PrivateRoutes />}>
                  <Route path="dashboard" element={<Dashboard />} />
                  <Route path="change-password" element={<ChangePassword />} />
                </Route>
              </Route>
              <Route path="reset-password" element={<ResetPassword />} />
            </Routes>
          </div>
        </div>
      </div>
    </AuthProvider>
  );
}

export default App;

演示

Edit i18next-react-router-my-url-isnt-changing-correctly-when-language-is-switch

关于reactjs - i18next + react 路由器 : My URL isn't changing correctly when language is switched,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76835824/

相关文章:

redux - 如何确定 react 路由器中的事件路由

javascript - 在兄弟 React.js 之间传递索引

javascript - localStorage 的设置值是否有副作用?

android - ionic 2 : Run a background service with cordova

reactjs - 如何使用 react 测试库测试流畅的 ui 下拉菜单?

typescript - 引用错误 : Cannot access 'jest_mock_extended_1' before initialization

javascript - React router v4 渲染元素内的组件

javascript - 什么情况下可以卸载根组件?

javascript - 无法读取React中未定义的属性 'xxxxx'

javascript - ReactJS,渲染后重定向