digitaltunnel/arabic-toolkit

Arabic name transliteration and money-to-words conversion for Laravel.

Maintainers

Package info

github.com/digital-tunnel/arabic-toolkit

pkg:composer/digitaltunnel/arabic-toolkit

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.0.0 2026-04-03 23:50 UTC

This package is auto-updated.

Last update: 2026-04-03 23:57:01 UTC


README

Arabic Toolkit

Latest Version PHP Version License

Arabic Toolkit

The definitive Arabic language toolkit for Laravel -- transliteration, money-to-words, Hijri dates, and 9 more services for building Arabic applications.

1,200+ curated Arabic names, 12 currencies, 3 dialects, smart vowel insertion, and zero external dependencies.

Table of Contents

Requirements

Dependency Version
PHP ^8.2
Laravel 11.x, 12.x, 13.x

Installation

composer require digitaltunnel/arabic-toolkit

The package auto-discovers its service provider and facade. No manual registration needed.

Publish Configuration (optional)

php artisan vendor:publish --tag=arabic-toolkit-config

This publishes config/arabic-toolkit.php where you can set application-wide defaults.

Quick Start

use DigitalTunnel\ArabicToolkit\Facades\ArabicToolkit;

// Transliterate Arabic names to English
ArabicToolkit::transliterate('حسام الشهري');
// "Hossam Al Shehri"

// Convert money to words
ArabicToolkit::moneyToWords(1500.50, 'EGP');
// "One Thousand Five Hundred Egyptian Pounds and Fifty Piastres"

// Convert to Arabic words
ArabicToolkit::moneyToWords(1500, 'EGP', locale: 'ar');
// "ألف وخمسمائة جنيه مصري"

// Hijri date
ArabicToolkit::toHijri('2026-04-04')->format('j F Y', 'ar');
// "١٦ شوال ١٤٤٧"

// Arabic slug for URLs
ArabicToolkit::slug('مقالة عن البرمجة');
// "مقالة-عن-البرمجة"

// Detect gender from name
ArabicToolkit::detectGender('فاطمة');
// "female"

Configuration

After publishing, edit config/arabic-toolkit.php:

return [
    'dialect'          => 'egyptian',   // 'egyptian', 'levantine', 'gulf'
    'capitalize'       => true,
    'default_currency' => 'EGP',
    'ta_marbuta'       => 'a',          // 'a', 'ah', 'et'

    'money' => [
        'append_only'  => false,        // Add "Only" / "فقط" suffix
        'locale'       => 'en',         // 'en' or 'ar'
    ],
];

All options can be overridden per-call via method parameters.

Services

1. Arabic Name Transliteration

Convert Arabic names to their English phonetic equivalents using a hybrid two-tier system:

  • Tier 1: Dictionary of 1,200+ curated common names
  • Tier 2: Smart character-by-character fallback with vowel insertion
// Dictionary matches (exact + fuzzy)
ArabicToolkit::transliterate('حسام');        // "Hossam"
ArabicToolkit::transliterate('محمد أحمد');   // "Mohammed Ahmed"
ArabicToolkit::transliterate('عبدالله');     // "Abdullah"
ArabicToolkit::transliterate('عبد الله');    // "Abdullah" (space variant)

// Family names with "ال" prefix
ArabicToolkit::transliterate('الشهري');       // "Al Shehri"
ArabicToolkit::transliterate('القحطاني');     // "Al Qahtani"
ArabicToolkit::transliterate('حسام الشهري'); // "Hossam Al Shehri"

// Particle words
ArabicToolkit::transliterate('محمد بن علي');  // "Mohammed Bin Ali"
ArabicToolkit::transliterate('أبو بكر');     // "Abu Bakr"

// Dialect support
ArabicToolkit::transliterate('جمال', 'levantine'); // "Jamal" (not "Gamal")

Smart features:

Feature Example
Fuzzy matching (ى ↔ ي) مصطفي → Mostafa (finds مصطفى)
Fuzzy matching (أ ↔ ا) احمد → Ahmed (finds أحمد)
Compound joining عبد + الله → Abdullah
Smart vowel insertion الشهري → Al Shehri (not "Alshhry")
"ال" prefix handling Always "Al " for names (no sun-letter assimilation)

Supported dialects:

Dialect ج ق Example
Egyptian (default) g q جمال → Gamal
Levantine j ' جمال → Jamal
Gulf j g جمال → Jamal

