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

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

esign/laravel-underscore-translatable
=====================================

A laravel package to make your eloquent models translatable.

1.12.0(1mo ago)326.0k↓50.6%3MITPHPPHP ^8.1CI passing

Since Nov 14Pushed 1mo ago4 watchersCompare

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

READMEChangelog (10)Dependencies (12)Versions (21)Used By (3)

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

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

[![Latest Version on Packagist](https://camo.githubusercontent.com/3d5c84ebc0d0cde0691bd94317e79abdaa8ad7c89b6e1afa11faa1aae682ae4e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f657369676e2f6c61726176656c2d756e64657273636f72652d7472616e736c617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-underscore-translatable)[![Total Downloads](https://camo.githubusercontent.com/62a9316d4ba0551678b3e24dfdaadc213120f9fa5226bf421dbf4f5cf79c6258/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f657369676e2f6c61726176656c2d756e64657273636f72652d7472616e736c617461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/esign/laravel-underscore-translatable)[![GitHub Actions](https://github.com/esign/laravel-underscore-translatable/actions/workflows/main.yml/badge.svg)](https://github.com/esign/laravel-underscore-translatable/actions/workflows/main.yml/badge.svg)

This package allows you to make eloquent models translatable by using separate columns for each language, e.g. `title_nl` and `title_en`. This package is heavily inspired by Spatie's [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable).

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

[](#installation)

You can install the package via composer:

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

Usage
-----

[](#usage)

### Preparing your model

[](#preparing-your-model)

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

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

class Post extends Model
{
    use UnderscoreTranslatable;

    public $translatable = ['title'];
}
```

Your database structure should look like the following:

```
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title_nl')->nullable();
    $table->string('title_fr')->nullable();
    $table->string('title_en')->nullable();
});
```

### 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->title_nl
$post->getTranslation('title', 'nl')
```

To retrieve all translations, you may use `getTranslations`:

```
$post->getTranslations('title');
// returns ['en' => 'Your first translation', 'nl' => 'Jouw eerste vertaling']
```

If you omit the key, translations for all translatable attributes will be returned:

```
$post->getTranslations();
// returns ['title' => ['en' => '...', 'nl' => '...']]
```

You may also limit the returned locales:

```
$post->getTranslations('title', ['en']);
// returns ['en' => 'Your first translation']
```

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

```
$post->title_en = 'Your first translation';
$post->title_nl = '';
$post->title_fr = null;

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

To retrieve only the locales that have a translated column present for a specific key, use `getTranslatedLocales`:

```
$post->title_en = 'Your first translation';
$post->title_nl = 'Jouw eerste vertaling';

$post->getTranslatedLocales('title'); // returns ['en', '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:

```
$post->title_en = 'Your first translation';
$post->title_nl = 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:

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

### Setting translations

[](#setting-translations)

To set the translation for the current locale you may use the attribute you have defined in the `translatable` property. Or you could pass it immediately when creating a model:

```
$post->title = 'Your first translation';

Post::create([
    'title' => 'Your first translation',
]);
```

You may also use the `setTranslation` method:

```
$post->setTranslation('title', 'en', 'Your first translation');
$post->setTranslation('title', 'nl', 'Jouw eerste vertaling');
```

You could also set multiple translations at once using the `setTranslations` method or immediately passing them along when creating a model:

```
$post->setTranslations('title', [
    'en' => 'Your first translation',
    'nl' => 'Jouw eerste vertaling',
]);

Post::create([
    'title' => [
        'en' => 'Your first translation',
        'nl' => 'Jouw eerste vertaling',
    ],
]);
```

This package does not persist translations to the database, so don't forget to save your model:

```
$post->setTranslation('title', 'en', 'Your first translation');
$post->save();
```

### Defining accessors and mutators

[](#defining-accessors-and-mutators)

You're able to define accessors just like you're used to in Laravel:

```
public function getTitleAttribute($value): string
{
    return ucfirst($value);
}
```

The same goes for mutators:

```
public function setTitleAttribute($value, $locale): void
{
    $this->attributes['title_' . $locale] = strtolower($value);
}
```

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

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

###  Health Score

55

—

FairBetter than 97% of packages

Maintenance91

Actively maintained with recent releases

Popularity31

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 87% 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 ~108 days

Recently: every ~10 days

Total

16

Last Release

44d ago

PHP version history (2 changes)1.0.0PHP ^8.0

1.7.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 (40 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (4 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (2 commits)")

---

Tags

i18nlaravelphptranslationseloquenttranslatableesign

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

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

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

###  Alternatives

[spatie/laravel-sluggable

Generate slugs when saving Eloquent models

1.5k12.4M291](/packages/spatie-laravel-sluggable)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k29.9M42](/packages/kirschbaum-development-eloquent-power-joins)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.0M84](/packages/mongodb-laravel-mongodb)[watson/validating

Eloquent model validating trait.

9743.4M53](/packages/watson-validating)[cybercog/laravel-love

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

1.2k322.4k1](/packages/cybercog-laravel-love)[spiritix/lada-cache

A Redis based, automated and scalable database caching layer for Laravel

592452.8k2](/packages/spiritix-lada-cache)

PHPackages © 2026

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