Notice: originally written in January 2017, article was updated in October 2019, with latest information about the packages and removing the ones that are no longer maintained.


Laravel framework has quite a simple localization function – you can put language translations in resources/lang folder. But it’s not convenient to edit them in the code, so there are many packages that help make this process more effective. Let’s review the most popular ones.

There will be three groups of packages:

  • Visual resources/lang Translation Managers
  • Packages for Multi-Language Models
  • Other Non-visual Translation Packages

First – how translations work in Laravel

Let’s start with recap of the basics – how you can use translations without any packages.

Basically, four things:

1. Language folders

You create your language folders in resources/lang – for example, resources/lang/en and resources/lang/de.

2. Language files

In each of those folders you create a file or files where you store arrays of translations in key-value mode.
Same file in different language folders should have the same filename.

Example – resources/lang/en/words.php:

return [
    'page_title' => 'QuickAdmin page',
    'page_description' => 'Best page in the world'
];

Example – resources/lang/de/words.php:

return [
    'page_title' => 'QuickAdmin Seite',
    'footer'     => 'Beste Seite der Welt'
];

3. You define current active language, otherwise called ‘locale’

It should be one of your folder names – in this case, ‘en’ or ‘de’.
First, there is a default setting in config/app.php:

'locale' => 'en',

But you can override it by setting the local like this anywhere in your code:

App::setLocale($locale);

Also, you can define the locale according to the routes, like this:

Route::get('welcome/{locale}', function ($locale) {
    App::setLocale($locale);
});

4. Actually using the translations in Controller or View

To view the actual word from the translation file or assign it to some variable, you should call function trans():

trans('words.page_title');

Depending on the locale you have set, the system will return ‘QuickAdmin page’ or ‘QuickAdmin Seite’. The parameter of trans() function is a string that consists of two parts – filename, then dot symbol (.) and then array key that you want to use. In our case – words and page_title.

You can also save translations in a different format – in JSON-based files, with undescore function __(‘Login’) to reach them. Read more in this article: Laravel JSON-based Translations with Underscores __() Function.

More about general localization – in the official Laravel documentation.

Now, how can we make it more convenient? Let’s get to the useful packages.

All of the packages mentioned are actively maintained, and updated at least once in last few months.
For each of the packages, I will provide URL, author, and the date of first release. I think it’s really useful, judging about package’s popularity or how well it is maintained.


Group 1. Visual resources/lang Translation Managers

1. barryvdh/laravel-translation-manager

URL: https://github.com/barryvdh/laravel-translation-manager
Author: Barry vd. Heuvel
First release: June 2014

This is one of the oldest translation managers with a graphical interface. Basically, that’s what you get with this package – an adminpanel where you can visually edit your translations (temporarily saved in the database) and then sync with Laravel files.

Typical workflow:
– Import translations: Read all translation files and save them in the database
– Find all translations in php/twig sources
– Optionally: Listen to missing translation with the custom Translator
– Translate all keys through the webinterface
– Export: Write all translations back to the translation files.

Here’s how it looks visually:

barry-translation-manager

So you can go to translate your constants via URL /translations, which is by default not guarded by any password but you can do it quite easily. Or, alternatively, there are a few Artisan commands:

php artisan translations:import

The import command will search through lang files and load all strings in the database, so you can easily manage them.

php artisan translations:export [group]

The export command will write the contents of the database back to lang php files. This will overwrite existing translations and remove all comments, so make sure to backup your data before using. You can also divide translations by groups, and supply the group name to define which groups you want to publish.

This approach is quite convenient, and it solves quite a big problem – giving the clients a convenient way to edit the translations without any help of the developer, except for publishing it back to the Laravel app.

That said, I would be cautious with such automatic import/export and would make a backup of files before any overwrite, as the author says himself.


2. joedixon/laravel-translation

URL: https://github.com/joedixon/laravel-translation
Author: Joe Dixon
First release: September 2018

This is relatively new package. It provides user interface to add new languages and add and update translations. On top of that, there are Artisan commands to manage your translations and scan your application for missing translations.

After installation, all you need to do is to go to /languages URL (which may be configurable and also protected by Middleware) and you will see an awesome translation adminpanel, powered by Laravel + Vue.js:

Package supports file or database drivers to store the translations.

I’ve also done a video review of this package:


Group 2. Packages for Multi-Language Models

3. spatie/laravel-translatable

URL: https://github.com/spatie/laravel-translatable
Author: Spatie
First release: April 2016

One of the most popular packages, its author Freek has article about it: Making Eloquent models translatable

This package contains a trait to make Eloquent models translatable. Translations are stored as json. There is no extra table needed to hold them.