2. Money to Words

Convert numeric amounts to written words with full currency support:

// English output
ArabicToolkit::moneyToWords(1500.50, 'EGP');
// "One Thousand Five Hundred Egyptian Pounds and Fifty Piastres"

ArabicToolkit::moneyToWords(1, 'USD');
// "One US Dollar"

ArabicToolkit::moneyToWords(2500, 'SAR');
// "Two Thousand Five Hundred Saudi Riyals"

// Arabic output
ArabicToolkit::moneyToWords(1500.50, 'EGP', locale: 'ar');
// "ألف وخمسمائة جنيه مصري وخمسون قرش"

// "Only" suffix for checks and invoices
ArabicToolkit::moneyToWords(1500, 'EGP', appendOnly: true);
// "One Thousand Five Hundred Egyptian Pounds Only"

ArabicToolkit::moneyToWords(1500, 'EGP', appendOnly: true, locale: 'ar');
// "ألف وخمسمائة جنيه مصري فقط"

// 3-decimal currencies
ArabicToolkit::moneyToWords(1.001, 'KWD');
// "One Kuwaiti Dinar and One Fils"

Supported currencies (12):

Code Currency Fractional Unit Decimals
EGP Egyptian Pound Piastre 2
SAR Saudi Riyal Halala 2
AED UAE Dirham Fils 2
USD US Dollar Cent 2
EUR Euro Cent 2
GBP British Pound Penny/Pence 2
KWD Kuwaiti Dinar Fils 3
QAR Qatari Riyal Dirham 2
BHD Bahraini Dinar Fils 3
OMR Omani Rial Baisa 3
JOD Jordanian Dinar Fils 3
LBP Lebanese Pound Piastre 2

All currencies include Arabic names with proper grammar (singular/dual/plural).

3. Text Utilities

Essential Arabic text processing operations:

// Remove diacritics (harakat)
ArabicToolkit::removeHarakat('الحَمْدُ لِلَّهِ');
// "الحمد لله"

// Normalize alef variants (أ إ آ → ا)
ArabicToolkit::normalizeAlef('أحمد إبراهيم آدم');
// "احمد ابراهيم ادم"

// Convert digits (Western ↔ Eastern)
ArabicToolkit::toEasternDigits('2026');  // "٢٠٢٦"
ArabicToolkit::toWesternDigits('٢٠٢٦'); // "2026"

// Detect Arabic text
ArabicToolkit::isArabic('حسام');   // true
ArabicToolkit::isArabic('Hello');  // false

// Remove tatweel/kashida
ArabicToolkit::removeTatweel('حـــسام'); // "حسام"

4. Arabic Slug Generator

Generate URL-friendly slugs from Arabic text -- unlike Laravel's Str::slug() which destroys Arabic characters:

ArabicToolkit::slug('مقالة عن البرمجة');
// "مقالة-عن-البرمجة"

ArabicToolkit::slug('أحمد إبراهيم');
// "احمد-ابراهيم" (normalizes alef variants)

ArabicToolkit::slug('مقالة عن PHP');
// "مقالة-عن-php" (mixed Arabic/English)

// Transliterated slug (Latin characters)
ArabicToolkit::slug('مقالة عن البرمجة', transliterate: true);
// "maqala-an-albarmaja"

Automatically removes harakat, normalizes alef, removes tatweel, collapses whitespace, and handles mixed-language text.

5. Search Normalization

Full normalization pipeline for Arabic text search indexing. Ensures that "أحمد", "احمد", "أَحْمَد" all match:

ArabicToolkit::normalizeForSearch('أحمد مُحَمَّد');
// "احمد محمد"

The pipeline applies (in order):

  1. Remove harakat (diacritics)
  2. Normalize alef variants (أ إ آ → ا)
  3. Normalize ta marbuta (ة → ه)
  4. Normalize ya maqsura (ى → ي)
  5. Remove tatweel
  6. Normalize digits (Eastern → Western)
  7. Collapse whitespace

Individual steps are also available:

ArabicToolkit::normalizeTaMarbuta('فاطمة');  // "فاطمه"
ArabicToolkit::normalizeYaMaqsura('مصطفى'); // "مصطفي"

Laravel Scout integration:

// In your model's toSearchableArray()
public function toSearchableArray()
{
    return [
        'name' => ArabicToolkit::normalizeForSearch($this->name),
        'bio'  => ArabicToolkit::normalizeForSearch($this->bio),
    ];
}

