[Deprecated] A Laravel package for multilingual models

Overview

This package has been deprecated. But worry not. You can use Astrotomic/laravel-translatable.


Laravel-Translatable

Total Downloads Build Status Code Coverage Latest Stable Version License SensioLabsInsight StyleCI

Laravel Translatable

If you want to store translations of your models into the database, this package is for you.

This is a Laravel package for translatable models. Its goal is to remove the complexity in retrieving and storing multilingual model instances. With this package you write less code, as the translations are being fetched/saved when you fetch/save your instance.

Docs

Demo

Getting translated attributes

  $greece = Country::where('code', 'gr')->first();
  echo $greece->translate('en')->name; // Greece
  
  App::setLocale('en');
  echo $greece->name;     // Greece

  App::setLocale('de');
  echo $greece->name;     // Griechenland

Saving translated attributes

  $greece = Country::where('code', 'gr')->first();
  echo $greece->translate('en')->name; // Greece
  
  $greece->translate('en')->name = 'abc';
  $greece->save();
  
  $greece = Country::where('code', 'gr')->first();
  echo $greece->translate('en')->name; // abc

Filling multiple translations

  $data = [
    'code' => 'gr',
    'en'  => ['name' => 'Greece'],
    'fr'  => ['name' => 'Grèce'],
  ];

  $greece = Country::create($data);
  
  echo $greece->translate('fr')->name; // Grèce

Laravel compatibility

Laravel Translatable
5.8 9.*
5.7 9.*
5.6 9.*
5.5 8.*
5.4 7.*
5.3 6.*
5.2 5.5 - 6.*
5.1 5.0 - 6.*
5.0 5.0 - 5.4
4.2.x 4.4.x
4.1.x 4.4.x
4.0.x 4.3.x

Tutorials

Installation in 4 steps

Step 1: Install package

Add the package in your composer.json by executing the command.

composer require dimsav/laravel-translatable

Next, add the service provider to app/config/app.php

Dimsav\Translatable\TranslatableServiceProvider::class,

Step 2: Migrations

In this example, we want to translate the model Country. We will need an extra table country_translations:

Schema::create('countries', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('code');
    $table->timestamps();
});

Schema::create('country_translations', function(Blueprint $table)
{
    $table->increments('id');
    $table->integer('country_id')->unsigned();
    $table->string('name');
    $table->string('locale')->index();

    $table->unique(['country_id','locale']);
    $table->foreign('country_id')->references('id')->on('countries')->onDelete('cascade');
});

Step 3: Models

  1. The translatable model Country should use the trait Dimsav\Translatable\Translatable.
  2. The convention for the translation model is CountryTranslation.
// models/Country.php
class Country extends Eloquent {
    
    use \Dimsav\Translatable\Translatable;
    
    public $translatedAttributes = ['name'];
    protected $fillable = ['code'];
    
    /**
     * The relations to eager load on every query.
     *
     * @var array
     */
    // (optionaly)
    // protected $with = ['translations'];

}

// models/CountryTranslation.php
class CountryTranslation extends Eloquent {

    public $timestamps = false;
    protected $fillable = ['name'];

}

The array $translatedAttributes contains the names of the fields being translated in the "Translation" model.

Step 4: Configuration

We copy the configuration file to our project.

Laravel 5.*

php artisan vendor:publish --tag=translatable 

Laravel 4.*

php artisan config:publish dimsav/laravel-translatable

Note: There isn't any restriction for the format of the locales. Feel free to use whatever suits you better, like "eng" instead of "en", or "el" instead of "gr". The important is to define your locales and stick to them.

Configuration

The config file

You can see the options for further customization in the config file.

The translation model

The convention used to define the class of the translation model is to append the keyword Translation.

So if your model is \MyApp\Models\Country, the default translation would be \MyApp\Models\CountryTranslation.

To use a custom class as translation model, define the translation class (including the namespace) as parameter. For example:

<?php 

namespace MyApp\Models;

use Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model as Eloquent;

class Country extends Eloquent
{
    use Translatable;

    public $translationModel = 'MyApp\Models\CountryAwesomeTranslation';
}

Features list

Please read the installation steps first, to understand what classes need to be created.

Available methods

// Before we get started, this is how we determine the default locale.
// It is set by laravel or other packages.
App::getLocale(); // 'fr' 

// To use this package, first we need an instance of our model
$germany = Country::where('code', 'de')->first();

// This returns an instance of CountryTranslation of using the default locale.
// So in this case, french. If no french translation is found, it returns null.
$translation = $germany->translate();

