Développement Web

Tutoriel : Créer un site multilingue (français/arabe)

10 min de lecture

Prérequis

  • Niveau : bases HTML/CSS, notion de Flexbox/Grid.
  • Outils : VS Code + Live Server, navigateur moderne (testez avec et sans dir="rtl").
  • Temps estimé : 1 h 30.

Pourquoi un site bilingue FR/AR ?

Au Sénégal et plus largement en Afrique de l’Ouest et au Maghreb, l’arabe est largement compris. Un site bilingue multiplie votre audience et démontre une attention culturelle. Mais l’arabe étant RTL (right-to-left), il ne suffit pas de traduire : il faut adapter toute la mise en page.

Les défis d’un site bilingue français/arabe

Créer un site multilingue ne se limite pas à traduire le texte. L’arabe est une langue RTL (Right-to-Left) qui s’écrit de droite à gauche, ce qui impacte toute la mise en page : les menus passent à droite, les icônes s’inversent, les marges changent de côté. Ce tutoriel vous montre comment gérer le RTL proprement avec HTML et CSS, et comment structurer un site bilingue français/arabe.

Étape 1 : la base HTML avec l’attribut dir

<!-- Page en français (LTR par défaut) -->
<html lang="fr" dir="ltr">

<!-- Page en arabe (RTL) -->
<html lang="ar" dir="rtl">

L’attribut dir="rtl" inverse automatiquement :

  • L’alignement du texte (de gauche à droite → droite à gauche)
  • L’ordre des éléments en Flexbox et Grid
  • Les propriétés CSS margin-inline-start, padding-inline-end, etc.

Étape 2 : CSS avec les propriétés logiques

Les propriétés CSS « logiques » s’adaptent automatiquement au sens de lecture. Utilisez-les à la place des propriétés physiques :

/* ❌ ANCIEN — Ne s'adapte PAS au RTL */
.card {
  margin-left: 20px;
  padding-right: 16px;
  text-align: left;
  border-left: 3px solid blue;
}

/* ✅ NOUVEAU — S'adapte automatiquement au RTL */
.card {
  margin-inline-start: 20px;     /* gauche en LTR, droite en RTL */
  padding-inline-end: 16px;      /* droite en LTR, gauche en RTL */
  text-align: start;              /* gauche en LTR, droite en RTL */
  border-inline-start: 3px solid blue;
}

Table de correspondance

Propriété physique Propriété logique
margin-left margin-inline-start
margin-right margin-inline-end
padding-left padding-inline-start
padding-right padding-inline-end
text-align: left text-align: start
float: left float: inline-start
left: 0 inset-inline-start: 0
width inline-size
height block-size

Étape 3 : Flexbox et Grid en RTL

Bonne nouvelle : Flexbox et Grid s’inversent automatiquement avec dir="rtl".

/* Ce CSS fonctionne dans les deux sens sans modification */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* En LTR : logo à gauche, liens à droite */
/* En RTL : logo à droite, liens à gauche */
/* AUTOMATIQUE — rien à changer */

Étape 4 : Inverser les icônes directionnelles

Les icônes qui indiquent une direction doivent être inversées en RTL :

/* Inverser les flèches et icônes directionnelles */
[dir="rtl"] .icon-arrow,
[dir="rtl"] .icon-chevron,
[dir="rtl"] .icon-back {
  transform: scaleX(-1);
}

/* NE PAS inverser : les icônes non-directionnelles */
/* ✓ Horloge, téléphone, email, recherche → restent identiques */
/* ✕ Flèche retour, chevron suivant, progress bar → à inverser */

Étape 5 : le switch de langue

<nav class="lang-switch">
  <a href="/fr/" class="actif">Français</a>
  <a href="/ar/">العربية</a>
</nav>
.lang-switch {
  display: flex;
  gap: 8px;
}

.lang-switch a {
  padding: 6px 16px;
  border: 1px solid #ddd;
  border-radius: 20px;
  text-decoration: none;
  color: #333;
}

.lang-switch a.actif {
  background: #4a90d9;
  color: white;
  border-color: #4a90d9;
}

Étape 6 : les polices pour l’arabe

/* Police système pour l'arabe */
[dir="rtl"] body {
  font-family: 'Noto Sans Arabic', 'Segoe UI', Tahoma, sans-serif;
  line-height: 1.8; /* L'arabe nécessite plus d'interligne */
}

/* Google Fonts pour l'arabe */
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@400;700&display=swap" rel="stylesheet">

Polices arabes recommandées : Noto Sans Arabic (Google, gratuite), Cairo, Tajawal, IBM Plex Sans Arabic.

