React Router v4+Redux多语言应用:URL传locale及路径生成问题
Hey there! Let's tackle that language selector path generation issue you're facing with your React/Redux i18n app. Based on your setup (using react-redux-i18n, ConnectedRouter, and path-to-regexp), here's a practical, step-by-step solution:
Core Approach
The goal is to generate route paths that swap the current language identifier while preserving the rest of the page's route structure. We'll leverage path-to-regexp (which you're already using) and your existing Redux i18n state to make this seamless.
Step 1: Create a Path Generation Utility Function
First, build a reusable function to parse the current route, swap the language parameter, and compile the new path. This works with your existing path-to-regexp setup:
import pathToRegexp from 'path-to-regexp'; // Generate a new route path with the target language const generateLangPath = (match, targetLang, currentPath) => { // Case 1: Current route already has a language parameter if (match.params.lang) { const pathRegex = pathToRegexp(match.path); const params = pathRegex.exec(currentPath).groups; // Replace the language parameter with the target language params.lang = targetLang; return pathToRegexp.compile(match.path)(params); } // Case 2: No language parameter (fallback for root routes) else { return `/${targetLang}${currentPath === '/' ? '' : currentPath}`; } };
Step 2: Build the Language Selector Component
Create a connected component that fetches the current language from Redux, uses the utility function to generate paths, and handles language switching + routing:
import React from 'react'; import { connect } from 'react-redux'; import { setLocale } from 'react-redux-i18n'; const LanguageSelector = ({ match, history, currentLang }) => { // Define your supported languages const supportedLanguages = ['en', 'fr', 'de']; const handleLanguageChange = (targetLang) => { if (targetLang === currentLang) return; // Generate the new route path const newPath = generateLangPath(match, targetLang, history.location.pathname); // Update Redux i18n state setLocale(targetLang); // Navigate to the new language-specific path history.push(newPath); }; return ( <ul className="language-selector"> {supportedLanguages.map(lang => ( <li key={lang}> <button onClick={() => handleLanguageChange(lang)} disabled={lang === currentLang} className={lang === currentLang ? 'active' : ''} > {lang.toUpperCase()} </button> </li> ))} </ul> ); }; // Connect to Redux to get current language and i18n actions export default connect( state => ({ currentLang: state.i18n.locale }), { setLocale } )(LanguageSelector);
Step 3: Update Your Route Configuration
Make sure your root routes include a language parameter to support the path structure. This ensures your existing NavLink patterns (like ${match.url}/ABC) work correctly with language prefixes:
import { ConnectedRouter, Switch, Route, Redirect } from 'react-router-redux'; import { createBrowserHistory } from 'history'; import App from './containers/App'; const history = createBrowserHistory(); const RootRouter = () => ( <ConnectedRouter history={history}> <Switch> // Main app route with language parameter <Route path="/:lang" component={App} /> // Redirect root to default language (e.g., English) <Redirect from="/" to="/en" /> </Switch> </ConnectedRouter> ); export default RootRouter;
Step 4: Integrate the Selector into Your App
Add the LanguageSelector to your App.jsx container alongside your existing navigation:
// containers/App.jsx import LanguageSelector from './LanguageSelector'; const App = ({ match }) => ( <div> {/* Language selector */} <LanguageSelector match={match} /> {/* Existing navigation */} <ul> <li> <NavLink to={`${match.url}/`}>Home</NavLink> </li> <li> <NavLink to={`${match.url}/ABC`}>ABC</NavLink> </li> <li> <NavLink to={`${match.url}/DEF`}>DEF</NavLink> </li> </ul> {/* Your page routes */} <Switch> <Route path={`${match.path}/`} exact component={Home} /> <Route path={`${match.path}/ABC`} component={ABC} /> <Route path={`${match.path}/DEF`} component={DEF} /> </Switch> </div> );
Key Notes
- Your existing
NavLinkpatterns will automatically use the new language prefix becausematch.urlreflects the current language-specific route (e.g.,/frinstead of/en). - The utility function handles both routes with existing language parameters and root redirects, ensuring consistency across your app.
- We're using
react-redux-i18n's built-insetLocaleaction to update the language state, which keeps your i18n logic centralized.
内容的提问来源于stack exchange,提问作者Flo Schild