After installation, all you need to do is this in your Model:

use Spatie\Translatable\HasTranslations;

class NewsItem extends Model
{
    use HasTranslations;
    
    public $translatable = ['name'];
}

And then this is how you manipulate the translations:

$newsItem = new NewsItem; // This is an Eloquent model
$newsItem
   ->setTranslation('name', 'en', 'Name in English')
   ->setTranslation('name', 'nl', 'Naam in het Nederlands')
   ->save();
   
$newsItem->name; // Returns 'Name in English' given that the current app locale is 'en'
$newsItem->getTranslation('name', 'nl'); // returns 'Naam in het Nederlands'

app()->setLocale('nl');

$newsItem->name; // Returns 'Naam in het Nederlands'

4. Astrotomic/laravel-translatable (ex. dimsav/laravel-translatable)

URL: https://github.com/Astrotomic/laravel-translatable
Authors: Tom Witkowski | Dimitrios Savvopoulos
First release: February 2014

If we want translatable Models, like multi-language product catalog or a blog, this is one of the biggest package in this list. Note that it changed the owner in summer 2019. In terms of downloads, more than 1 million is really impressive.

Basically, this package works like this:

  • For every model you create additional database table with name [model]_translations and model [Model]Translation
  • Your main model should use Trait of the package and has a property $translatedAttributes
  • Then you can get translations with a code like this:
$greece = Country::where('code', 'gr')->first();
echo $greece->translate('en')->name; // Greece

Also you can fill in the translations like this:

$greece->translate('en')->name = 'abc';
$greece->save();

Now, if you want to do something custom like searching for specific string in specific language, or order by translation value, you need to write Eloquent queries, like this one:

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

There are more useful methods available, like translateOrDefault(), hasTranslation(), scopes like translatedIn() etc. To be honest, this package would deserve a separate review, so we will leave it for you to read the whole Readme file.

All in all, I’m not surprised this package is so popular. It even has its tutorial on the official Laravel blog Laravel News and two packages created additionally by the community:


Group 3. Other Non-visual Translation Packages

5. mcamara/laravel-localization

URL: https://github.com/mcamara/laravel-localization
Author: Marc Cámara
First release: January 2014

One of the most popular packages in this list. Basically, it takes care of multi-language routing, URLs and Middleware.

Here’s how your routes/web.php file should look:

    Route::group(['prefix' => LaravelLocalization::setLocale()], function()
    {
        /** ADD ALL LOCALIZED ROUTES INSIDE THIS GROUP **/
        Route::get('/', function()
        {
            return View::make('hello');
        });

        Route::get('test',function(){
            return View::make('test');
        });
    });

    /** OTHER PAGES THAT SHOULD NOT BE LOCALIZED **/

Once this route group is added to the routes file, a user can access all locales added into supportedLocales, which is set in configuration.

