Fondations
Langues & RTL
اللغات والاتجاه من اليمين إلى اليسار
Locales prises en charge
Déclarées dans src/dsm/i18n/index.ts, chacune avec son code BCP-47, sa direction et son libellé natif.
| Locale | Code | Direction | Libellé natif |
|---|---|---|---|
| fr | fr-MA | ltr | Français |
| ar | ar-MA | rtl | العربية |
| zgh | zgh | ltr | ⵜⴰⵎⴰⵣⵉⵖⵜ |
| en | en | ltr | English |
LocaleProvider, useLocale, useT
LocaleProvider pose la direction (via le DirectionProvider de Base UI) et expose la locale, le code de langue et le dictionnaire courant.
import { LocaleProvider, useLocale, useT } from "@/dsm/i18n/provider";
<LocaleProvider locale="ar">
<Page />
</LocaleProvider>
function Page() {
const { locale, dir, lang } = useLocale(); // "ar", "rtl", "ar-MA"
const t = useT(); // dictionnaire UiStrings courant
return <button aria-label={t.close}>{t.next}</button>;
}Le dictionnaire UiStrings
Un même jeu de clés dans les quatre langues. Ajouter une clé impose de la traduire partout, sans exception.
| Clé | fr | ar | zgh | en |
|---|---|---|---|---|
| kingdom | Royaume du Maroc | المملكة المغربية | ⵜⴰⴳⵍⴷⵉⵜ ⵏ ⵍⵎⵖⵔⵉⴱ | Kingdom of Morocco |
| home | Accueil | الرئيسية | ⵜⴰⵙⵏⴰ ⵜⴰⵎⵣⵡⴰⵔⵓⵜ | Home |
| search | Rechercher | بحث | ⴰⵔⵣⵣⵓ | Search |
| next | Suivant | التالي | ⴰⴹⴼⴰⵕ | Next |
| required | obligatoire | إلزامي | ⵉⵜⵜⵡⴰⵜⵜⵔ | required |
| close | Fermer | إغلاق | ⵔⴳⵍ | Close |
Chiffres, dates et montants
Les conventions marocaines, appliquées par les fonctions de @/dsm/lib/format : chiffres occidentaux dans les trois langues, virgule décimale, dirham en MAD ou د.م., dates grégoriennes avec l'hégirien en complément.
| Locale | Nombre | Montant | Date | Hégirien (indicatif) |
|---|---|---|---|---|
| fr | 1 234 567,89 | 1 250,50 MAD | 17 septembre 2026 | 6 rabia ath-thani 1448 |
| ar | 1 234 567,89 | 1 250,50 د.م. | 17 شتنبر 2026 | 6 ربيع الآخر 1448 |
| zgh | 1 234 567,89 | 1 250,50 MAD | 17 ⵛⵓⵜⴰⵏⴱⵉⵔ 2026 | 6 rabia ath-thani 1448 |
Chiffres occidentaux, partout
En arabe aussi : c'est l'usage de l'administration, de la presse et de l'école au Maroc. Ne forcez jamais les chiffres indo-arabes (nu-arab) ; formatNumber impose nu-latn.
Espace fine et virgule
Milliers séparés par une espace fine insécable, décimales par une virgule, dans les trois langues : « 1 234 567,89 ». Intl seul donnerait un point des milliers en fr-MA.
Dirham : MAD ou د.م.
Code ISO après le montant en français et en amazighe (« 1 250,50 MAD »), symbole د.م. en arabe. Jamais « DH », « Dhs » ni « dh » dans une interface officielle. Deux décimales pour un prix, aucune pour un chiffre-clé.
Dates grégoriennes en toutes lettres
Format long dans la langue de l'interface (17 septembre 2026, 17 شتنبر 2026, 17 ⵛⵓⵜⴰⵏⴱⵉⵔ 2026) ; JJ/MM/AAAA uniquement dans les champs de saisie (DateInput).
Hégirien en complément, jamais seul
formatHijriDate utilise le calendrier islamic-umalqura. Le Maroc suit l'observation lunaire locale : la date calculée peut différer d'un jour, présentez-la comme indicative — « 17 septembre 2026 (6 rabia ath-thani 1448) ».
Téléphone et heures
National « 06 12 34 56 78 », international « +212 6 12 34 56 78 » (IdentityInput, formatPhone). Heures sur 24 h : « 8 h 30 – 16 h 30 ».
import { formatDate, formatDualDate, formatMoney, formatNumber, formatPhone } from "@/dsm/lib/format";
formatNumber(1234567.89, "ar"); // "1 234 567,89"
formatMoney(1250.5, "fr"); // "1 250,50 MAD"
formatMoney(1250.5, "ar"); // "1 250,50 د.م."
formatDate(new Date(), "zgh"); // "17 ⵛⵓⵜⴰⵏⴱⵉⵔ 2026"
formatDualDate(new Date(), "fr"); // "17 septembre 2026 (6 rabia ath-thani 1448)"
formatPhone("+212612345678"); // "06 12 34 56 78"Règles RTL
Un composant DSM ne teste jamais dir === 'rtl' : il s'exprime en propriétés logiques et laisse le navigateur inverser la mise en page.
LTR
RTL
Même classe, même code : le filet de bordure et le retrait passent du côté gauche au côté droit avec la direction.
{/* À éviter */}
<div className="pl-4 pr-2 ml-1 text-left border-l-4" />
{/* À faire */}
<div className="ps-4 pe-2 ms-1 text-start border-s-4" />
{/* Glissement au survol qui respecte le sens de lecture */}
<span className="translate-x-1 rtl:-translate-x-1" />Démonstration trilingue
Basculez la langue dans la barre de l'aperçu : direction, police et contenu changent ensemble, sans recharger la page.
Alerte, bouton et badge
Le composant lit useLocale() et useT() : aucune chaîne n'est écrite en dur.
Information
Ce panneau démontre la mise en page logique : le bouton, le badge et le texte suivent la direction sans code spécifique à la langue.
Ordre de la marque nationale
Sur les supports officiels, les trois lignes du nom du Royaume suivent toujours cet ordre, quelle que soit la langue de l'interface.
- 1المملكة المغربيةar
- 2ⵜⴰⴳⵍⴷⵉⵜ ⵏ ⵍⵎⵖⵔⵉⴱzgh
- 3Royaume du Marocfr
Recommandations pour le tifinaghe
Noto Sans Tifinagh n'est chargée qu'en une seule graisse : la hiérarchie visuelle passe par la taille et l'espacement, jamais par le gras.
Traductions amazighes : relecture en attente
Une seule graisse
Noto Sans Tifinagh est chargée en poids 400 uniquement (font-tifinagh) : n'appliquez jamais font-bold à du texte tifinaghe, il n'a aucun effet et casse la cohérence.
Tracking élargi
Ajoutez tracking-wide sur les lignes tifinaghes pour compenser la densité des glyphes, comme le fait BlockMark sur la ligne zgh.
Relecture d'une page en RTL
- Basculer dir="rtl" et vérifier qu'aucun texte ni contrôle ne déborde ou ne se chevauche.
- Vérifier que les flèches et chevrons directionnels s'inversent, et que Check, X et ExternalLink restent fixes.
- Chercher dans le diff toute classe pl-/pr-/ml-/mr-/left-/right-/text-left/text-right : elles doivent disparaître au profit des classes logiques.
- Vérifier que les glissements au survol utilisent rtl:-translate-x-* et non une valeur codée en dur.
- Aligner le texte avec text-start / text-end plutôt qu'avec un côté physique.
- Vérifier l'ordre de la marque nationale (arabe, tifinaghe, français) et son alignement à droite.
- Parcourir la page au clavier : l'ordre de tabulation doit suivre l'ordre visuel RTL.
- Relire le rendu de l'amazighe tifinaghe : une seule graisse, un tracking élargi.
Le direction provider est unique
LocaleProvider intègre déjà le DirectionProvider de Base UI : n'en ajoutez pas un second dans une page ou un composant.