6. Arabic Pluralization

Arabic has one of the most complex pluralization systems: singular, dual, plural (3-10), and singular again (11+). This service handles it:

ArabicToolkit::pluralize(0, 'ملف', 'ملفان', 'ملفات');
// "٠ ملفات"

ArabicToolkit::pluralize(1, 'رسالة', 'رسالتان', 'رسائل');
// "رسالة"

ArabicToolkit::pluralize(2, 'ملف', 'ملفان', 'ملفات');
// "ملفان"

ArabicToolkit::pluralize(5, 'ملف', 'ملفان', 'ملفات');
// "٥ ملفات"

ArabicToolkit::pluralize(15, 'ملف', 'ملفان', 'ملفات');
// "١٥ ملف"

Get just the word form without the number:

ArabicToolkit::pluralForm(5, 'ملف', 'ملفان', 'ملفات');
// "ملفات"

Arabic pluralization rules:

Count Form Used
0 Plural
1 Singular (no number shown)
2 Dual (no number shown)
3-10 Plural (جمع قلة)
11+ Singular (تمييز)

7. Hijri Date Converter

Convert between Gregorian and Hijri (Islamic) calendar dates:

// Gregorian → Hijri
$hijri = ArabicToolkit::toHijri('2026-04-04');
$hijri->format('j F Y');        // "16 Shawwal 1447"
$hijri->format('j F Y', 'ar');  // "١٦ شوال ١٤٤٧"
$hijri->format('d/m/Y');        // "16/10/1447"

// Access components
$hijri->day;                    // 16
$hijri->month;                  // 10
$hijri->year;                   // 1447
$hijri->monthName('en');        // "Shawwal"
$hijri->monthName('ar');        // "شوال"

// Hijri → Gregorian
$gregorian = ArabicToolkit::fromHijri(16, 10, 1447);
// ['year' => 2026, 'month' => 4, 'day' => 4]

// Today in Hijri
$today = ArabicToolkit::hijriToday();

Format tokens:

Token Output Example
j Day (1-30) 7
d Day with leading zero 07
n Month (1-12) 10
m Month with leading zero 10
F Month name Shawwal / شوال
Y Year (4 digits) 1447

Hijri month names:

# English Arabic
1 Muharram محرم
2 Safar صفر
3 Rabi al-Awwal ربيع الأول
4 Rabi al-Thani ربيع الثاني
5 Jumada al-Ula جمادى الأولى
6 Jumada al-Thani جمادى الآخرة
7 Rajab رجب
8 Sha'ban شعبان
9 Ramadan رمضان
10 Shawwal شوال
11 Dhul Qi'dah ذو القعدة
12 Dhul Hijjah ذو الحجة

8. Gender Detection

Detect the gender of an Arabic name using dictionary lookup + morphological analysis:

ArabicToolkit::detectGender('محمد');    // "male"
ArabicToolkit::detectGender('فاطمة');   // "female"
ArabicToolkit::detectGender('إحسان');  // "unisex"
ArabicToolkit::detectGender('نور');     // "unisex"

Detection layers:

  1. Dictionary lookup -- checks against known male/female/unisex names
  2. Morphological rules:
    • Ta marbuta (ة) ending → female
    • Alef maqsura (ى) ending → female
    • اء ending → female (أسماء, شيماء, زهراء)
    • Default → male

9. Number Formatting

Format numbers with Eastern Arabic digits, separators, and ordinals:

// Eastern Arabic digit formatting
ArabicToolkit::formatNumber(1234567.89);
// "١٬٢٣٤٬٥٦٧٫٨٩"

ArabicToolkit::formatNumber(1234567.89, decimals: 0);
// "١٬٢٣٤٬٥٦٨"

// Percentage
ArabicToolkit::formatPercentage(0.157);
// "١٥٫٧٪"

// Ordinals (1st-10th with gender)
ArabicToolkit::ordinal(1);             // "الأول"
ArabicToolkit::ordinal(3);             // "الثالث"
ArabicToolkit::ordinal(1, 'female');   // "الأولى"
ArabicToolkit::ordinal(3, 'female');   // "الثالثة"

Ordinals (masculine/feminine):

# Male Female
1 الأول الأولى
2 الثاني الثانية
3 الثالث الثالثة
4 الرابع الرابعة
5 الخامس الخامسة
6 السادس السادسة
7 السابع السابعة
8 الثامن الثامنة
9 التاسع التاسعة
10 العاشر العاشرة