// It is possible to define a default locale per model by overriding the model constructor.
public function __construct(array $attributes = [])
{
    parent::__construct($attributes);
    
    $this->defaultLocale = 'de';
}

// It is also possible to define a default locale for our model on the fly:
$germany->setDefaultLocale('de');

// If an german translation exists, it returns an instance of 
// CountryTranslation. Otherwise it returns null.
$translation = $germany->translate('de');

// If a german translation doesn't exist, it attempts to get a translation  
// of the fallback language (see fallback locale section below).
$translation = $germany->translate('de', true);

// Alias of the above.
$translation = $germany->translateOrDefault('de');

// Returns instance of CountryTranslation of using the default locale.
// If no translation is found, it returns a fallback translation
// if enabled in the configuration.
$translation = $germany->getTranslation();

// If an german translation exists, it returns an instance of 
// CountryTranslation. Otherwise it returns null.
// Same as $germany->translate('de');
$translation = $germany->getTranslation('de', true);

// To set the translation for a field you can either update the translation model.
// Saving the model will also save all the related translations.
$germany->translate('en')->name = 'Germany';
$germany->save();

// Alternatively we can use the shortcut
$germany->{'name:en'} = 'Germany';
$germany->save();

// There are two ways of inserting mutliple translations into the database
// First, using the locale as array key.
$greece = $country->fill([
    'en'  => ['name' => 'Greece'],
    'fr'  => ['name' => 'Grèce'],
]);

// The second way is to use the following syntax.  
$greece = $country->fill([
    'name:en' => 'Greece',
    'name:fr' => 'Grèce',
]);

// Returns true/false if the model has translation about the current locale. 
$germany->hasTranslation();

// Returns true/false if the model has translation in french. 
$germany->hasTranslation('fr');

// If a german translation doesn't exist, it returns
// a new instance of CountryTranslation.
$translation = $germany->translateOrNew('de');

// Returns a new CountryTranslation instance for the selected
// language, and binds it to $germany
$translation = $germany->getNewTranslation('it');

// The eloquent model relationship. Do what you want with it ;) 
$germany->translations();

// Remove all translations linked to an object
$germany->deleteTranslations();

// Delete one or multiple translations
$germany->deleteTranslations('de');
$germany->deleteTranslations(['de', 'en']);

// Gel all the translations as array
$germany->getTranslationsArray();
// Returns
[
 'en' => ['name' => 'Germany'],
 'de' => ['name' => 'Deutschland'],
 'fr' => ['name' => 'Allemagne'],
];

// Creates a clone and clones the translations
$replicate = $germany->replicateWithTranslations(); 

Available scopes

// Returns all countries having translations in english
Country::translatedIn('en')->get();

// Returns all countries not being translated in english
Country::notTranslatedIn('en')->get();

// Returns all countries having translations
Country::translated()->get();

// Eager loads translation relationship only for the default
// and fallback (if enabled) locale
Country::withTranslation()->get();

// Returns an array containing pairs of country ids and the translated
// name attribute. For example: 
// [
//     ['id' => 1, 'name' => 'Greece'], 
//     ['id' => 2, 'name' => 'Belgium']
// ]
Country::listsTranslations('name')->get()->toArray();

// Filters countries by checking the translation against the given value 
Country::whereTranslation('name', 'Greece')->first();

// Filters countries by checking the translation against the given value, only in the specified locale
Country::whereTranslation('name', 'Greece', 'en')->first();

// Or where translation
Country::whereTranslation('name', 'Greece')->orWhereTranslation('name', 'France')->get();

// Filters countries by checking the translation against the given string with wildcards
Country::whereTranslationLike('name', '%Gree%')->first();

// Or where translation like
Country::whereTranslationLike('name', '%eece%')->orWhereTranslationLike('name', '%ance%')->get();

Magic properties

To use the magic properties, you have to define the property $translatedAttributes in your main model:

class Country extends Eloquent {

    use \Dimsav\Translatable\Translatable;

    public $translatedAttributes = ['name'];
}
// Again we start by having a country instance
$germany = Country::where('code', 'de')->first();

// We can reference properties of the translation object directly from our main model.
// This uses the default locale and is the equivalent of $germany->translate()->name
$germany->name; // 'Germany'

// We can also quick access a translation with a custom locale
$germany->{'name:de'} // 'Deutschland'

Fallback

Fallback locales