Approche JavaScript pour le switch dynamique

function setLanguage(lang) {
  const html = document.documentElement;
  
  if (lang === 'ar') {
    html.setAttribute('dir', 'rtl');
    html.setAttribute('lang', 'ar');
  } else {
    html.setAttribute('dir', 'ltr');
    html.setAttribute('lang', 'fr');
  }
  
  // Sauvegarder la préférence
  localStorage.setItem('lang', lang);
}

// Au chargement, restaurer la langue
const savedLang = localStorage.getItem('lang') || 'fr';
setLanguage(savedLang);

Erreurs fréquentes

Mise en page cassée en arabe

Cause : usage de margin-left/padding-right physiques au lieu des propriétés logiques.
Solution : utilisez exclusivement margin-inline-start/end, padding-inline-start/end, text-align: start/end. Tout s’inverse automatiquement avec dir="rtl".

Icônes directionnelles non inversées

Cause : les flèches « suivant » pointent toujours à droite, même en arabe (où le sens est inversé).
Solution : ciblez avec [dir="rtl"] .icon-arrow { transform: scaleX(-1); }. Ne touchez PAS aux icônes neutres (recherche, téléphone, email).

Polices latines moches en arabe

Cause : on garde 'Segoe UI' qui rend mal les caractères arabes.
Solution : chargez une police adaptée (Noto Sans Arabic, Cairo, Tajawal, IBM Plex Sans Arabic) et augmentez line-height à 1.7-1.9.

SEO multilingue oublié

Cause : Google ne sait pas quelle langue indexer pour quel public.
Solution : ajoutez <link rel="alternate" hreflang="fr" href="..." /> et hreflang="ar" dans le <head> de chaque page.

Exercice

  1. Créez une page avec un header, une section hero et 3 cartes de services
  2. Utilisez uniquement des propriétés CSS logiques
  3. Ajoutez un bouton de switch FR/AR qui change dir et lang
  4. Vérifiez que la mise en page s’inverse correctement
  5. Ajoutez les polices Google Fonts appropriées pour chaque langue

À lire ensuite

Cadrer le projet bilingue avant d’ouvrir le code

Avant la première ligne de code, posez par écrit la liste des langues, la langue par défaut, le comportement attendu pour un visiteur sans préférence et la politique de fallback quand une traduction manque. Pour le couple français-arabe, le piège classique est de traiter l’arabe comme une simple traduction du français : c’est en réalité une seconde mise en page complète, avec direction de lecture, ponctuation, chiffres et typographie spécifiques. À Dakar, Abidjan ou Conakry, la même page peut être consultée en 3G dégradée puis en fibre, donc chaque arbitrage technique pèse sur l’expérience réelle.

Documentez aussi votre cible métier : un site institutionnel sénégalais aura besoin du FCFA (1 EUR = 655,957 FCFA, parité fixe), d’un numéro Orange/Mixx by Yas pour le contact, et probablement d’une version arabe destinée à la diaspora golfe. Cette note de cadrage évite les allers-retours coûteux en phase de tests.

Étape 1 — Choisir une stratégie d’URL stable

Trois schémas existent : sous-répertoire (/fr/, /ar/), sous-domaine (fr.example.com, ar.example.com) ou domaines séparés. Pour un site bilingue francophone-arabe destiné à l’Afrique de l’Ouest et au Maghreb, le sous-répertoire reste le meilleur compromis SEO : un seul domaine concentre l’autorité, les redirections sont triviales, et Google gère parfaitement les variantes via hreflang.

https://example.sn/fr/produits/abonnement
https://example.sn/ar/المنتجات/الاشتراك

Ne mélangez jamais les deux schémas dans la même section. Si vous partez sur /fr/ et /ar/, le rendre obligatoire pour 100 % des URLs publiques, y compris la racine qui doit rediriger en 302 vers la langue détectée.

Étape 2 — Déclarer la direction RTL au niveau HTML

L’arabe se lit de droite à gauche. Cela ne se règle pas en CSS, mais directement sur la balise racine du document. Sans cette déclaration, le navigateur applique la direction par défaut LTR et casse l’alignement des listes, des formulaires et des icônes.

<!-- Page française -->
<html lang="fr" dir="ltr">
<!-- Page arabe -->
<html lang="ar" dir="rtl">

Vérifiez ensuite dans l’inspecteur Chrome qu’aucun parent n’écrase l’attribut dir. Si vous utilisez un framework, exposez la direction comme variable globale plutôt qu’en dur dans un layout.

Étape 3 — Créer une feuille CSS dédiée RTL avec logical properties

