PHPackages                             shammaa/laravel-model-translations - 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. [Database &amp; ORM](/categories/database)
4. /
5. shammaa/laravel-model-translations

ActiveLibrary[Database &amp; ORM](/categories/database)

shammaa/laravel-model-translations
==================================

Smart and easy table-per-model translation system for Laravel

v1.4.3(4mo ago)042MITPHPPHP ^8.1

Since Dec 30Pushed 4mo agoCompare

[ Source](https://github.com/shammaa/laravel-model-translations)[ Packagist](https://packagist.org/packages/shammaa/laravel-model-translations)[ RSS](/packages/shammaa-laravel-model-translations/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (2)Versions (10)Used By (0)

Laravel Smart Model Translations
================================

[](#laravel-smart-model-translations)

A professional multilingual translation system for Laravel using the **Table per Model** approach with enhanced query capabilities.

Features
--------

[](#features)

- ✅ **Auto-Joins:** Query translated fields directly without worrying about `join` or `whereHas`.
- ✅ **Fluent API:** Clean methods like `translateTo()` and magic property access.
- ✅ **Performance:** Optimized database queries for multilingual data.
- ✅ **Native Ordering:** Sort results by translated columns with built-in scopes.
- ✅ **Flexible Setup:** Easy integration with existing models and professional trait implementation.

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

[](#installation)

```
composer require shammaa/laravel-model-translations
```

Setup
-----

[](#setup)

### 1. Prepare your Database

[](#1-prepare-your-database)

For an `Article` model, create an `article_translations` table:

```
Schema::create('article_translations', function (Blueprint $table) {
    $table->id();
    $table->foreignId('article_id')->constrained()->cascadeOnDelete();
    $table->string('locale')->index();

    // Translatable fields
    $table->string('title');
    $table->text('content');
});
```

### 2. Configure Models

[](#2-configure-models)

**Main Model:**

```
use Shammaa\LaravelModelTranslations\Traits\HasTranslations;

class Article extends Model
{
    use HasTranslations;

    protected $translatable = ['title', 'content'];
}
```

**Translation Model:**

```
class ArticleTranslation extends Model
{
    public $timestamps = false;
    protected $fillable = ['title', 'content', 'locale'];
}
```

Data Entry Methods
------------------

[](#data-entry-methods)

This package offers three flexible methods for handling translations to fit any workflow.

### 1. Simple Property Assignment (No Arrays)

[](#1-simple-property-assignment-no-arrays)

The most intuitive way. Just assign values to translatable properties as if they were normal model attributes. The library automatically detects the current application locale and directs the data to the correct translation table.

**Best for:** Single-language forms or simple updates.

```
// Assuming current locale is 'ar'
app()->setLocale('ar');

$article = new Article();
$article->status = 'active';      // Saved to main 'articles' table
$article->title = 'عنوان المقال';  // Automatically routed to 'article_translations'
$article->save();
```

### 2. Specific Locale Array

[](#2-specific-locale-array)

Save translations for a specific language explicitly, regardless of the current application locale.

**Best for:** Programmatic updates or background tasks.

```
$article->translateTo([
    'title'   => 'English Title',
    'content' => 'High-performance content'
], 'en')->save();
```

### 3. Bulk Multi-locale Array

[](#3-bulk-multi-locale-array)

Handle multiple languages in a single call. The library intelligently parses the nested arrays in two different formats.

**Best for:** Admin dashboards with multi-language tabs.

**Format A: Locale-first (Traditional)**

```
$article->translateTo([
    'ar' => [
        'title' => 'عنوان عربي',
        'content' => 'محتوى عربي'
    ],
    'en' => [
        'title' => 'English Title',
        'content' => 'English content'
    ]
])->save();
```

**Format B: Attribute-first (Smart)**This format is particularly useful when working with slug generators or specialized input fields.

```
$article->translateTo([
    'title' => [
        'ar' => 'عنوان عربي',
        'en' => 'English Title'
    ],
    'content' => [
        'ar' => 'محتوى عربي',
        'en' => 'English content'
    ]
])->save();
```

### 4. Smart Mass Assignment

[](#4-smart-mass-assignment)

You can use standard Laravel methods like `create()` or `update()`. The library will filter translatable fields automatically.

```
Article::create([
    'status' => 'published',
    'title'  => 'New Smart Article' // Automatically saved for current locale
]);
```

---

### Smart Querying (The "Killer" Feature)

[](#smart-querying-the-killer-feature)

Unlike other packages, you don't need to manually join tables or use complex `whereHas` queries.

#### 1. Smart Join (Performance)

[](#1-smart-join-performance)

The `withTranslation()` scope performs a single `leftJoin` on the database level. This is much faster than `with('translations')` for large lists when you only need the current locale.

```
// Gets articles and their current locale translations in ONE query
$articles = Article::withTranslation()->get();
```

#### 2. Automatic Filtering

[](#2-automatic-filtering)

```
// Search title in current language
$articles = Article::whereTranslation('title', 'like', '%Laravel%')->get();
```

#### 3. Smart Ordering

[](#3-smart-ordering)

```
// Order by the translated title (not the ID or main table)
$articles = Article::orderByTranslation('title', 'asc')->get();
```

#### 4. Filter by Missing Translations

[](#4-filter-by-missing-translations)

```
// Find models that don't have a translation for Arabic
$missingAr = Article::emptyTranslation('ar')->get();
```

#### 5. Find by Translated Slug 🆕

[](#5-find-by-translated-slug-)

When your `slug` is stored in the translations table, use these methods to find models easily:

```
// Find article by slug (searches all locales)
$article = Article::findByTranslatedSlug('my-article-slug');

// Find by slug in specific locale
$article = Article::findByTranslatedSlug('my-article-slug', 'ar');

// Find or throw 404
$article = Article::findByTranslatedSlugOrFail('my-article-slug');

// Use as a query scope
$articles = Article::whereTranslatedSlug('my-article-slug')->with('author')->first();

// If your slug column has a different name
$article = Article::findByTranslatedSlug('my-slug', null, 'url_slug');
```

**Example in Controller:**

```
public function show($locale, $slug)
{
    app()->setLocale($locale);

    $article = Article::findByTranslatedSlugOrFail($slug, $locale);

    return view('articles.show', compact('article'));
}
```

Advanced Configuration
----------------------

[](#advanced-configuration)

If your model or table names don't follow the defaults, you can override them:

```
class Article extends Model
{
    use HasTranslations;

    protected $translatable = ['title'];

    // Optional Overrides
    protected $translationModel = \App\Models\Translations\ArticleTrans::class;
    protected $translationForeignKey = 'art_id';
    protected $localeColumn = 'lang';
}
```

License
-------

[](#license)

MIT

Author
------

[](#author)

**Shadi Shammaa**

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance78

Regular maintenance activity

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

9

Last Release

120d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/092a8b57ed995393618ee9dbf2055d43060fef84a2c5b4ef4e305bab3ff5b432?d=identicon)[shadishammaa](/maintainers/shadishammaa)

---

Top Contributors

[![shammaa](https://avatars.githubusercontent.com/u/8601466?v=4)](https://github.com/shammaa "shammaa (8 commits)")

### Embed Badge

![Health badge](/badges/shammaa-laravel-model-translations/health.svg)

```
[![Health](https://phpackages.com/badges/shammaa-laravel-model-translations/health.svg)](https://phpackages.com/packages/shammaa-laravel-model-translations)
```

###  Alternatives

[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[genealabs/laravel-pivot-events

This package introduces new eloquent events for sync(), attach(), detach() or updateExistingPivot() methods on BelongsToMany relation.

1404.9M8](/packages/genealabs-laravel-pivot-events)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[aglipanci/laravel-eloquent-case

Adds CASE statement support to Laravel Query Builder.

115157.2k](/packages/aglipanci-laravel-eloquent-case)

PHPackages © 2026

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