If you want to fallback to a default translation when a translation has not been found, enable this in the configuration using the use_fallback key. And to select the default locale, use the fallback_locale key.

Configuration example:

return [
    'use_fallback' => true,

    'fallback_locale' => 'en',    
];

You can also define per-model the default for "if fallback should be used", by setting the $useTranslationFallback property:

class Country {

    public $useTranslationFallback = true;

}

Fallback per property

Even though we try having all models nicely translated, some fields might left empty. What's the result? You end up with missing translations for those fields!

The property fallback feature is here to help. When enabled, translatable will return the value of the fallback language for those empty properties.

The feature is enabled by default on new installations. If your config file was setup before v7.1, make sure to add the following line to enable the feature:

'use_property_fallback' => true,

Of course the fallback locales must be enabled to use this feature.

If the property fallback is enabled in the configuration, then translatable will return the translation of the fallback locale for the fields where the translation is empty.

customize empty translation property detection

This package is made to translate strings, but in general it's also able to translate numbers, bools or whatever you want to. By default a simple empty() call is used to detect if the translation value is empty or not. If you want to customize this or use different logic per property you can override isEmptyTranslatableAttribute() in your main model.

protected function isEmptyTranslatableAttribute(string $key, $value): bool
{
    switch($key) {
        case 'name':
            return empty($value);
        case 'price':
            return !is_number($value);
        default:
            return is_null($value);
    }
}

Country based fallback

Since version v5.3 it is possible to use country based locales. For example, you can have the following locales:

  • English: en
  • Spanish: es
  • Mexican Spanish: es-MX
  • Colombian Spanish: es-CO

To configuration for these locales looks like this:

    'locales' => [ 
        'en',
        'es' => [
            'MX',
            'CO',
        ],
    ];

We can also configure the "glue" between the language and country. If for instance we prefer the format es_MX instead of es-MX, the configuration should look like this:

   'locale_separator' => '_',

What applies for the fallback of the locales using the en-MX format?

Let's say our fallback locale is en. Now, when we try to fetch from the database the translation for the locale es-MX but it doesn't exist, we won't get as fallback the translation for en. Translatable will use as a fallback es (the first part of es-MX) and only if nothing is found, the translation for en is returned.

Translation Autoloading

If the toArray() method is called it's possible to autoload all translations. To control this feature the package comes with a config value to_array_always_loads_translations and three static methods in the trait:

  • enableAutoloadTranslations() - forces to load all translations
  • disableAutoloadTranslations() - disables autoload and returns parent attributes
  • defaultAutoloadTranslations() - does not change the default behavior logic (default)

Add ons

Thanks to the community a few packages have been written to make usage of Translatable easier when working with forms:

FAQ

I need some example code!

Examples for all the package features can be found in the code used for the tests.

I need help!

Got any question or suggestion? Feel free to open an Issue.

I want to help!

You are awesome! Watch the repo and reply to the issues. You will help offering a great experience to the users of the package. #communityWorks

Also buy me a beer by making a donation. ❤️

I am getting collisions with other trait methods!

Translatable is fully compatible with all kinds of Eloquent extensions, including Ardent. If you need help to implement Translatable with these extensions, see this example.

How do I migrate my existing table to use laravel-translatable?

Please see the installation steps to understand how your database should be structured.

If your properties are written in english, we recommend using these commands in your migrations:

// We insert the translation attributes into the fresh translated table: 
\DB::statement("insert into country_translations (country_id, name, locale) select id, name, 'en' from countries");

// We drop the translation attributes in our main table: 
Schema::table('countries', function ($table) {
    $table->dropColumn('name');
}); 

How do I sort by translations?

A tip here is to make the MySQL query first and then do the Eloquent one.

To fetch a list of records ordered by a translated field, you can do this:

SELECT * from countries
JOIN country_translations as t on t.country_id = countries.id 
WHERE locale = 'en'
GROUP BY countries.id
ORDER BY t.name desc

The corresponding eloquent query would be:

Country::join('country_translations as t', function ($join) {
        $join->on('countries.id', '=', 't.country_id')
            ->where('t.locale', '=', 'en');
    }) 
    ->groupBy('countries.id')
    ->orderBy('t.name', 'desc')
    ->with('translations')
    ->get();

How can I select a country by a translated field?

For example, let's image we want to find the Country having a CountryTranslation name equal to 'Portugal'.

Country::whereHas('translations', function ($query) {
    $query->where('locale', 'en')
    ->where('name', 'Portugal');
})->first();