Plutôt que de dupliquer toute votre CSS, basculez sur les propriétés logiques modernes. Elles s’adaptent automatiquement à la direction du document et évitent un fichier rtl.css de plusieurs centaines de lignes à maintenir.

/* Au lieu de margin-left, padding-right, etc. */
.card { margin-inline-start: 1rem; padding-inline: 1.25rem; }
.btn  { border-inline-end: 2px solid #0a5; }
.menu { text-align: start; }

Cette approche divise par trois le volume de CSS spécifique. Elle est supportée par tous les navigateurs modernes (Chrome 87+, Firefox 66+, Safari 15+), donc parfaitement fiable pour un public ouest-africain équipé majoritairement de Chrome Android récent.

Étape 4 — Charger les bonnes polices arabes

Les polices latines ne contiennent pas tous les glyphes arabes nécessaires. Sans police dédiée, le navigateur retombe sur une police système (souvent Tahoma sous Windows, Geeza Pro sous macOS) avec un rendu inégal. Optez pour Noto Sans Arabic ou Cairo via Google Fonts, ou auto-hébergez-les pour réduire la latence.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700&display=swap" rel="stylesheet">

html[lang="ar"] body { font-family: "Cairo", sans-serif; line-height: 1.8; }
html[lang="fr"] body { font-family: "Inter", sans-serif; line-height: 1.6; }

Augmentez systématiquement la line-height en arabe : les diacritiques (harakat) et les liaisons de caractères demandent davantage d’espace vertical pour rester lisibles.

Étape 5 — Internationaliser les chaînes avec un fichier de traduction

Sortez tout texte du HTML et placez-le dans des fichiers JSON séparés par langue. Cette discipline évite les oublis quand vous ajoutez une nouvelle page et permet à un traducteur arabophone de travailler sans toucher au code.

// locales/fr.json
{ "nav": { "home": "Accueil", "pricing": "Tarifs" } }

// locales/ar.json
{ "nav": { "home": "الرئيسية", "pricing": "الأسعار" } }

Côté code, utilisez i18next, vue-i18n, react-intl ou next-intl selon votre stack. La sortie attendue : aucune chaîne en dur dans les composants, et un script de validation qui hurle si une clé existe en français mais pas en arabe.

Étape 6 — Localiser les chiffres, dates et la monnaie

Les chiffres arabes orientaux (٠١٢٣٤٥٦٧٨٩) sont attendus par une partie du lectorat du Golfe, mais la diaspora maghrébine et ouest-africaine utilise les chiffres latins. Tranchez selon votre cible et restez cohérent.

const prix = 19500; // FCFA
new Intl.NumberFormat('fr-SN', { style:'currency', currency:'XOF' }).format(prix);
// "19 500 F CFA"
new Intl.NumberFormat('ar-EG', { style:'currency', currency:'EGP' }).format(prix);

Pour un site sénégalais, affichez le FCFA en français (XOF) et basculez en dirham marocain ou riyal saoudien selon le pays détecté pour la version arabe. L’API Intl du navigateur fait tout le travail de formatage sans dépendance externe.

Étape 7 — Déclarer hreflang pour Google et Bing

Sans balises hreflang, Google peut servir la page française à un internaute saoudien et inversement. Ajoutez ces balises dans le <head> de chaque page, en pointant les deux variantes plus une version x-default de fallback.

<link rel="alternate" hreflang="fr" href="https://example.sn/fr/produits">
<link rel="alternate" hreflang="ar" href="https://example.sn/ar/المنتجات">
<link rel="alternate" hreflang="x-default" href="https://example.sn/fr/produits">

Vérifiez ensuite dans Google Search Console > Paramètres internationaux que les deux langues sont bien détectées sans erreur de réciprocité. Ce contrôle prend deux minutes et évite des semaines de ranking médiocre.

Étape 8 — Tester sur mobile bas de gamme avant la mise en ligne

Le test ultime : ouvrez votre site dans Chrome DevTools > émulateur Galaxy A14 ou Tecno Spark, throttling 3G, et naviguez en arabe. Vérifiez que les icônes flèches sont retournées (un < devient >), que les marges respirent, que les formulaires alignent les labels à droite et que le menu burger s’ouvre du bon côté.

Lancez aussi un audit Lighthouse sur les deux versions linguistiques séparément. Une page arabe peut être plus lourde de 80 à 120 Ko à cause des polices : compressez en woff2, déclarez font-display: swap et préchargez uniquement les graisses utilisées au-dessus de la ligne de flottaison. Un score performance supérieur à 85 sur Galaxy A14 reste votre objectif minimum avant publication.

Partager