10. Keyboard Layout Converter

Fix text typed with the wrong keyboard layout active -- a very common issue in Arabic applications:

// English keys typed on Arabic keyboard → Arabic
ArabicToolkit::fixKeyboard('pshl');
// "حسام"

// Arabic keys typed on English keyboard → English
ArabicToolkit::fixKeyboard('حسام', 'ar_to_en');
// "pshl"

// Auto-detect direction
ArabicToolkit::fixKeyboard('pshl');      // Arabic detected → "حسام"
ArabicToolkit::fixKeyboard('حسام');       // English detected → "pshl"

// Get both variants for search
ArabicToolkit::searchVariants('pshl');
// ['original' => 'pshl', 'swapped' => 'حسام']

Useful for search boxes where users forget to switch keyboard layout.

11. BiDi Text Helpers

Handle bidirectional text issues when mixing Arabic (RTL) and English (LTR):

// Detect text direction
ArabicToolkit::textDirection('مرحبا بالعالم');   // "rtl"
ArabicToolkit::textDirection('Hello World');      // "ltr"

// Fix BiDi display issues (wraps LTR segments with Unicode marks)
ArabicToolkit::bidi('اتصل على 0501234567');
// Wraps phone number with LRM marks to prevent reversal

12. Arabic Greeting Generator

Generate contextually correct, gender-aware Arabic greetings:

// Time-aware greeting (morning/evening)
ArabicToolkit::greeting('محمد');
// "صباح الخير يا محمد" (morning) or "مساء الخير يا محمد" (evening)

// Formal salutation for letters/emails
ArabicToolkit::salutation('محمد', 'male');
// "السيد محمد المحترم"

ArabicToolkit::salutation('فاطمة', 'female');
// "السيدة فاطمة المحترمة"

// Welcome message with gender-correct pronoun
ArabicToolkit::welcome('أحمد', 'male');
// "أهلاً بك يا أحمد"

ArabicToolkit::welcome('سارة', 'female');
// "أهلاً بكِ يا سارة"

Gender is auto-detected using the Gender Detection service when not specified.

API Reference

ArabicToolkit Facade

Method Returns Service
transliterate(string, ?string) string Transliteration
moneyToWords(float|int, ?string, bool, ?string) string Money to Words
removeHarakat(string) string Text Utilities
normalizeAlef(string) string Text Utilities
toEasternDigits(string) string Text Utilities
toWesternDigits(string) string Text Utilities
isArabic(string) bool Text Utilities
removeTatweel(string) string Text Utilities
normalizeForSearch(string) string Search Normalization
normalizeTaMarbuta(string) string Search Normalization
normalizeYaMaqsura(string) string Search Normalization
slug(string, bool) string Slug Generator
pluralize(int, string, string, string) string Pluralization
pluralForm(int, string, string, string) string Pluralization
toHijri(string) HijriDate Hijri Date
fromHijri(int, int, int) array Hijri Date
hijriToday() HijriDate Hijri Date
detectGender(string) string Gender Detection
formatNumber(float|int, int) string Number Formatting
formatPercentage(float, int) string Number Formatting
ordinal(int, string) string Number Formatting
fixKeyboard(string, ?string) string Keyboard Layout
searchVariants(string) array Keyboard Layout
bidi(string) string BiDi Helpers
textDirection(string) string BiDi Helpers
greeting(string, ?string) string Greeting Generator
salutation(string, ?string) string Greeting Generator
welcome(string, ?string) string Greeting Generator

Real-World Examples

Invoice Generator

$amount = 15750.50;
$hijri = ArabicToolkit::toHijri(now()->format('Y-m-d'));

echo ArabicToolkit::moneyToWords($amount, 'SAR', appendOnly: true, locale: 'ar');
// "خمسة عشر ألف وسبعمائة وخمسون ريال سعودي وخمسون هللة فقط"

echo $hijri->format('d/m/Y', 'ar');
// "١٦/١٠/١٤٤٧"

Blog Post URL

$post = Post::create(['title' => 'مقالة عن الذكاء الاصطناعي']);
$post->slug = ArabicToolkit::slug($post->title);
// "مقالة-عن-الذكاء-الاصطناعي"

Search with Arabic Normalization