You can find more info at the Laravel Querying Relations docs.

Why do I get a mysql error while running the migrations?

If you see the following mysql error:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'my_database.#sql-455_63'
  (errno: 150) (SQL: alter table `country_translations` 
  add constraint country_translations_country_id_foreign foreign key (`country_id`) 
  references `countries` (`id`) on delete cascade)

Then your tables have the MyISAM engine which doesn't allow foreign key constraints. MyISAM was the default engine for mysql versions older than 5.5. Since version 5.5, tables are created using the InnoDB storage engine by default.

How to fix

For tables already created in production, update your migrations to change the engine of the table before adding the foreign key constraint.

public function up()
{
    DB::statement('ALTER TABLE countries ENGINE=InnoDB');
}

public function down()
{
    DB::statement('ALTER TABLE countries ENGINE=MyISAM');
}

For new tables, a quick solution is to set the storage engine in the migration:

Schema::create('language_translations', function(Blueprint $table){
  $table->engine = 'InnoDB';
  $table->increments('id');
    // ...
});

The best solution though would be to update your mysql version. And always make sure you have the same version both in development and production environment!

Donations

This software has been crafted with attention and love.

Show your love and support by sending bitcoin to this address: 167QC4XQ3acgbwVYWAdmS81jARCcVTWBXU

Or by sending to this PayPal address: [email protected]

❤️ Thank you!

