Skip to content
Devix Open Source

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.

Where to go next

Updated 15 Sep 2026