Also, you can use Middleware to redirect all “non-localized” routes to the corresponding “localized”:

    Route::group(
    [
        'prefix' => LaravelLocalization::setLocale(),
        'middleware' => [ 'localeSessionRedirect', 'localizationRedirect' ]
    ],
// ...

The coolest feature of the package, in my opinion, is Translated Routes – for example, you want to have URL /en/article/5 for English language, and /de/artikel/5 for German language. I mean, different slugs here. It’s possible with this package!

    Route::get(LaravelLocalization::transRoute('routes.view'),function($id){
          return View::make('view',['id'=>$id]);
    });

Finally, there’s a big set of helpers and functions like getLocalizedURL(), getURLFromRouteNameTranslated() and others. So you can call the helpers directly from your views to form the correct links or redirect to the intended page.

So this is a really nice package overall – no wonder it’s so popular.


6. spatie/laravel-translation-loader

URL: https://github.com/spatie/laravel-translation-loader/
Author: Spatie
First release: October 2016

There is a short tutorial about this package, written by the author on his popular blog, but I will summarize it for you.

Basically, all the package does is storing the translations in the database and using LanguageLine model to manage them.

So if you want to store all your resources/lang contents in the database, you should create line-by-line, like this:

use Spatie\TranslationLoader\LanguageLine;

LanguageLine::create([
   'group' => 'validation',
   'key' => 'required',
   'text' => ['en' => 'This is a required field', 'nl' => 'Dit is een verplicht veld'],
]);

And then, whenever you call trans(‘validation.required’); – the package will check, if there is a value in the database, if not – then will load the translation from resources/lang/[locale]/validation.php file, as usual.

Also, the package allows you to create your own storing methods and extend the functionality.


7. Waavi/translation

URL: https://github.com/Waavi/translation
Author: Waavi web development studio
First release: November 2013

This package does quite a lot – it has a set of functions. To be honest, it is quite hard to read the documentation and understand it all at once. But let’s break it down.

Translations source

This package allows you to load translation from the regular Laravel localization files (in /resources/lang), from the database, from cache or in a mix of the previous for development. You may configure the desired mode of operation through the translator.php config file and/or the TRANSLATION_SOURCE environment variable.

If you choose database method, you would have to run package migrations and then command php artisan translator:load to load the files into the database.

Also, it allows to store translations in cache and load from there – for this you would use constants like TRANSLATION_CACHE_ENABLED, TRANSLATION_CACHE_TIMEOUT and TRANSLATION_CACHE_SUFFIX.

Translation repository

Package has its own Repository class \Waavi\Translation\Repositories\LanguageRepository to manage the translations.

With this repository you would be able to find and update the translations, search for available locales and even query the percentage of locale translations finished.

Model attribute translation

This package is also suitable for model translations – you just need to add array property $translatableAttributes to your model, and within migration add fields with suffix _translation. Though, to be honest, I don’t understand how the package stores different languages values in the same database table, but I guess if you play with this package, you will find out.

URL localization

Finally, you may use Waavi\Translation\Middleware\TranslationMiddleware to make sure all of your urls are properly localized. The TranslationMiddleware will only redirect GET requests that do not have a locale in them.

So there you go – a lot of functionality in one package, right?


8. nikaia/translation-sheet

URL: https://github.com/nikaia/translation-sheet
Author: Nassif Bourguig
First release: September 2016

A package with a brilliant idea – a different approach to manage translations. The package uses… Google Sheets! Basically, developers export all the constants to Google Sheets, then translators/clients do their job, and then developers import the words back into the system. Convenient!

Workflow looks like this:

  • You create Google application via Developer Console, create a Google Sheet and put the credentials and Sheet ID into Laravel config file
  • And then you run Artisan commands: translation_sheet:setup + translation_sheet:prepare + translation_sheet:push will publish translations to the sheet
  • Then translation_sheet:lock locks the sheet from further changes
  • And then translation_sheet:pull will pull it back into Laravel project

There are also a few more helping Artisan commands, but in general it’s that simple.


9. zerospam/laravel-gettext (ex. xinax/laravel-gettext)

URL: https://github.com/zerospam/laravel-gettext
Author: ZEROSPAM Security Inc. | Nicolás Daniel Palumbo
First release: October 2014

The last package on the list (oh wait, there are a few bonuses, read on!) is designed to work with GNU gettext and Poedit.

First thing you do after installing this package is configuring your supported locales in config file, and hten running php artisan gettext:create command, which generates the directory structure and translation files for the first time – in resources/lang/i18n.

Then you can use translations like this:

echo __('Translated string');  // Reminds of WordPress, doesn't it?

Example view in Blade file:

{{ __('Translated string') }}

Also, there are additional Gettext functions – like this one for plural:

{{ _n('Translated string', 'Translated plural string', $n) }}

You can edit your translations with Poedit – just use the files from here:
resources/lang/i18n/[locale]/LC_MESSAGES/[domain].po

Finally, package provides methods to get/set active locales, change settings folders in config files and handling the routes – you can read it all in the official Readme file.

All in all, I would recommend this package if you’re familiar with Gettext and Poedit – then you don’t need to change your workflow too much.


10. caouecs/Laravel-lang

URL: https://github.com/caouecs/Laravel-lang
Author: Fred Delrieu
First release: March 2015

The last package on our list is simply a list of 73 languages for Laravel. In this repository, you can find the lang files.

All you need to do is to require this package and then copy the languages/files you need into your resources/lang folder.


Bonus: JavaScript packages

While searching for packages, I’ve stumbled upon two interesting ones related to JavaScript. Won’t review them here, but they perform pretty much the same thing – loading your translations into JavaScript code. Here are the links:


Conclusion: Is there the best package?

The packages may be divided into categories, so let’s start with Translation Managers. There’s no winner here – every package in the list has some different approach to translations or various use-cases, you just pick the one suitable for your workflow: whether you like to translate things via Web, Artisan, Google Sheets or Poedit.

Next, multi-language Models. Clear leaders in this space are definitely two packages with the same name Laravel Translatable. Choose the one you prefer – the one by Spatie, or the one by Astrotomic/Dimsav.

Finally, the best (by far) package for handling routes and middlewares for multi-language project is Laravel Localization.

Are there any packages I’ve missed? Or maybe you have some comments about any of the ones mentioned in the list?