Comments
  • Translations are not saved when using Baum\Node

    Translations are not saved when using Baum\Node

    Hi,

    in my project I need to create a model that uses both a nested tree structured and translations. To translate the model I use your package. The nested set structure is provided by https://github.com/etrepat/baum.

    If my model extends Baum/Node the translations are not saved at all.

    <?php
    
    use Dimsav\Translatable\Translatable;
    
    class Category extends Baum\Node
    {
        use Translatable;
    
        protected $guarded = array('id', 'url');
    
        public $translatedAttributes = ['name', 'url'];
        public $translationModel = 'CategoryTranslation';
    
    }
    

    When changing Baum/Node to Eloquent the translations are saved correctly.

    How can this problem be solved?

    inactive 
    opened by freekmurze 33
  • How to check if there's a translation

    How to check if there's a translation

    Hello,

    This might be a stupid question, but I'd like to check if there's a translation before echoing, to avoid the Trying to get property of non-object error.

    I've tried:

    isset($page->translate($lang)->title) ? $page->translate($lang)->title : ''
    
    is_object($page->translate($lang)) ? $page->translate($lang)->title : ''
    
    $page->translate($lang) ? $page->translate($lang)->title : ''
    

    None work.

    Since the a certain version, when a translation doesn't exists, it doesn't return an empty string. It might be nice to return an empty string of no translation exists in the db for that language, to avoid having to make these checks in views all the time.

    Thank you.

    feature 
    opened by nWidart 30
  • Need help with creating a post using this translatable package

    Need help with creating a post using this translatable package

    I've followed this tutorial for build a translatable logic: https://mydnic.be/post/how-to-build-an-efficient-and-seo-friendly-multilingual-architecture-for-your-laravel-application

    Right now if I put manually records in the database by using a command from here: https://github.com/mydnic/Laravel-Multilingual-SEO-Example/blob/master/app/Console/Commands/InsertDummyPosts.php

    I can retrieve the translated posts succesfully, but how can I create a content end edit using the two tables method with translate package?

    This is my code:

    PostsController

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Post;
    use App\User;
    use Session;
    use Illuminate\Support\Facades\Auth;
    
    class PostsController extends Controller
    {
        /**
         * Display a listing of the resource.
         *
         * @return \Illuminate\Http\Response
         */
        public function index()
        {
            $posts = Post::orderBy('id', 'desc')->paginate(5);
            return view('admin.posts.index', compact('posts'));
        }
    
        /**
         * Show the form for creating a new resource.
         *
         * @return \Illuminate\Http\Response
         */
        public function create()
        {
            return view('admin.posts.create');
        }
    
        /**
         * Store a newly created resource in storage.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return \Illuminate\Http\Response
         */
        public function store(Request $request)
        {
          $this->validate($request, [
            'title' => 'required',
            'body' => 'required',
          ]);
    
          $input = $request->all();
          $user = Auth::user();
    
          $user->posts()->create($input);
    
          session()->flash('created_post', 'The post has been created');
    
          return redirect('/en/admin/posts');
    
          // This wont work because it's trying to save the post in posts table, instead of post_translations table.
        }
    
        /**
         * Display the specified resource.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function show($id)
        {
            //
        }
    
        /**
         * Show the form for editing the specified resource.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function edit($id)
        {
            //
        }
    
        /**
         * Update the specified resource in storage.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function update(Request $request, $id)
        {
            //
        }
    
        /**
         * Remove the specified resource from storage.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function destroy($id)
        {
            //
        }
    
        public function posts() {
          $posts = Post::orderBy('id', 'desc')->paginate(5);
    
          return view('posts', compact('posts'));
        }
    
        public function post($slug) {
          
          $post = Post::whereTranslation('slug', $slug)->firstOrFail();
    
          return view('post', compact('post'));
        }
    }
    
    

    From the code you can see the store method and that's working only if I store in one database without translatable package. I need help to change that.

    The Post model:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    use Dimsav\Translatable\Translatable;
    
    class Post extends Model
    {
        use Translatable;
    
        public $translatedAttributes = ['title', 'slug', 'body'];
    
        protected $fillable = ['title', 'slug', 'body', 'status', 'locale'];
    
        public function user() {
          return $this->belongsTo('App\User');
        }
    
        public function posts() {
          return $this->hasMany('App\Post');
        }
    }
    
    

    The PostTranslate model:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    use Cviebrock\EloquentSluggable\Sluggable;
    
    class PostTranslation extends Model
    {
        use Sluggable;
    
        public $timestamps = false;
        protected $fillable = ['title', 'slug', 'body', 'status', 'locale'];
    
        /**
         * Return the sluggable configuration array for this model.
         *
         * @return array
         */
         public function sluggable()
        {
            return [
                'slug' => [
                    'source' => 'title'
                ]
            ];
        }
    }
    

    The User model:

    <?php
    
    namespace App;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password', 'role_id', 'status',
        ];
    
        /**
         * The attributes that should be hidden for arrays.
         *
         * @var array
         */
        protected $hidden = [
            'password', 'remember_token',
        ];
    
        public function role(){
            return $this->belongsTo('App\Role');
        }
    
        public function isAdmin() {
          if($this->role->name == 'Administrator') {
            return true;
          }
          return false;
        }
    
        public function posts() {
          return $this->hasMany('App\Post');
        }
    }
    
    

    database/migrations/2017_09_26_140138_create_posts_table.php

    <?php
    
    use Illuminate\Support\Facades\Schema;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class CreatePostsTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('posts', function (Blueprint $table) {
                $table->increments('id');
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('posts');
        }
    }
    

    database/migrations/2017_09_26_140327_create_post_translations_table.php

    <?php
    
    use Illuminate\Support\Facades\Schema;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    class CreatePostTranslationsTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('post_translations', function (Blueprint $table) {
                $table->increments('id');
                $table->integer('post_id')->unsigned();
                $table->string('locale')->index();
    
                // The actual fields to store the content of your entity. You can add whatever you need.
                $table->string('title');
                $table->string('slug')->unique();
                $table->text('body');
                $table->integer('status')->default(0);
    
                $table->unique(['post_id', 'locale']);
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('post_translations');
        }
    }
    

    resources/view/admin/posts/create.blade.php

    @extends('layouts.backend')
    
    @section('content')
      @include('includes.tinymce')
      <h1>Create post</h1>
      <form action="/en/admin/posts" method="post" enctype="multipart/form-data">
        {{ csrf_field() }}
        <div class="form-group">
          <label>Title</label>
          <input type="text" name="title" class="form-control" value="{{old('title')}}">
        </div>
        <div class="form-group">
          <label>Body</label>
          <textarea name="body" class="form-control" rows="10">{{old('body')}}</textarea>
        </div>
        <div class="form-group">
          <label>Language</label>
          <select name="locale">
            <option value="en">English</option>
            <option value="fr">French</option>
          </select>
        </div>
        <div class="form-group">
          <label>Status</label>
          <select name="status" class="form-control">
            <option value="1">Published</option>
            <option value="0">Draft</option>
          </select>
        </div>
        <div class="form-group">
          <input type="submit" class="btn btn-primary" value="Create post">
        </div>
      </form>
      @include('includes.errors')
    @endsection
    

    Any help is appreciated.

    And another thing: How can I retrieve the local language into the links?

    Lets say I have a link for creating a new page: href="/admin/posts/create"

    How can I set like this?

    href="/en/admin/posts/create"

    or

    href="/fr/admin/posts/create"

    depends from the chosen language. Is there any variable I can use here?

    opened by emco83 23
  • can't add translations

    can't add translations

    Hello, i'm trying to add translations from json, but they aren't saving.

    i send data like this:

    en: {summary: "random summary"} ru: {summary: "random summary"}

    it creates new record, but without translations. any ideas?

    opened by giokaxo 23
  • Laravel 5 Validations

    Laravel 5 Validations

    Hi, Thanks a lot for this nice package. I'm using Laravel 5.1, please is there a way to validate fooTranslation attributes ? For example I have the attribute 'name' required and unique in 'foo' model, so how can I update it with this validation ? Example :

    class Foo extends Model { use Translatable;
    protected $table = 'foos'; public $translatedAttributes = ['name', 'description'];

    feature todo 
    opened by AEK-BKF 18
  • Set Locale method not working

    Set Locale method not working

    Hi, First of all, thanks for this amazing package, very useful here in Belgium ;-) ! IO have a little bug when I try to print a translated field like this: echo $article->title;

    The app doesn't use the current locale.

    I set the locale like that in my controller: App::setLocale('fr');

    Inside the view:

    This prints 'fr': app()->getLocale()

    This works : $article->translate('fr')->title

    But not if I use the shortcut directly.

    Thanks for your help !

    opened by ConstantMath 16
  • How to translate pivot values?

    How to translate pivot values?

    I couldn't find a way to translate pivot values from ManyToMany relationships. In my case, I have a Combination model and an Attribute model which are connected together with a belongsToMany relationship and a pivot value as shown below:

    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Combination extends Model {
       public function product() {
          return $this->belongsTo('App\Product');
       }
    
       public function product_attributes() {
          return $this->belongsToMany('App\Attribute')->withPivot('value');
       }
    }
    

    The attribute_combination intermediate table looks like this:

    +--------------+----------------+-------+ 
    | attribute_id | combination_id | value |
    |--------------+----------------+-------|
    | 1            | 1              | Black |
    | 2            | 1              | M     |
    | 1            | 2              | Black |
    | 2            | 2              | L     |
    +--------------+----------------+-------+
    

    Is there a way to retrieve the translation of this pivot value?

    opened by marcbelletre 15
  • Is there are reason why the saved/updated events are fired even when there are no changes?

    Is there are reason why the saved/updated events are fired even when there are no changes?

    I'm using laravel-translatable with laravel-auditing in a single model which causes auditing to create a log entry even though there are no changes.

    https://github.com/owen-it/laravel-auditing/issues/221

    bug todo 
    opened by wyred 14
  • Add getFillable() method

    Add getFillable() method

    This PR adds translatable attributes to the $fillable list when requested through getFillable() (which is the recommended way to access the $fillable property.

    Moreover, this method is very handy to filter out unwanted request input by simply using $request->only(Model::getFillable()).

    By implementing this PR, Laravel Translatable integrates even more gracefully in the fillable features of Eloquent.

    opened by Propaganistas 14
  • Cannot retrieve all locales info to use in Laravel Form::model bind technique.

    Cannot retrieve all locales info to use in Laravel Form::model bind technique.

    Is there a way that I can simply do $country->all(), and the return will retrieve all correct data in arrays to fill in automatically my Form::model binding ?

    PS: Sorry for open a Issue, I don't know any extra place that I could put my doubts out!

    opened by jonathanpmartins 14
  • Disable translations for specific query

    Disable translations for specific query

    Here is my case: I have product which have a categories. When I edit the product I don't want to get translated categories. I want only category.id How can I achieve that?

    Here is what I'm doing now:

    $product = Product::select('id', 'sku',...)
    ->with(['categories' => function ($query) {
                            $query->select(['categories.id']);
                        }])
    ->where('id', $id)
    ->first();
    

    But I'm getting categories with their translations. Is it possible for that query only to get categories without translations?

    question help wanted next release 
    opened by rafailml 13
Releases(v10.0.0)
  • v10.0.0(Jun 3, 2019)

  • v9.5.0(Jun 3, 2019)

  • v9.4.0(Feb 28, 2019)

  • v9.3.0(Feb 3, 2019)

  • v9.2.0(Sep 6, 2018)

  • v9.1.0(Aug 7, 2018)

    • Do not call get translation with fallback locale and fallback enabled #502
    • Allow translateOrDefault() and translateOrNew() to default to user app locale #500
    • Change autoload translations behavior on runtime #501
    • Use fallback in attributesToArray() #503
    • Added orderByTranslation() scope #504
    • Example in doc for locale filtering in whereTranslation() scope #487
    • Fire saving event in every case #457
    • Allow to change default translation model namespace from config file #508
    Source code(tar.gz)
    Source code(zip)
  • v9.0(Feb 10, 2018)

  • v8.1(Jan 4, 2018)

    v. 8.1

    • Fixed error when fallback not available. #422
    • Fixed withTranslation query scope performance #417
    • Fixed fallback for country-based locales #417
    • Fixed empty attribute values #410
    Source code(tar.gz)
    Source code(zip)
  • v8.0(Sep 1, 2017)

  • v7.3(Jun 18, 2017)

  • v7.2.1(Jun 7, 2017)

  • v7.2(Jun 7, 2017)

    v. 7.2

    • Added replicateWithTranslations(). #346
    • Added orWhereTranslation and orWhereTranslationLike scopes. #338
    • Added support for laravel auto-discovery. #359
    • Added tag for publishing the config file. #360
    Source code(tar.gz)
    Source code(zip)
  • v7.1(Jun 6, 2017)

    v. 7.1

    • Added fallback per attribute. #348
    • Added getTranslationsArray() #347
    • Fixed filling 'property:locale' format was not validating the locale. #356
    Source code(tar.gz)
    Source code(zip)
  • v7.0(Jan 29, 2017)

  • v6.1(Jan 28, 2017)

    v. 6.1

    • Filling a model now supports using the 'property:locale' format in keys. #314 For example:
    $country->fill(['name:en' => 'Belgium']);
    
    • Added config to skip translations in toArray() for better performance when needed. #315
    Source code(tar.gz)
    Source code(zip)
  • v6.0.1(Aug 19, 2016)

  • v6.0(Aug 17, 2016)

    • Translated fillable properties should only be defined in the translation model.
      • To update from version 5, move all the fillable properties belonging to a translation to the corresponding translation models.
    • Added deleteTranslations() method for conveniently deleting translations
    Source code(tar.gz)
    Source code(zip)
  • v5.6.1(Aug 17, 2016)

  • v5.6(Apr 21, 2016)

  • v5.5.1(Apr 10, 2016)

  • v5.5(Feb 7, 2016)

    • Added Laravel 5.2 support
    • Dropped Laravel 5.0 support
    • Added scope whereTranslationLike() #183
    • Fire 'updated' event when saving translations. #190
    • setAttribute() returns the model itself, which is now the default in eloquent. #201
    Source code(tar.gz)
    Source code(zip)
  • v5.4(Nov 15, 2015)

  • v5.3(Oct 23, 2015)

    Changes

    • Added country based fallback #169
    • Added whereTranslation() scope. #168

    Country based fallback

    It is now possible to use country based locales. For example, you can have the following locales:

    • English: en
    • Spanish: es
    • Mexican Spanish: es-MX
    • Colombian Spanish: es-CO

    To configuration for these locales looks like this:

        'locales' => [ 
            'en',
            'es' => [
                'MX',
                'CO',
            ],
        ];
    

    We can also configure the "glue" between the language and country. If for instance we prefer the format es_MX instead of es-MX, the configuration should look like this:

       'locale_separator' => '_',
    

    What applies for the fallback of the locales using the en-MX format?

    Let's say our fallback locale is en. Now, when we try to fetch from the database the translation for the locale es-MX but it doesn't exist, we won't get as fallback the translation for en. Translatable will use as a fallback es (the first part of es-MX) and only if nothing is found, the translation for en is returned.

    Source code(tar.gz)
    Source code(zip)
  • v5.2(Oct 18, 2015)

  • v5.1.2(Oct 17, 2015)

    Fixed

    • Db in tests is dropped and recreated to make tests more stable (https://github.com/dimsav/laravel-translatable/commit/3cc29a21c27726a2d14463b3ec0d55c26487eb58)
    • Bug when using syntax $country->{'name:en'} and locale doesn't exist #150

    Changed

    • Method isTranslationAttribute() is now public #151
    Source code(tar.gz)
    Source code(zip)
  • v5.1.1(Sep 24, 2015)

  • v5.1(May 7, 2015)

  • v5.0.1(Mar 6, 2015)

  • v5.0(Feb 13, 2015)

  • v4.5(Jan 30, 2015)

    v. 4.5

    • Added scope to list translated attributes in the current locale.
    • Force fire "saved" event when the original model is not saved, but the translation is. #85
    Source code(tar.gz)
    Source code(zip)
Owner
Dimitris Savvopoulos
Dimitris Savvopoulos
Easy multilingual urls and redirection support for the Laravel framework

Linguist - Multilingual urls and redirects for Laravel This package provides an easy multilingual urls and redirection support for the Laravel framewo

Tanel Tammik 189 Jul 18, 2022
Trait for multilingual resource file support

⚡ Usage This library supports MultilingualResourceTrait which can be used in PluginBase. Multilingual support of resource files is possible using this

PocketMine-MP projects of PresentKim 1 Jun 7, 2022
Making Eloquent models translatable

A trait to make Eloquent models translatable This package contains a trait to make Eloquent models translatable. Translations are stored as json. Ther

Spatie 1.9k Jan 7, 2023
Package to manage Laravel translations locally

Translation Manager For Laravel Easy to use package that helps you with the translation of your Laravel application locally. Features ✅ Check all loca

null 5 Jan 8, 2022
List of 77 languages for Laravel Framework 4, 5, 6, 7 and 8, Laravel Jetstream , Laravel Fortify, Laravel Cashier and Laravel Nova.

Laravel Lang In this repository, you can find the lang files for the Laravel Framework 4/5/6/7/8, Laravel Jetstream , Laravel Fortify, Laravel Cashier

Laravel Lang 6.9k Dec 29, 2022
pH7CMS Internationalization package.

?? pH7CMS Internationalization (I18N) package ?? Get new languages for your pH7CMS website!

pH7 Social Dating CMS (pH7CMS) 18 Oct 5, 2022
Composer package providing translation features for PHP apps

PHP translation This is a composer package providing translation support for PHP applications. It is similar to gettext, in usage, with these differen

Sérgio Carvalho 0 Aug 15, 2022
This package allows to translate text using Google Translator for free without api.

Text Translator for PHP This package allows text translation using Google Translate for free without an API. It extracts the translated text from the

The Jano 3 Nov 7, 2022
75 languages support for Laravel 5 application based on Laravel-Lang/lang.

Laravel-lang 75 languages support for Laravel 5 application based on Laravel-Lang/lang. Features Laravel 5+ && Lumen support. Translations Publisher.

安正超 1.3k Jan 4, 2023
Easy localization for Laravel

Laravel Localization Easy i18n localization for Laravel, an useful tool to combine with Laravel localization classes. The package offers the following

Marc Cámara 3k Jan 4, 2023
Better translation management for Laravel

Better localization management for Laravel Introduction Keeping a project's translations properly updated is cumbersome. Usually translators do not ha

Waavi 354 Dec 18, 2022
Support multiple language resources for Laravel

Laratrans Support multiple language resources for Laravel. Docs Installation composer require lechihuy/laratrans After you install the package success

Lê Chí Huy 3 Dec 21, 2021
Laravel translation made __('simple').

Translation.io client for Laravel 5.5+/6/7/8 Add this package to localize your Laravel application. Use the official Laravel syntax (with PHP or JSON

Translation.io 109 Dec 29, 2022
🎌 Laravel Localization Helper :: Easily add translation variables from Blade templates.

LocalizationHelper Package for convenient work with Laravel's localization features and fast language files generation. Take a look at contributing.md

Awes.io 36 Jul 18, 2022
Manage Laravel translation files

Laravel 5 Translation Manager For Laravel 4, please use the 0.1 branch! This is a package to manage Laravel translation files. It does not replace the

Barry vd. Heuvel 1.5k Jan 4, 2023
A GUI for managing JSON translation files in your laravel projects.

Laravel Language Manager Langman is a GUI for managing your JSON language files in a Laravel project. Installation Begin by installing the package thr

Mohamed Said 515 Nov 30, 2022
A Gui To Manage Laravel Translation Files

Lingo A file based translation manager, which unlike other Lang managers don't need a database connection to handle the translation. Installation comp

Muah 97 Dec 5, 2022
Generates a vue-i18n compatible include file from your Laravel translations

This is fork of martinlindhe/laravel-vue-i18n-generator to give Laravel 8+ support for this excellent package.

Alefe Souza 1 Nov 11, 2021
A Laravel package for multilingual models

Introduction If you want to store translations of your models into the database, this package is for you. This is a Laravel package for translatable m

Astrotomic 974 Dec 23, 2022
Laravel Multilingual Models

Laravel Multilingual Models Make Eloquent model attributes translatable without separate database tables for translation values. Simply access $countr

Guido Cella 2 Feb 8, 2022