PHPackages                             yazidkhaldi/laravel-ilsawn - 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. [PDF &amp; Document Generation](/categories/documents)
4. /
5. yazidkhaldi/laravel-ilsawn

ActiveLibrary[PDF &amp; Document Generation](/categories/documents)

yazidkhaldi/laravel-ilsawn
==========================

A Laravel package to manage multilingual translations via CSV, with a Livewire UI and JS hooks for React, Vue, Svelte, and native support for Blade and Livewire.

v1.0.2(2mo ago)134↓100%[1 PRs](https://github.com/YazidKHALDI/laravel-ilsawn/pulls)MITPHPPHP ^8.2CI passing

Since Mar 8Pushed 1mo agoCompare

[ Source](https://github.com/YazidKHALDI/laravel-ilsawn)[ Packagist](https://packagist.org/packages/yazidkhaldi/laravel-ilsawn)[ Docs](https://github.com/yazidkhaldi/laravel-ilsawn)[ GitHub Sponsors](https://github.com/ilsawn)[ RSS](/packages/yazidkhaldi-laravel-ilsawn/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (13)Versions (6)Used By (0)

[![Laravel ilsawn Logo](resources/images/ilsawn.png)](resources/images/ilsawn.png)

A Laravel package to manage multilingual translations through a single CSV file. Comes with a Livewire management UI, an Inertia.js integration, and JS adapters for React, Vue 3, and Svelte.

> **ilsawn** (ⵉⵍⵙⴰⵡⵏ) — from the Amazigh word **ⵉⵍⵙ** (*ils*), meaning *language* or *tongue*. The plural **ⵉⵍⵙⴰⵡⵏ** carries both senses: the organ of speech, and a people's idiom.

---

[![Laravel ilsawn ui](resources/images/ilsawn-ui.png)](resources/images/ilsawn-ui.png)

Features
--------

[](#features)

- **One CSV, all locales** — every translation lives in a single human-readable file
- **Livewire UI** — browse, search, and edit translations inline from the browser
- **Artisan commands** — scan your codebase for missing keys, remove stale ones, generate JSON files
- **Inertia.js support** — `SharesTranslations` trait pushes the active locale to the frontend automatically, with production caching built in
- **JS adapters** — thin wrappers for React, Vue 3, and Svelte that expose the familiar `__()` helper
- **AI auto-translation** — one-click translation powered by `laravel/ai` (optional)
- **Safe fallback chain** — missing locale → default locale → key itself; the app never breaks

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13
- Livewire 3 or 4

---

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

[](#installation)

```
composer require yazidkhaldi/laravel-ilsawn
php artisan ilsawn:install
```

The install command:

1. Publishes `config/ilsawn.php`
2. Creates `lang/ilsawn.csv` with a header row for your configured locales
3. Publishes `app/Providers/IlsawnServiceProvider.php` where you control who can access the UI
4. If Inertia.js is detected: publishes the JS adapters to `resources/js/vendor/ilsawn/` and prints setup instructions

Then register the provider in `bootstrap/providers.php`:

```
App\Providers\IlsawnServiceProvider::class,
```

---

Publishing assets
-----------------

[](#publishing-assets)

All assets are published automatically by `ilsawn:install`. The tags below are only needed if you want to **re-publish or customise** individual pieces after installation.

TagWhat gets publishedDestination`ilsawn-config`Package config file`config/ilsawn.php``ilsawn-views`Livewire UI views`resources/views/vendor/ilsawn/``ilsawn-js`JS adapters (React, Vue, Svelte, Blade)`resources/js/vendor/ilsawn/````
php artisan vendor:publish --tag=ilsawn-config
php artisan vendor:publish --tag=ilsawn-views
php artisan vendor:publish --tag=ilsawn-js
```

Add `--force` to overwrite files that were already published.

---

Configuration
-------------

[](#configuration)

`config/ilsawn.php`:

```
return [
    // Locales your app supports — each becomes a column in the CSV
    'locales'        => ['en', 'fr', 'ar'],

    // Primary fallback locale when a translation is missing
    'default_locale' => 'en',

    // Path to the CSV file, relative to base_path()
    'csv_path'       => 'lang/ilsawn.csv',

    // Automatic CSV backup before every generate run
    'backup'         => true,
    'backup_limit'   => 5,   // 0 = keep all backups

    // Column delimiter — semicolon avoids conflicts with commas in text
    'delimiter'      => ';',

    // Directories scanned for translation keys (relative to base_path())
    'scan_paths'     => ['app', 'resources'],

    // Paths excluded from scanning
    'scan_exclude'   => ['resources/js/vendor/ilsawn'],

    // URL prefix for the management UI  →  /ilsawn
    'route_prefix'   => 'ilsawn',

    // Middleware applied to UI routes
    'middleware'     => ['web'],
];
```

---

The CSV file
------------

[](#the-csv-file)

```
key;en;fr;ar
dashboard.title;Dashboard;Tableau de bord;لوحة القيادة
welcome;Welcome :name;Bienvenue :name;مرحبا :name
```

- **key** — any string: plain text, dot notation, snake\_case, or a full sentence
- **locale columns** — one per locale listed in `config('ilsawn.locales')`
- **`:placeholder`** — use `:name` syntax for variable substitution in both PHP and JS

Edit this file directly, or use the Livewire UI at `/ilsawn`.

---

Working with multiple locales
-----------------------------

[](#working-with-multiple-locales)

### Laravel's built-in lang files

[](#laravels-built-in-lang-files)

When you run `php artisan lang:publish`, Laravel creates `lang/en/` with four files:

```
lang/en/auth.php
lang/en/pagination.php
lang/en/passwords.php
lang/en/validation.php

```

For each additional locale, the best practice is to **clone those files** into the matching folder and translate them:

```
lang/fr/auth.php
lang/fr/pagination.php
lang/fr/passwords.php
lang/fr/validation.php

```

Pre-translated versions for dozens of languages are available at: **[github.com/Laravel-Lang/lang](https://github.com/Laravel-Lang/lang/tree/main/locales)**

Copy the files for your locales directly from that repository.

### Starter kit and package strings (Breeze, Jetstream…)

[](#starter-kit-and-package-strings-breeze-jetstream)

Some starter kits (e.g. Laravel Breeze) add strings that you may also want to translate — dashboard labels, auth messages, etc.

**Laravel's native translator does NOT auto-load arbitrary JSON files from `lang/{locale}/`.**For Blade and Livewire, only these sources are loaded automatically:

- `lang/{locale}/auth.php`, `pagination.php`, `passwords.php`, `validation.php` (PHP namespace files)
- `lang/{locale}.json` — the root-level JSON, which is exactly what ilsawn generates

So the correct workflow for those strings is: **add them to the CSV**. ilsawn will generate `lang/fr.json`, `lang/ar.json`, etc., and Laravel will pick them up natively.

> **Inertia.js note:** If you use the `SharesTranslations` trait, it also reads JSON files placed in `lang/{locale}/` (e.g. `lang/fr/breeze.json`) and merges them into the shared `translations` prop. This is Inertia-only — it does not affect Blade.

```
lang/fr.json   ← generated by ilsawn:generate — do not edit manually

```

### What ilsawn's CSV handles

[](#what-ilsawns-csv-handles)

ilsawn's scanner automatically **skips** any key it finds in Laravel's standard lang files:

- `lang/{locale}/auth.php`, `pagination.php`, `passwords.php`, `validation.php`
- `lang/{locale}/*.json` (read by Inertia's SharesTranslations)

The CSV therefore stays focused on **your project's own strings** — no noise from the framework.

---

Artisan commands
----------------

[](#artisan-commands)

### `ilsawn:generate`

[](#ilsawngenerate)

Generates one JSON file per locale in `lang/` (e.g. `lang/en.json`, `lang/fr.json`).

```
php artisan ilsawn:generate
```

Run this whenever you edit the CSV to make changes available to the application. It creates a timestamped CSV backup and clears the application cache automatically.

**Options:**

FlagDescription`--scan`Scan `scan_paths` for `__()` calls and add missing keys to the CSV`--cleanup`Prompt to remove keys that are no longer referenced in code`--remove-duplicates`Prompt to remove keys that already exist in Laravel's own `lang/` PHP files`--dry-run`Preview all changes without modifying any file### `ilsawn:install`

[](#ilsawninstall)

Publish config, CSV stub, Gate provider, and JS adapters. Safe to re-run with `--force` to overwrite already-published files.

---

Using translations
------------------

[](#using-translations)

### Blade &amp; Livewire (PHP side)

[](#blade--livewire-php-side)

Use Laravel's native `__()` helper — no change to your workflow:

```
{{ __('dashboard.title') }} {{ __('welcome', ['name' => $user->name]) }}
```

### Blade + Alpine.js (JS side)

[](#blade--alpinejs-js-side)

For projects that use Blade without Inertia, add the `@ilsawnTranslations` directive to your main layout. It outputs a `` tag that inlines the current locale's translations into the page:

```

    @ilsawnTranslations

```

Then import the adapter once in your JS entry file:

```
import "@/vendor/ilsawn/adapters/blade";
```

That's it. `window.__` is now available globally, so Alpine.js inline expressions work without any extra setup:

```

```

Or import the function explicitly in any JS file:

```
import { __ } from "@/vendor/ilsawn/adapters/blade";

__("dashboard.title"); // 'Dashboard'
__("welcome", { name: "Ali" }); // 'Welcome Ali'
```

### Inertia.js (server side)

[](#inertiajs-server-side)

Open `app/Http/Middleware/HandleInertiaRequests.php` and make two additions:

```
// 1. Add the use statement inside the class
use ilsawn\LaravelIlsawn\SharesTranslations;

class HandleInertiaRequests extends Middleware
{
    use SharesTranslations; // ← add this

    public function share(Request $request): array
    {
        return [
            ...parent::share($request),
            'auth' => ['user' => $request->user()],
            // ... your existing shared props ...
            'translations' => $this->translations($request), // ← add this
        ];
    }
}
```

That's it. The trait provides the `translations()` method — no other changes needed.

In production the result is cached forever under `ilsawn_translations_{locale}` and invalidated automatically when `ilsawn:generate` runs.

### React

[](#react)

```
import { useLang } from "@/vendor/ilsawn/adapters/react";

export default function Page() {
    const { __ } = useLang();

    return {__("dashboard.title")};
}
```

### Vue 3

[](#vue-3)

```

import { useLang } from "@/vendor/ilsawn/adapters/vue";

const { __ } = useLang();

    {{ __("dashboard.title") }}

```

### Svelte

[](#svelte)

```

import { useLang } from '@/vendor/ilsawn/adapters/svelte';

const { __ } = useLang();

{__('dashboard.title')}
```

### Variable substitution in JS

[](#variable-substitution-in-js)

All adapters support `:placeholder` replacements, consistent with Laravel's PHP syntax:

```
__("welcome", { name: "Ali" }); // 'Welcome Ali'
```

---

Livewire UI
-----------

[](#livewire-ui)

[![Laravel ilsawn ui](resources/images/ilsawn-ui.png)](resources/images/ilsawn-ui.png)

Visit `/ilsawn` (or your configured `route_prefix`) to access the translation manager.

FeatureDescriptionSearchFilter keys in real timeMissing onlyToggle to show only keys that have at least one empty locale — great for spotting gaps quicklyInline editClick Edit on any row to update values directly in the browser`=` buttonCopy the key itself into a locale field — useful for brand names or terms that need no translationAI buttonAuto-translate the source text into the target locale (requires `laravel/ai`)ScanDetect new keys from your codebase and add them to the CSV without leaving the UIGenerate JSONRegenerate the JSON locale files; a red dot on the button signals the CSV has unsaved changesPending keys bannerShown on page load when keys exist in code that are not yet in the CSV---

Authorization
-------------

[](#authorization)

`ilsawn:install` publishes `app/Providers/IlsawnServiceProvider.php`:

```
Gate::define('viewIlsawn', function ($user) {
    return in_array($user->email, [
        'admin@example.com',
    ]);
});
```

Replace the closure body with any logic you need — role checks, environment guards, etc. The UI returns 403 for anyone the gate denies.

---

AI auto-translation (optional)
------------------------------

[](#ai-auto-translation-optional)

Install `laravel/ai`:

```
composer require laravel/ai
```

[![Laravel ilsawn ui](resources/images/ilsawn-ai.gif)](resources/images/ilsawn-ai.gif)

An **AI** button appears automatically in the edit row for each non-source locale. It translates the source text into the target language using your configured AI provider. No additional configuration inside ilsawn is needed.

---

Fallback chain
--------------

[](#fallback-chain)

When a translation is requested:

1. Look up the key in the active locale's JSON file
2. If missing, fall back to the `default_locale` value
3. If that is also empty, return the key itself

The app never throws — a missing translation degrades gracefully to the key string.

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE) for details.

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance88

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96% 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 ~2 days

Total

3

Last Release

62d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/86d73524768560122991125ef5641f9e5189137e1016cdbb8da4b955c399d646?d=identicon)[YazidKHALDI](/maintainers/YazidKHALDI)

---

Top Contributors

[![YazidKHALDI](https://avatars.githubusercontent.com/u/70165468?v=4)](https://github.com/YazidKHALDI "YazidKHALDI (24 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

laravellocalizationpackagelaravellocalizationi18ntranslationmultilingualcsvilsawnlaravel-ilsawn

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/yazidkhaldi-laravel-ilsawn/health.svg)

```
[![Health](https://phpackages.com/badges/yazidkhaldi-laravel-ilsawn/health.svg)](https://phpackages.com/packages/yazidkhaldi-laravel-ilsawn)
```

###  Alternatives

[lukasss93/laravel-larex

Translate your Laravel application from a single CSV file!

9790.3k2](/packages/lukasss93-laravel-larex)[ufirst/lang-import-export

A Laravel package providing artisan commands to import and export language files from and to CSV.

42207.9k](/packages/ufirst-lang-import-export)[highsolutions/laravel-lang-import-export

A Laravel package providing artisan commands to import and export language files from and to CSV.

25292.3k](/packages/highsolutions-laravel-lang-import-export)[smousss/laravel-globalize

Make Laravel projects translatable in a matter of seconds!

2266.3k](/packages/smousss-laravel-globalize)[omaralalwi/lexi-translate

Laravel translation package with morph relationships and caching.

754.3k2](/packages/omaralalwi-lexi-translate)

PHPackages © 2026

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