DeveloperBreeze

🔎 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

Continue Reading

Discover more amazing content handpicked just for you

Tutorial

How to Stop SSH From Timing Out

Edit the SSH daemon config:

sudo nano /etc/ssh/sshd_config

Aug 21, 2025
Read More
Tutorial

Globalization in React (2025 Trends & Best Practices)

  • 🇪🇺 GDPR requires local-language privacy policies
  • 🇨🇳 China's Cybersecurity Law needs local hosting + Mandarin support
  • 🇸🇦 Saudi localization laws mandate Arabic for all government services

Your React app must support legal localization where applicable.

May 04, 2025
Read More
Tutorial

Implementing Internationalization (i18n) in a Large React Application (2025 Guide)

In component:

const { t } = useTranslation('dashboard');

May 04, 2025
Read More
Tutorial

Building Micro-Frontends with Webpack Module Federation (2025 Guide)

In webpack.config.js of app-shell:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
const path = require('path');

module.exports = {
  mode: 'development',
  devServer: {
    port: 8080,
  },
  entry: './src/bootstrap.js',
  output: {
    publicPath: 'http://localhost:8080/',
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'app_shell',
      remotes: {
        analytics_app: 'analytics_app@http://localhost:8081/remoteEntry.js',
      },
      shared: require('./package.json').dependencies,
    }),
    new HtmlWebpackPlugin({ template: './public/index.html' }),
  ],
};

May 04, 2025
Read More
Tutorial

State Management Beyond Redux: Using Zustand for Scalable React Apps

Zustand is a small, fast, and scalable state management solution for React applications. Developed by the creators of Jotai and React-spring, Zustand aims to provide a minimalistic API based on hooks, eliminating the need for boilerplate code and context providers.

Key Features:

May 03, 2025
Read More
Tutorial

Mastering React Rendering Performance with Memoization and Context

import React, { useState, useMemo } from 'react';

function ExpensiveComponent({ data }) {
  const processedData = useMemo(() => {
    // Expensive computation
    return data.map(item => /* processing */ item);
  }, [data]);

  return <div>{/* render processedData */}</div>;
}

This approach ensures that the expensive computation runs only when data changes, improving performance.

May 03, 2025
Read More
Tutorial

✅ How to Disable MySQL Password Validation on Ubuntu 25.04

This should now work without any errors.

If you want to bring back strong password policies:

May 01, 2025
Read More
Tutorial

How to Move the MySQL Data Directory to a New Location on Ubuntu 25.04

By default, MySQL stores all its data in /var/lib/mysql. This tutorial explains how to safely move the MySQL data directory to a new location (e.g., another disk or partition) on Ubuntu 25.04.

Before making any changes, stop the MySQL service:

May 01, 2025
Read More
Tutorial

How to Install PHP, MySQL, and phpMyAdmin on Ubuntu 25.04 (LAMP Stack Setup Guide)

You can now access phpMyAdmin at http://localhost/phpmyadmin.

If you're using Apache and want to set up a virtual host for your Laravel application:

May 01, 2025
Read More
Tutorial

How to Fix NVIDIA Driver Issues on Ubuntu (Dell Vostro 3521)

Launch apps like this:

prime-run firefox
prime-run blender
prime-run vlc

Apr 14, 2025
Read More
Tutorial

Avoiding Memory Leaks in C++ Without Smart Pointers

void legacyFunction(char* data);

void useLegacyAPI() {
    ScopedArray<char> buffer(new char[512]);
    legacyFunction(buffer.get());
}

Even without smart pointers, you can manage memory safely in C++ using the RAII pattern. This approach:

Apr 11, 2025
Read More
Tutorial

Deep Copy in C++: How to Avoid Shallow Copy Pitfalls

Shallow a(10);
Shallow b = a;  // default copy constructor

This causes both a.data and b.data to point to the same memory. When both destructors run, delete is called twice on the same pointer — undefined behavior!

