PHPackages                             goodm4ven/arabicable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. goodm4ven/arabicable

ActiveLibrary[Search &amp; Filtering](/categories/search)

goodm4ven/arabicable
====================

A unified Arabic language support package crafted in pure PHP with smooth Laravel integration

v1.2.7(2mo ago)0214↓90.9%[2 PRs](https://github.com/GoodM4ven/PACKAGE_LARAVEL_arabicable/pulls)MITPHPPHP ^8.4||^8.3CI passing

Since Mar 20Pushed 1mo agoCompare

[ Source](https://github.com/GoodM4ven/PACKAGE_LARAVEL_arabicable)[ Packagist](https://packagist.org/packages/goodm4ven/arabicable)[ Docs](https://github.com/goodm4ven/PACKAGE_LARAVEL_arabicable)[ Fund](https://www.buymeacoffee.com/GoodM4ven)[ GitHub Sponsors](https://github.com/GoodM4ven)[ RSS](/packages/goodm4ven-arabicable/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (54)Versions (21)Used By (0)

بسم الله الرحمن الرحيم

Arabicable
==========

[](#arabicable)

Practical Arabic text processing for Laravel, focused on fast and predictable Arabic search with database-backed searchable variants.

[![Latest Version on Packagist](https://camo.githubusercontent.com/93eac0e03f262d707b862ebf01469de375e19f3be87df388fdb01d06ef4ee1a6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f676f6f646d3476656e2f61726162696361626c652e7376673f7374796c653d666f722d7468652d626164676526636f6c6f723d67726179)](https://packagist.org/packages/goodm4ven/arabicable)[![GitHub Tests Action Status](https://camo.githubusercontent.com/0760954782358c2207cfbba43531aa0567621a34d072fb23a3a6b0f606fa8695/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f676f6f646d3476656e2f5041434b4147455f4c41524156454c5f61726162696361626c652f706573742e796d6c3f6272616e63683d646576266c6162656c3d7465737473267374796c653d666f722d7468652d626164676526636f6c6f723d666f72657374677265656e)](https://github.com/goodm4ven/PACKAGE_LARAVEL_arabicable/actions?query=workflow%3Apest+branch%3Adev)[![Coverage Status](https://camo.githubusercontent.com/5fc757190d20a976fc6b527d86ff79567551456538ff6e336c0cd4db3e2542bd/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f676f6f646d3476656e2f5041434b4147455f4c41524156454c5f61726162696361626c652f6465763f7374796c653d666f722d7468652d626164676526636f6c6f723d707572706c65)](https://codecov.io/gh/goodm4ven/PACKAGE_LARAVEL_arabicable/tree/dev)[![Total Downloads](https://camo.githubusercontent.com/c07d9cd8c1714370cfef8a0a8d93bbc7a26a16e8d3757e638cba13cfa4cc6c6d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f676f6f646d3476656e2f61726162696361626c652e7376673f7374796c653d666f722d7468652d626164676526636f6c6f723d626c7565)](https://packagist.org/packages/goodm4ven/arabicable)

[![](./.github/images/banner.png)](./.github/images/banner.png)Description
-----------

[](#description)

Arabicable primarily stores Arabic field variants in dedicated database columns, so indexing and querying remain consistent and fast through normal Eloquent workflows.

For each Arabicable text column, the package maintains:

- ``
- `_with_harakat`
- `_searchable`
- `_stemmed`

And all in all, this package provides all of these features:

### Anaylsis and Search

[](#anaylsis-and-search)

- Generate Arabic-ready database columns and keep searchable variants in sync automatically with [Arabicable model and migration setup](#arabicable-model--migration).
- Run exact, like, and relevance-ranked Arabic matching with [search scopes](#search-scopes) and [text processing helpers](#text-processing-helpers).
- Build comprehensive query plans using normalization, tokenization, stop-word filtering, stemming, and lexical expansion via [text processing helpers](#text-processing-helpers) and [search scopes](#search-scopes).
- Control text with or without harakat and diacritics using the [ArabicFilter facade](#arabicfilter-facade), [Arabic facade common methods](#arabic-facade-common-methods), and [CamelTools facade](#cameltools-facade-pure-php-utility-port).
- Normalize letters, punctuation, spacing, and keywords using the [Arabic facade common methods](#arabic-facade-common-methods) and [CamelTools facade](#cameltools-facade-pure-php-utility-port).
- Compile and seed local lexical dictionaries for variants and stop-words using the [dictionary workflow](#dictionary-workflow-arabicableraw_data_path).
- Use pure-PHP transliteration, mapping, normalization, dediacritization, and tokenization through the [CamelTools facade](#cameltools-facade-pure-php-utility-port).

### Al-Qur'an

[](#al-quran)

- Query Quran data at both ayah and exact word-occurrence levels with [Quran indexing tables](#quran-indexing-tables).
- Render Quran text with DigitalKhatt-compatible fonts while searching normalized fields via [DigitalKhatt / Quran font setup](#digitalkhatt--quran-font-setup).

### Date

[](#date)

- Convert dates between Gregorian and Hijri calendars with [Gregorian/Hijri date helpers](#gregorianhijri-date-helpers) and [Arabic facade common methods](#arabic-facade-common-methods).

### Numbers

[](#numbers)

- Convert numerals between ASCII digits (`123`) and Arabic-Indic digits (`١٢٣`) from backend and browser using [Arabic facade common methods](#arabic-facade-common-methods) and the [JavaScript number helper](#javascript-number-helper).

### Voice

[](#voice)

- Add browser speech-to-text, text-to-speech, and voice transforms with the [RunAnywhere STT/TTS companion](#runanywhere-stttts-companion).

Installation
------------

[](#installation)

1. Install via Composer:

```
composer require goodm4ven/arabicable
```

2. Run installer:

```
php artisan arabicable:install --seed
```

This publishes config + migrations, runs migration (with prompt unless `--testing`), and imports dictionaries when `--seed` is provided.

3. Publish the assets:

```
php artisan vendor:publish --tag=arabicable-assets
```

Raw data resolution defaults are customizable if you wish:

- `arabicable.raw_data_path` is auto-resolved from `vendor/goodm4ven/arabicable/resources/raw-data`, then `resources/raw-data`.
- You can publish package raw datasets to your app with:

```
php artisan vendor:publish --tag="arabicable-raw-data" --force
```

### Upgrading

[](#upgrading)

Refresh published package files:

```
php artisan vendor:publish --tag="arabicable-config" --force
php artisan vendor:publish --tag="arabicable-migrations" --force
php artisan vendor:publish --tag="arabicable-raw-data" --force
php artisan migrate
```

If local dictionary sources changed:

```
php artisan arabicable:compile-data
php artisan arabicable:seed --all --truncate
```

Usage
-----

[](#usage)

### Arabicable Model &amp; Migration

[](#arabicable-model--migration)

1. Add an Arabicable migration macro:

    ```
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;

    Schema::create('notes', function (Blueprint $table): void {
        $table->id();
        $table->arabicText('content');
        $table->timestamps();
    });
    ```
2. Use `Arabicable` trait on your model:

    ```
    use GoodMaven\Arabicable\Traits\Arabicable;
    use Illuminate\Database\Eloquent\Model;

    class Note extends Model
    {
        use Arabicable;

        protected $fillable = ['content'];
    }
    ```

Observer-managed columns are now updated automatically when `content` changes:

- `$note->content`
- `$note->content_with_harakat`
- `$note->content_searchable`
- `$note->content_stemmed`

If using [Spatie Translatable](https://spatie.be/docs/laravel-translatable/v6/introduction), migration macros accept `?bool $isTranslatable`:

```
$table->arabicText('content', isTranslatable: true);
```

Note

`Arabicable` trait also provides `getSearchableTranslations()` for flattened keys like `content_searchable_ar`, `content_searchable_en`, etc.

### Search Scopes

[](#search-scopes)

`Arabicable` trait includes:

- `scopeSearchArabic`
- `scopeWhereArabicLike`
- `scopeSearchArabicComprehensive`
- `scopeWhereArabicComprehensive`
- `scopeOrderByArabicRelevance`

Example:

```
Post::query()
    ->searchArabic('content', $query)
    ->limit(20)
    ->get();
```

Comprehensive mode builds terms from:

- normalized query text
- tokens
- stop-word removal
- stems
- lexical variants (`roots`, `stems`, `original_words`, or `all`)

### Text Processing Helpers

[](#text-processing-helpers)

```
use GoodMaven\Arabicable\Facades\Arabic;
use GoodMaven\Arabicable\Facades\ArabicFilter;

$searchable = ArabicFilter::forSearch($text);
$stemmed = ArabicFilter::forStem($text);
$withoutHarakat = ArabicFilter::withoutHarakat($text);
$clean = Arabic::stripWeirdCharacters($text, keepHarakat: true, keepPunctuation: true);
$keywords = Arabic::extractKeywords($text);
$plan = Arabic::buildComprehensiveSearchPlan($query);
$variants = Arabic::expandWordVariants($tokens, mode: 'all', stripStopWords: true);
```

### ArabicFilter Facade

[](#arabicfilter-facade)

- `withHarakat(string $text): string`
- `withoutHarakat(string $text): string`
- `withoutDiacritics(string $text, bool $keepShadda = false): string`
- `forSearch(string $text): string`
- `forStem(string $text): string`
- `forMemorizationComparison(string $text, bool $stripCommons = true, bool $stripConnectors = true): string`

### Arabic Facade (Common Methods)

[](#arabic-facade-common-methods)

- Harakat/diacritics: `removeHarakat`, `removeDiacritics`, `addHarakat`
- Normalization: `normalizeHuroof`, `normalizeNumeralsForSearch`, `stripWeirdCharacters`
- Keywords/search: `tokenize`, `stemWord`, `stemWords`, `removeStopWords`, `extractKeywords`, `buildComprehensiveSearchPlan`, `expandWordVariants`
- Commons/cache: `removeCommons`, `clearConceptCache`
- Punctuation/spacing: `toTightPunctuationStyle`, `toLoosePunctuationStyle`, `removeAllPunctuationMarks`, `normalizeSpaces`
- Date conversion: `gregorianToHijri`, `hijriToGregorian`

### Quran Indexing Tables

[](#quran-indexing-tables)

Enable Quran features in config when needed:

```
'features' => [
    'quran' => true,
],
```

After running migrations, Arabicable creates and imports:

- `quran_verses`: one row per ayah with `surah_number`, `ayah_number`, `ayah_index`, `text_uthmani`, `text_searchable`, `text_sanitized`, `text_without_harakat`, `text_without_diacritics`, `text_normalized_huroof`.
- `quran_words`: one row per word occurrence with `verse_id`, `word_position`, `global_word_index`, `token_uthmani`, `token_sanitized`, `token_searchable`, `token_without_harakat`, `token_without_diacritics`, `token_normalized_huroof`, `token_stem`, `token_root`, `token_lemma`.
- `quran_verse_explanations`: ayah-linked tafsir/i'rab records from SQLite sources (`source_key`, `content_kind`, `content_html`, `content_text`).
- `quran_word_annotations`: optional word-level notes/translation payloads linked to exact `quran_words` rows.

For repeat words, target the occurrence with:

- `verse_id + word_position` for stable position inside ayah.
- `global_word_index` for a single canonical word pointer across the full Quran.

This structure is ready for later tafsir/translation attachments at ayah level or exact word occurrence level.

Default source config keys:

- `arabicable.raw_data_path`
- `arabicable.data_sources.quran_othmani_surahs_dir`
- `arabicable.data_sources.quran_exegesis_databases_dir`
- `arabicable.data_sources.quran_layout_databases_dir`
- `arabicable.data_sources.quran_lexicon_databases_dir`
- `arabicable.data_sources.quran_fonts_dir`
- `arabicable.data_sources.quran_surah_headers_fonts_dir`

For tafsir / i'rab SQLite data:

- Put files like `ar-tafsir-al-tabari.db` and `al-i-rab-al-muyassar.db` in `/quran/exegesis`.
- Keep required exegesis SQLite files inside `/quran/exegesis` (or your configured data source path).
- Explanations are stored for display and retrieval, and are not part of Arabicable search indexing.

### Gregorian/Hijri Date Helpers

[](#gregorianhijri-date-helpers)

```
use GoodMaven\Arabicable\Facades\Arabic;

$hijri = Arabic::gregorianToHijri(2025, 1, 1); // ['year' => ..., 'month' => ..., 'day' => ...]
$gregorian = Arabic::hijriToGregorian($hijri['year'], $hijri['month'], $hijri['day']);
```

### JavaScript Number Helper

[](#javascript-number-helper)

Published asset: `public/vendor/arabicable/arabicable.js`

```
window.ArabicableNumbers.toArabicIndic('123'); // "١٢٣"
window.ArabicableNumbers.toAscii('١٢٣'); // "123"
window.ArabicableNumbers.normalizeForBackendSearch('رقم ١٢٣', 'arabic'); // "رقم 123"
window.ArabicableNumbers.normalizeForBackendSearch('رقم 123', 'indian'); // "رقم ١٢٣"
window.ArabicableNumbers.normalizeForBackendSearch('123', 'both'); // "123 ١٢٣"
```

### DigitalKhatt / Quran Font Setup

[](#digitalkhatt--quran-font-setup)

Arabicable can be paired with DigitalKhatt-style Quran rendering in your app frontend.

1. Publish package assets (and optionally Quran raw-data files if you want app-local copies):

```
php artisan vendor:publish --tag=arabicable-assets --force
php artisan vendor:publish --tag=arabicable-raw-data --force
```

2. Use the included Quran font file (published under `public/vendor/arabicable/madina.woff2`), or replace it with your preferred DigitalKhatt-compatible font build.

    Surah header fonts are also bundled and available in both locations:

    - `resources/raw-data/quran/fonts/surah-headers/QCF_SurahHeader_COLOR-Regular.woff2`
    - `resources/raw-data/quran/fonts/surah-headers/surah-name-v2.woff2`
    - `public/vendor/arabicable/QCF_SurahHeader_COLOR-Regular.woff2`
    - `public/vendor/arabicable/surah-name-v2.woff2`
3. Define your Quran text class:

```
@font-face {
  font-family: 'MadinaQuran';
  src: url('/vendor/arabicable/madina.woff2') format('woff2');
  font-display: swap;
}

.font-quran {
  font-family: 'MadinaQuran', 'Amiri', serif;
}

.font-quran-surah-header {
  font-family: 'QcfSurahHeaderColor', 'SurahNameV2', 'MadinaQuran', 'Amiri', serif;
}
```

4. Render Uthmani text with `.font-quran`, while using `text_searchable`/`token_searchable` fields for search queries.
5. Optional package config for surah header font selection:

```
'quran_fonts' => [
    'surah_headers' => [
        'preferred' => 'qcf-surah-header-color-regular',
        'available' => [
            'qcf-surah-header-color-regular' => [
                'family' => 'QcfSurahHeaderColor',
                'filename' => 'QCF_SurahHeader_COLOR-Regular.woff2',
                'format' => 'woff2',
            ],
            'surah-name-v2' => [
                'family' => 'SurahNameV2',
                'filename' => 'surah-name-v2.woff2',
                'format' => 'woff2',
            ],
        ],
    ],
],
```

If you integrate the external `digitalkhatt.js` stack, keep Arabicable as the search/index layer and use DigitalKhatt purely for display shaping.

### RunAnywhere STT/TTS Companion

[](#runanywhere-stttts-companion)

Install frontend packages:

```
npm install @runanywhere/web @runanywhere/web-onnx
```

Initialize and register your bridge:

```
import { RunAnywhere, SDKEnvironment } from '@runanywhere/web';
import { ONNX } from '@runanywhere/web-onnx';

await RunAnywhere.initialize({ environment: SDKEnvironment.Production, debug: false });
await ONNX.register();

window.ArabicableRunAnywhere.setBridge({
  async speechToText(audioInput, options = {}) {
    // Return string or object containing transcript text
    return { text: '' };
  },
  async textToSpeech(text, options = {}) {
    // Return Float32Array, Blob, or { audio/blob/url, sampleRate }
    return { audio: new Float32Array(), sampleRate: 24000 };
  },
});
```

Bridge API methods:

- `speechToText(audioInput, options)`
- `textToSpeech(text, options)`
- `voiceToText(audioInput, options)`
- `textToVoice(text, options)`
- `voiceToVoice(audioInput, options)`
- `transformArabic({ text, audio, target }, options)`
- `decodeAudioBlob(blob, targetSampleRate?)`
- `playFloat32Audio(audio, sampleRate?)`
- `playAudio(result)`

### Dictionary Workflow (`arabicable.raw_data_path`)

[](#dictionary-workflow-arabicableraw_data_path)

`compiled-*` files are runtime dictionaries. `source-*` files are local raw assets.

Compile:

```
php artisan arabicable:compile-data
php artisan arabicable:compile-data --raw-data-path=/absolute/path/to/raw-data
php artisan arabicable:compile-data --without-extra-stopwords
```

Seed DB dictionaries:

```
php artisan arabicable:seed --all
php artisan arabicable:seed --common-texts --stop-words
php artisan arabicable:seed --all --truncate
```

Current DB imports:

- `common_arabic_texts`
- `arabic_stop_words`

Current file-backed lexical expansion sources:

- `/verbs/compiled-word-variants.tsv`
- `/quran/compiled-quran-word-index.tsv`

All source paths are configurable via `config/arabicable.php` using:

- `arabicable.raw_data_path` (global base path)
- `arabicable.data_sources.*` (per-file/per-directory overrides)

API
---

[](#api)

### Validation Rules

[](#validation-rules)

- `GoodMaven\Arabicable\Rules\Arabic`
- `GoodMaven\Arabicable\Rules\ArabicWithSpecialCharacters`
- `GoodMaven\Arabicable\Rules\UncommonArabic`
- `GoodMaven\Arabicable\Rules\UniqueArabicWithSpecialCharacters`

### Artisan Commands

[](#artisan-commands)

CommandPurpose`arabicable:install`Publish config/migrations, migrate, optional seed (`--testing`, `--seed`)`arabicable:compile-data`Compile local datasets (`--raw-data-path`, `--without-extra-stopwords`)`arabicable:seed`Import configured dictionaries (`--all`, `--common-texts`, `--stop-words`, `--truncate`)### Migration Macros

[](#migration-macros)

MacroPurpose`indianDate($columnName, $isNullable = false, $isUnique = false)`Creates date column and `_indian``arabicString($columnName, $length = 255, $isNullable = false, $isUnique = false, $supportsFullSearch = false, $isTranslatable = null)`String + Arabicable variant columns`arabicTinyText($columnName, $isNullable = false, $isUnique = false, $supportsFullSearch = false, $isTranslatable = null)`TinyText + variants`arabicText($columnName, $isNullable = false, $isUnique = false, $isTranslatable = null)`Text + variants`arabicMediumText($columnName, $isNullable = false, $isUnique = false, $isTranslatable = null)`MediumText + variants`arabicLongText($columnName, $isNullable = false, $isUnique = false, $isTranslatable = null)`LongText + variants### Global Functions

[](#global-functions)

- `ar_indian(string $property): string`
- `ar_with_harakat(string $property): string`
- `ar_searchable(string $property): string`
- `ar_stem(string $property): string`
- `ar_expand_variants(...)`
- `arabicable_special_characters(...)`
- `camel_tools()` and `camel_*` helpers

### CamelTools Facade (Pure-PHP Utility Port)

[](#cameltools-facade-pure-php-utility-port)

Key utilities:

- Builtin mapping/transliteration: `mapWithBuiltin`, `transliterateWithBuiltin`, `arclean`
- Unicode/orthographic normalization: `normalizeUnicode`, `normalizeAlef*`, `normalizeAlefMaksura*`, `normalizeTehMarbuta*`, `normalizeOrthography`
- Dediacritization: `dediac*`
- Tokenization: `simpleWordTokenize`

Contribution
------------

[](#contribution)

- Always target `dev` branch for your PRs.

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE.md).

Credits
-------

[](#credits)

- Youssif Shaaban Alsager ([yshalsager](https://github.com/yshalsager))
- [Linuxscout](https://github.com/linuxscout)
- [CAMeL Tools](https://github.com/CAMeL-Lab/camel_tools)
- [ar-php](https://github.com/khaled-alshamaa/ar-php)
- [Qul by Tarteel](https://qul.tarteel.ai/resources)
- [Nuqaya](https://github.com/nuqayah)

والحمد لله رب العالمين

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance89

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 93.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Recently: every ~18 days

Total

15

Last Release

60d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2fe03bedf65c411e3623e9c103eb2dc4626c5d4ee3fab62cfb98d88caab82a4b?d=identicon)[GoodM4ven](/maintainers/GoodM4ven)

---

Top Contributors

[![GoodM4ven](https://avatars.githubusercontent.com/u/121377476?v=4)](https://github.com/GoodM4ven "GoodM4ven (54 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")

---

Tags

arabichijrilaravelphpquransearchstemmingsearchlaravelrootsarabictallstackpunctuationGoodM4venarabicablestemsharakat

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/goodm4ven-arabicable/health.svg)

```
[![Health](https://phpackages.com/badges/goodm4ven-arabicable/health.svg)](https://phpackages.com/packages/goodm4ven-arabicable)
```

###  Alternatives

[spatie/laravel-health

Monitor the health of a Laravel application

88212.7M180](/packages/spatie-laravel-health)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M352](/packages/psalm-plugin-laravel)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

24773.9k](/packages/harris21-laravel-fuse)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M279](/packages/laravel-ai)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

817336.8k3](/packages/defstudio-telegraph)[nativephp/mobile

NativePHP for Mobile

1.1k102.1k123](/packages/nativephp-mobile)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
