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

React多语言切换时动态修改URL避免404问题求助

问题原因

你当前的核心问题是切换语言时仅更新了state,但未同步修改当前URL的路径。比如在英文的/About页面切换到挪威语后,URL仍为#/About,但挪威语路由配置中不存在/About路径,因此直接匹配到404页面。只有点击导航链接时才会修正URL,回到正常页面。

解决方案

要实现任意页面切换语言时同步更新URL并渲染对应页面,需在切换语言时根据当前路径自动跳转到对应语言的等效路径,具体步骤如下:

  1. 建立两种语言路径的映射关系,方便互相转换
  2. 使用react-router-dom的useNavigate和useLocation钩子,获取当前路径并跳转到对应语言的路径
  3. 处理动态路由(如Projects/:id),确保切换语言时保留路由参数
修改后的代码示例
import React, { useState } from 'react';
import { HashRouter, NavLink, Routes, Route, useNavigate, useLocation } from 'react-router-dom';

import { Home } from './pages/Home';
import { About } from './pages/About';
import { Projects } from './pages/Projects';
import { Project } from './pages/Project';
import { Contact } from './pages/Contact';
import { PageNotFound } from './pages/PageNotFound';
import { ProjectsMenu } from './pages/ProjectsMenu';

import { Hjem } from './pages/Hjem';
import { Om } from './pages/Om';
import { Prosjekter } from './pages/Prosjekter';
import { Prosjekt } from './pages/Prosjekt';
import { Kontakt } from './pages/Kontakt';
import { SideIkkeFunnet } from './pages/SideIkkeFunnet';
import { ProsjekterMeny } from './pages/ProsjekterMeny';

import './assets/App.css';

function App() {
  const [isDarkMode, setIsDarkMode] = useState(false);
  const [language, setLanguage] = useState('english');
  const navigate = useNavigate();
  const location = useLocation();

  // 定义两种语言路径的映射关系
  const pathMap = {
    english: {
      '/': '/',
      '/About': '/Om',
      '/Projects': '/Prosjekter',
      '/Projects/:id': '/Prosjekter/:id',
      '/Contact': '/Kontakt'
    },
    norwegian: {
      '/': '/',
      '/Om': '/About',
      '/Prosjekter': '/Projects',
      '/Prosjekter/:id': '/Projects/:id',
      '/Kontakt': '/Contact'
    }
  };

  const handleModeToggle = () => {
    setIsDarkMode(!isDarkMode);
  };

  const handleLanguageToggle = () => {
    const targetLang = language === 'english' ? 'norwegian' : 'english';
    let currentPath = location.pathname;

    // 处理动态路由(如 /Projects/1 → /Prosjekter/1)
    if (currentPath.startsWith('/Projects/')) {
      const id = currentPath.split('/')[2];
      currentPath = '/Projects/:id';
      navigate(pathMap[language][currentPath].replace(':id', id));
    } else if (currentPath.startsWith('/Prosjekter/')) {
      const id = currentPath.split('/')[2];
      currentPath = '/Prosjekter/:id';
      navigate(pathMap[language][currentPath].replace(':id', id));
    } else {
      // 静态路由直接映射跳转
      navigate(pathMap[language][currentPath] || '/');
    }

    setLanguage(targetLang);
  };

  const getRoutes = () => {
    if (language === 'english') {
      return (
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/About" element={<About />} />
          <Route path="/Projects" element={<ProjectsMenu />}>
            <Route index element={<Projects />} />
            <Route path=":id" element={<Project />} />
          </Route>
          <Route path="/Contact" element={<Contact />} />
          <Route path="*" element={<PageNotFound />} />
        </Routes>
      );
    } else {
      return (
        <Routes>
          <Route path="/" element={<Hjem />} />
          <Route path="/Om" element={<Om />} />
          <Route path="/Prosjekter" element={<ProsjekterMeny />}>
            <Route index element={<Prosjekter />} />
            <Route path=":id" element={<Prosjekt />} />
          </Route>
          <Route path="/Kontakt" element={<Kontakt />} />
          <Route path="*" element={<SideIkkeFunnet />} />
        </Routes>
      );
    }
  };

  return (
    <div className={`app ${isDarkMode ? 'dark-mode' : 'light-mode'}`}>
      <nav>
        <div id="toggle" className="displayMode" onClick={handleModeToggle}>
          {isDarkMode ? 'Light Mode' : 'Dark Mode'}
        </div>
        <div id="language-toggle" className="languageMode" onClick={handleLanguageToggle}>
          {language === 'english' ? 'Norsk' : 'English'}
        </div>
        <ul>
          <li>
            <NavLink to="/">{language === 'english' ? 'Home' : 'Hjem'}</NavLink>
          </li>
          <li>
            <NavLink to={language === 'english' ? '/About' : '/Om'}>{language === 'english' ? 'About' : 'Om'}</NavLink>
          </li>
          <li>
            <NavLink to={language === 'english' ? '/Projects' : '/Prosjekter'}>{language === 'english' ? 'Projects' : 'Prosjekter'}</NavLink>
          </li>
          <li>
            <NavLink to={language === 'english' ? '/Contact' : '/Kontakt'}>{language === 'english' ? 'Contact' : 'Kontakt'}</NavLink>
          </li>
        </ul>
      </nav>
      <div className="homeAnimation"></div>
      {getRoutes()}
    </div>
  );
}

// 将HashRouter移至App外部,确保内部钩子能正常获取路由上下文
export default function WrappedApp() {
  return (
    <HashRouter>
      <App />
    </HashRouter>
  );
}
关键修改说明
  • 将HashRouter移到App组件外部,确保useNavigate和useLocation钩子能正常访问路由上下文
  • 新增pathMap对象,明确两种语言路径的对应关系,包括动态路由模板
  • 修改handleLanguageToggle函数:
    • 区分静态/动态路由,动态路由提取参数后替换到目标路径中
    • 通过navigate方法同步更新URL,再修改语言状态
  • 确保导航链接的to属性使用完整路径(如/About而非About),避免路径拼接错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:57:08