PHPackages                             esign/laravel-helpermodel-translatable - 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. esign/laravel-helpermodel-translatable

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

esign/laravel-helpermodel-translatable
======================================

A laravel package to make your eloquent models translatable.

1.12.0(1mo ago)0205MITPHPPHP ^8.1CI passing

Since Dec 5Pushed 1mo ago4 watchersCompare

[ Source](https://github.com/esign/laravel-helpermodel-translatable)[ Packagist](https://packagist.org/packages/esign/laravel-helpermodel-translatable)[ Docs](https://github.com/esign/laravel-helpermodel-translatable)[ RSS](/packages/esign-laravel-helpermodel-translatable/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (10)Versions (20)Used By (0)

Make Eloquent models translatable
=================================

[](#make-eloquent-models-translatable)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d7ecb145b4b1b48031bdbec0bbcfd0dc09b398b6bdf4b16ebe081bff588b5e2d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f657369676e2f6c61726176656c2d68656c7065726d6f64656c2d7472616e736c617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-helpermodel-translatable)[![Total Downloads](https://camo.githubusercontent.com/255d64b60a4cc5406a98b5c6422427994a1a87142fe2ec01a9a7227fe9963a4b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f657369676e2f6c61726176656c2d68656c7065726d6f64656c2d7472616e736c617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-helpermodel-translatable)[![GitHub Actions](https://github.com/esign/laravel-helpermodel-translatable/actions/workflows/main.yml/badge.svg)](https://github.com/esign/laravel-helpermodel-translatable/actions/workflows/main.yml/badge.svg)

This package allows you to make eloquent models translatable by using a seperate model for storing translations, e.g. `Post` and `PostTranslation`.

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

[](#installation)

You can install the package via composer:

```
composer require esign/laravel-helpermodel-translatable

```

The package will automatically register a service provider.

Next up, you can publish the configuration file:

```
php artisan vendor:publish --provider="Esign\HelperModelTranslatable\HelperModelTranslatableServiceProvider" --tag="config"

```

The config file will be published as `config/helpermodel-translatable.php` with the following content:

```
return [
    /**
     * These are the default namespaces where the HelperModelTranslatable
     * looks for the helper models. You may pass in either a string
     * or an array, they are tried in order and the first match is used.
     */
    'model_namespaces' => ['App', 'App\\Models'],
];

```

Usage
-----

[](#usage)

### Preparing your model

[](#preparing-your-model)

To make your model translatable you need to use the Esign\\HelperModelTranslatable\\HelperModelTranslatable trait on the model. Next up, you should define which fields are translatable by adding a public $translatable property.

```
use Esign\HelperModelTranslatable\HelperModelTranslatable;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HelperModelTranslatable;

    public $translatable = ['title'];
}

```

Next up, you may create a helper model just like you're used to:

```
use Illuminate\Database\Eloquent\Model;

class PostTranslation extends Model
{
    ...
}

```

### Retrieving translations

[](#retrieving-translations)

To retrieve a translation in the current locale you may use the attribute you have defined in the `translatable` property. Or you could use the `getTranslation` method:

```
$post->title
$post->getTranslation('title')

```

To retrieve a translation in a specific locale you may use the fully suffixed attribute or pass the locale to the `getTranslation` method:

```
$post->getTranslation('title', 'nl')

```

To check if a translated attribute exists, you may use the `hasTranslation` method:

```
PostTranslation::create(['language' => 'en', 'title' => 'Test en', 'tags' => ['🍎', '🍐', '🍋']]);
PostTranslation::create(['language' => 'nl', 'title' => null, 'tags' => []]);
PostTranslation::create(['language' => 'fr', 'title' => '']);

$post->hasTranslation('title', 'en'); // returns true
$post->hasTranslation('title', 'nl'); // returns false
$post->hasTranslation('title', 'fr'); // returns false
$post->hasTranslation('tags', 'en'); // returns true
$post->hasTranslation('tags', 'nl'); // returns false

```

In case you need to check if the actual translation model exists, you may use the `hasTranslationModel` method:

```
PostTranslation::create(['language' => 'en']);

$post->hasTranslationModel('en'); // returns true
$post->hasTranslationModel('nl'); // returns false

```

To retrieve the actual translation model you may use the `getTranslationModel` method:

```
$post->getTranslationModel();
$post->getTranslationModel('nl');

```

In case you do not supply a locale, the current locale will be used.

### Using a fallback

[](#using-a-fallback)

This package allows you to return the value of an attribute's `fallback_locale` defined in the `config/app.php` of your application.

The third `useFallbackLocale` parameter of the `getTranslation` method may be used to control this behaviour:

```
PostTranslation::create(['language' => 'en', 'title' => 'Your first translation']);
PostTranslation::create(['language' => 'nl', 'title' => null]);

$post->getTranslation('title', 'nl', true); // returns 'Your first translation'
$post->getTranslation('title', 'nl', false); // returns null

```

Or you may use dedicated methods for this:

```
PostTranslation::create(['language' => 'en', 'title' => 'Your first translation']);
PostTranslation::create(['language' => 'nl', 'title' => null]);

$post->getTranslationWithFallback('title', 'nl'); // returns 'Your first translation'
$post->getTranslationWithoutFallback('title', 'nl'); // returns null

```

You may configure the fallback locale by overwriting the `getFallbackLocale` method from the `HelperModelTranslatable` trait. The locale that was requested initially is passed as a parameter:

```
use Esign\HelperModelTranslatable\HelperModelTranslatable;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HelperModelTranslatable;

    public $translatable = ['title'];

    public function getFallbackLocale(?string $locale = null): ?string
    {
        return 'fr';
    }
}

```

### Customizing the relationship

[](#customizing-the-relationship)

By convention, this package assumes your helper model follows the same name of your main model suffixed by `Translation`, e.g. `Post` and `PostTranslation`. This model is used to load the `translations` relationship that you may customize by either defining the model / foreign key or by overwriting the relationship alltogether.

```
use Esign\HelperModelTranslatable\HelperModelTranslatable;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HelperModelTranslatable;

    public $translatable = ['title'];

    protected function getHelperModelClass(): string
    {
        return CustomPostTranslation::class;
    }

    protected function getHelperModelForeignKey(): string
    {
        return 'custom_post_id';
    }
}

```

```
use Esign\HelperModelTranslatable\HelperModelTranslatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Post extends Model
{
    use HelperModelTranslatable;

    public $translatable = ['title'];

    public function translations(): HasMany
    {
        return $this->hasMany(PostTranslation::class);
    }
}

```

In case you need to customize the default relationship name you may do so by overwriting the `helperModelRelation` property on your model:

```
use Esign\HelperModelTranslatable\HelperModelTranslatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Post extends Model
{
    use HelperModelTranslatable;

    protected $helperModelRelation = 'otherTranslations';
    public $translatable = ['title'];
}

```

It's also possible to use a different relationship dynamically by using the `useHelperModelRelation` method:

```
$post->useHelperModelRelation('secondaryTranslations')->getTranslation('title');

```

### Scopes

[](#scopes)

This package also ships with a few scopes that allow you to set constraints for the translations relationship:

```
Post::whereTranslation('title', 'Post about dogs');
Post::whereTranslation('title', 'like', '%dogs%');
Post::whereTranslation('title', 'like', '%dogs%', 'nl');
Post::whereTranslation('title', 'like', '%dogs%', ['nl', 'en']);
Post::whereTranslation('title', 'like', '%dogs%')->orWhereTranslation('title', 'like', '%cats%');

Post::translatedIn('nl');
Post::translatedIn(['nl', 'en']);
Post::translatedIn('nl')->orTranslatedIn('en');

```

### Testing

[](#testing)

```
composer test

```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

47

—

FairBetter than 94% of packages

Maintenance89

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 93.5% 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 ~92 days

Recently: every ~278 days

Total

18

Last Release

56d ago

PHP version history (2 changes)1.0.0PHP ^8.0

1.11.0PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/4599d7a8f6fdb63dd04305a49ae5ec9700b7a6eacdbe3a54f89584d75e34503f?d=identicon)[esign](/maintainers/esign)

---

Top Contributors

[![jordyvanderhaegen](https://avatars.githubusercontent.com/u/24370626?v=4)](https://github.com/jordyvanderhaegen "jordyvanderhaegen (43 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (3 commits)")

---

Tags

translationseloquenttranslatableesign

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/esign-laravel-helpermodel-translatable/health.svg)

```
[![Health](https://phpackages.com/badges/esign-laravel-helpermodel-translatable/health.svg)](https://phpackages.com/packages/esign-laravel-helpermodel-translatable)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k7.2M71](/packages/mongodb-laravel-mongodb)[cviebrock/eloquent-sluggable

Easy creation of slugs for your Eloquent models in Laravel

4.0k13.6M253](/packages/cviebrock-eloquent-sluggable)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k25.2M34](/packages/kirschbaum-development-eloquent-power-joins)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[watson/rememberable

Query caching for Laravel

1.1k5.2M13](/packages/watson-rememberable)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)

PHPackages © 2026

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