Apr 11, 2025
Read More
Tutorial

🛡️ Protect Your Forms Like a Pro: Anti-Spam Techniques That Actually Work

  • express-rate-limit (Node.js)
  • Laravel's built-in throttling

Check for suspicious content:

Apr 04, 2025
Read More
Tutorial

Build a Custom Rate Limiter in Node.js with Redis

// server.js
require("dotenv").config();
const express = require("express");
const rateLimiter = require("./rateLimiter");

const app = express();
const PORT = 3000;

app.use(rateLimiter(100, 3600)); // 100 requests/hour per IP

app.get("/", (req, res) => {
  res.send("Welcome! You're within rate limit.");
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

Use Postman or curl:

Apr 04, 2025
Read More
Tutorial
javascript

Building a Real-Time Object Detection Web App with TensorFlow.js and p5.js

  • A modern web browser that supports webcam access (Chrome, Firefox, or Edge).
  • Basic knowledge of HTML, CSS, and JavaScript.
  • Familiarity with p5.js (optional, but helpful).
  • A code editor (Visual Studio Code, Sublime Text, etc.).

You do not need any backend setup since everything runs in the browser using TensorFlow.js and p5.js.

Feb 12, 2025
Read More
Tutorial

Building a Cross-Platform Desktop App with Tauri and Svelte: A Step-by-Step Tutorial

Edit your Svelte components in the src folder. Open src/App.svelte and modify it to add your custom UI. For example:

<script>
  let count = 0;
  const increment = () => count += 1;
</script>

<main>
  <h1>Welcome to Tauri + Svelte Desktop App</h1>
  <p>Current count: {count}</p>
  <button on:click={increment}>Increment</button>
</main>

<style>
  main {
    text-align: center;
    padding: 2rem;
    font-family: Arial, sans-serif;
  }
  button {
    margin-top: 1rem;
    padding: 0.5rem 1rem;
    font-size: 1rem;
  }
</style>

Feb 12, 2025
Read More
Tutorial

Implementing a Domain-Specific Language (DSL) with LLVM and C++

#ifndef DSL_PARSER_H
#define DSL_PARSER_H

#include "Lexer.h"
#include "AST.h"
#include <memory>

class Parser {
public:
    Parser(Lexer& lexer);
    std::unique_ptr<ASTNode> parseExpression();

private:
    Lexer& lexer;
    Token currentToken;

    void eat(TokenType type);
    std::unique_ptr<ASTNode> factor();
    std::unique_ptr<ASTNode> term();
};

#endif // DSL_PARSER_H

Implementation: Parser.cpp

Feb 12, 2025
Read More
Tutorial
python

دليل عملي: بناء روبوت دردشة (Chatbot) باستخدام Python و NLP

حان وقت التفاعل مع الروبوت:

print("روبوت الدردشة: مرحباً! اكتب 'وداعاً' للخروج.")

while True:
    user_input = input("أنت: ")
    if "وداعاً" in user_input:
        print("روبوت الدردشة: وداعاً!")
        break
    response = chatbot_response(user_input)
    print(f"روبوت الدردشة: {response}")

Dec 12, 2024
Read More
Tutorial
python

كيف تبدأ رحلتك مع الذكاء الاصطناعي: دليل عملي للمبتدئين

ابدأ باستكشاف الشبكات العصبية وخوارزميات التعلم العميق.

3. هل يمكنني تطبيق الذكاء الاصطناعي في مشروعي الحالي؟

Dec 12, 2024
Read More
Tutorial
dart

دليل شامل: تطوير تطبيقات باستخدام إطار العمل Flutter

  • سيعرض هذا الأمر قائمة بالأدوات المطلوبة. أكمل تثبيت أي أدوات مفقودة.

استخدم الأمر التالي لإنشاء مشروع جديد:

Dec 12, 2024
Read More

Discussion 0

Please sign in to join the discussion.

No comments yet. Start the discussion!