🔎 Why Translate URLs?
When building a multilingual React application, translating the visible content is just part of the job. To make your app SEO-friendly and user-centric, you also need to:
- Translate URLs/slugs (e.g.,
/about-us
→ /fr/a-propos
) - Maintain SEO with hreflang for each language
- Improve UX by aligning URLs with user language
- Ensure route accessibility via browser language or manual switching
🚀 What You’ll Learn
- How to structure language-specific routes
- How to integrate URL translation with react-router-dom
- How to switch routes with language changes
- Bonus: how to integrate with react-i18next
⚙️ Setup: Project & Dependencies
Start with a React project (you can use CRA or Vite):
npx create-react-app react-i18n-routing
cd react-i18n-routing
Install necessary dependencies:
npm install react-router-dom i18next react-i18next i18next-browser-languagedetector
📁 Project Structure
/src
/locales
en.json
fr.json
/pages
Home.js
About.js
i18n.js
App.js
routes.js
📘 Step 1: i18n Configuration
Create i18n.js
:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import en from './locales/en.json';
import fr from './locales/fr.json';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: { en: { translation: en }, fr: { translation: fr } },
fallbackLng: 'en',
interpolation: {
escapeValue: false,
},
});
export default i18n;
Sample en.json
:
{
"routes": {
"home": "home",
"about": "about-us"
},
"title": "Welcome to our site!"
}
Sample fr.json
:
{
"routes": {
"home": "accueil",
"about": "a-propos"
},
"title": "Bienvenue sur notre site !"
}
🗺️ Step 2: Create Translatable Routes
Create routes.js
:
import Home from './pages/Home';
import About from './pages/About';
export const routes = (t) => [
{
path: `/${t('routes.home')}`,
element: <Home />,
},
{
path: `/${t('routes.about')}`,
element: <About />,
},
];
🧠 Step 3: Dynamic Routing with react-router-dom
Update App.js
:
import React from 'react';
import { useTranslation } from 'react-i18next';
import { BrowserRouter, Routes, Route, useNavigate } from 'react-router-dom';
import { routes } from './routes';
import './i18n';
const LanguageSwitcher = () => {
const { i18n } = useTranslation();
const navigate = useNavigate();
const switchLang = (lang) => {
const currentPath = window.location.pathname;
const currentPage = currentPath.split('/')[1];
i18n.changeLanguage(lang).then(() => {
// Re-map path using new language
const t = i18n.getFixedT(lang);
const mappedRoutes = {
en: { accueil: 'home', 'a-propos': 'about-us' },
fr: { home: 'accueil', 'about-us': 'a-propos' },
};
const newPath = `/${mappedRoutes[lang][currentPage] || ''}`;
navigate(newPath);
});
};
return (
<div className="lang-switch">
<button onClick={() => switchLang('en')}>EN</button>
<button onClick={() => switchLang('fr')}>FR</button>
</div>
);
};
const App = () => {
const { t } = useTranslation();
return (
<BrowserRouter>
<LanguageSwitcher />
<Routes>
{routes(t).map((route, idx) => (
<Route key={idx} path={route.path} element={route.element} />
))}
</Routes>
</BrowserRouter>
);
};
export default App;
🧩 Step 4: Simple Page Components
Create pages/Home.js
:
import { useTranslation } from 'react-i18next';
export default function Home() {
const { t } = useTranslation();
return (
<div>
<h1>{t('title')}</h1>
</div>
);
}
Create pages/About.js
:
import { useTranslation } from 'react-i18next';
export default function About() {
const { t } = useTranslation();
return (
<div>
<h1>{t('routes.about')}</h1>
</div>
);
}
🌍 Bonus: SEO & Server-Side Considerations
For full SEO benefits in translated URLs:
✅ Use a framework like Next.js for SSR with dynamic routes
✅ Add <html lang="en">
and <link rel="alternate" hreflang="fr">
tags
✅ Translate meta tags using react-helmet
or next/head
✅ Enable proper sitemap and routing strategy per locale
✅ Final Thoughts
Translating URLs in React improves both UX and SEO, especially in 2025 where Google increasingly favors language-aware URLs over query parameters like ?lang=fr
.
With this setup, your app can:
- Dynamically switch between translated URLs
- Support SEO-friendly, localized routing
- Scale to additional languages easily
💡 Next Steps
- Add 404 fallbacks for non-matching paths
- Integrate
i18next-http-backend
to load translations from a CMS - Use language subdomains (e.g.,
fr.site.com
) for region-specific experiences