// Index
$product->search_name = ArabicToolkit::normalizeForSearch($product->name);

// Query (user types "أحمد" or "احمد" -- both match)
$query = ArabicToolkit::normalizeForSearch($request->q);
$results = Product::where('search_name', 'LIKE', "%{$query}%")->get();

Personalized Email

$gender = ArabicToolkit::detectGender($user->first_name);
$salutation = ArabicToolkit::salutation($user->first_name, $gender);
$name_en = ArabicToolkit::transliterate($user->first_name);

Mail::to($user)->send(new WelcomeMail($salutation, $name_en));

Smart Search Box

// User types "pshl" (forgot to switch keyboard)
$variants = ArabicToolkit::searchVariants($request->q);
$results = User::where('name', 'LIKE', "%{$variants['original']}%")
    ->orWhere('name', 'LIKE', "%{$variants['swapped']}%")
    ->get();

Arabic Dashboard Numbers

$stats = [
    'revenue' => ArabicToolkit::formatNumber($totalRevenue),     // "١٬٢٣٤٬٥٦٧٫٨٩"
    'growth'  => ArabicToolkit::formatPercentage($growthRate),   // "١٥٫٧٪"
    'rank'    => ArabicToolkit::ordinal($rank),                  // "الثالث"
    'files'   => ArabicToolkit::pluralize($count, 'ملف', 'ملفان', 'ملفات'),
];

Architecture

src/
├── ArabicToolkit.php                 # Main entry point (28 public methods)
├── config/
│   └── arabic-toolkit.php            # Configuration
├── Contracts/
│   ├── TransliteratorInterface.php
│   └── MoneyConverterInterface.php
├── Currency/
│   ├── CurrencyRegistry.php          # 12 currencies (EN + AR names)
│   ├── MoneyToWords.php              # Bilingual money converter
│   ├── NumberToWords.php             # English number engine
│   └── NumberToWordsArabic.php       # Arabic number engine
├── Facades/
│   └── ArabicToolkit.php             # Laravel Facade
├── Hijri/
│   ├── HijriConverter.php            # Kuwaiti algorithm
│   └── HijriDate.php                 # Value object with formatting
├── Providers/
│   └── ArabicToolkitServiceProvider.php
├── Support/
│   ├── ArabicBidi.php                # BiDi text handling
│   ├── ArabicGreeting.php            # Gender-aware greetings
│   ├── ArabicNumber.php              # Number formatting & ordinals
│   ├── ArabicPlural.php              # Arabic pluralization rules
│   ├── ArabicSlug.php                # URL slug generator
│   ├── ArabicText.php                # Text normalization utilities
│   ├── GenderDetector.php            # Name gender detection
│   └── KeyboardLayout.php            # QWERTY ↔ Arabic mapping
└── Transliteration/
    ├── ArabicTransliterator.php       # Two-tier transliteration engine
    ├── CharacterMap.php               # Dialect-aware letter mappings
    └── NameDictionary.php             # 1,200+ curated names

Zero dependencies beyond Laravel's Illuminate Support.

Key design decisions:

  • All utility classes use static methods for simple direct usage
  • The Facade delegates everything to the main ArabicToolkit class
  • Name dictionary is a PHP constant array (no database, no JSON files)
  • Float-safe money conversion using integer math
  • Fuzzy name matching handles common Arabic typos automatically

Testing

The package ships with 175 Pest tests covering every service:

cd packages/digitaltunnel/arabic-toolkit
./vendor/bin/pest
  PASS  Tests\Unit\ArabicTextTest ............... 17 tests
  PASS  Tests\Unit\GenderTest .................... 8 tests
  PASS  Tests\Unit\HijriTest ..................... 8 tests
  PASS  Tests\Unit\KeyboardAndBidiTest .......... 16 tests
  PASS  Tests\Unit\MoneyToWordsTest ............. 63 tests
  PASS  Tests\Unit\NumberFormatTest .............. 7 tests
  PASS  Tests\Unit\PluralTest .................... 7 tests
  PASS  Tests\Unit\SlugTest ...................... 7 tests
  PASS  Tests\Unit\TransliterationTest .......... 42 tests

  Tests:    175 passed (253 assertions)

Security

If you discover a security vulnerability, please send an email to hey@digitaltunnel.net instead of opening a public issue.

See SECURITY.md for full details on our security policy, supported versions, and best practices.

License

The MIT License (MIT). See LICENSE for details.