Guide
Getting started
npm install @devix-labs/arabic-slugify
import { slug } from '@devix-labs/arabic-slugify';
slug('مرحبا بالعالم'); // 'mrhba-balaalm'
slug('مرحبا بالعالم', { script: 'keep' }); // 'مرحبا-بالعالم'
Read this before choosing a mode
Arabic script does not write short vowels. مرحبا is the consonants
m‑r‑h‑b plus a long alef. "marhaba" is not recoverable from it — not by this
library, not by any library, not without a dictionary.
So every romanisation of Arabic looks like this:
| library | مرحبا بالعالم |
|---|---|
| slugify | mrhba-balaalm |
| @sindresorhus/slugify | mrhba-balealm |
| speakingurl | mrhba-balaalm |
Laravel Str::slug |
mrhba-balaaalm |
Five answers, none of which means anything to an Arabic reader or an English one.
Every browser has handled Unicode paths for years, Google indexes them, and they
are percent-encoded on the wire. For Arabic content, /مرحبا-بالعالم is simply a
better URL than any romanisation of it:
slug('المقالة الأولى', { script: 'keep' }); // 'المقالة-الاولي'
script: 'latin' stays the default, because it is what every other library does
and what ASCII-only systems need. But if your readers read Arabic, keep the
script.
import { prefersScript } from '@devix-labs/arabic-slugify';
slug(title, { script: prefersScript(title) ? 'keep' : 'latin' });
When the text is vocalised, the romanisation is good
If an author has written the vowel marks, they are used:
slug('مَرْحَبًا بِالْعَالَمِ'); // 'marhaban-bialaaalami'
slug('مُحَمَّد'); // 'muhammad'
The most used alternative discards the marks entirely and returns mrhba either
way.
Language
slug('میروم به خانه', { lang: 'fa' }); // 'mirum-beh-khaneh'
slug('خوش آمدید', { lang: 'ur', script: 'keep' }); // 'خوش-امدید'
lang is 'ar', 'fa' or 'ur', and it does two things:
- Romanising, it picks the right reading: Persian's و is v at the start of a word and a vowel inside one; a final ه is eh; ث is s rather than th.
- Keeping the script, it decides which spelling to unify towards. Persian and Urdu use ی and ک; Arabic uses ي and ك. Unifying is what stops one article having two URLs — but unifying a Persian slug towards Arabic spells it in letters the language does not use.
The invisible characters
This is where the popular libraries go wrong, and it is worth knowing why.
slug('میروم', { lang: 'fa', script: 'keep' }); // 'میروم' — one word
A zero-width non-joiner is how Persian writes inside a word. Two of the most
downloaded slug libraries turn میروم into my-rwm — two words. The same
happens on a kashida (مرحـــبا), which is a decorative stretch, not a space.
Direction marks are removed too. A right-to-left override can make a URL read as something other than what it is, so it never belongs in one.