Laravel translation made __('simple').

Last update: May 20, 2022 client for Laravel 5.5+/6/7/8

Software License Build Status Test Coverage Maintainability Package Version Downloads

Add this package to localize your Laravel application.

Use the official Laravel syntax (with PHP or JSON files), or use the GetText syntax.

Write only the source text, and keep it synchronized with your translators on interface

Technical Demo (2.5min)

Need help? [email protected]

Table of contents

Translation syntaxes

Laravel Localization (PHP key/values)

The default Laravel method to localize.

// Regular

// Regular with sublevel key

// Pluralization
trans_choice('inbox.message', $number);

// Interpolation
__('inbox.hello', ['name' => $user->name]);

With the PHP file resources/lang/en/inbox.php:

return [
    'title' => 'Title to be translated',
    'hello' => 'Hello :name',
    'messages' => 'One message|Many messages',
    'menu' => [
        'title' => 'Title of menu'


  • trans can also be used instead of __.
  • You can organize your PHP files with subfolders like en/subfolder/inbox.php using keys like subfolder/inbox.title.

Laravel Localization (JSON source text)

A new feature of Laravel 5.4 is the possibility to use __ with the source text (and not only with keys like in the previous section).

These translations are stored into JSON files located in the resources/lang/ directory.

// Regular
__("Text to be translated");

// Pluralization
trans_choice(__('One message|Many messages'), $number);

// Interpolation
__('Hello :name', ['name' => $user->name]);

With the JSON file resources/lang/en.json:

    "Text to be translated": "",
    "One message|Many messages": "",
    "Hello :name": ""


  • To spend less time dealing with multiple JSON files, we advise to only edit the original language (usually en.json) to add new strings, and leave the translations empty. During a sync, This package will automatically create and fill the JSON files of the target languages.

  • If you want to organize your JSON files by feature, you can register new paths in AppServiceProvider like this:

public function boot()
    $loader = $this->app['translation.loader'];


This package adds the GetText support to Laravel. We strongly suggest that you use GetText to localize your application since it allows an easier and more complete syntax.

Also, you won't need to create and manage any PHP or JSON file since your code will be automatically scanned for any string to translate.

// Regular
t("Text to be translated");

// Pluralization
n("Singular text", "Plural text", $number);

// Regular with context
p("context", "Text to be translated");

// Pluralization with context
np("context", "Singular text", "Plural text", $number);

// Simple Interpolations (works with n, p and np too)
t('Hello %s', $user->name);

// Complex Interpolations (works with n, p and np too)
t(':city1 is bigger than :city2', [ ':city1' => 'NYC', ':city2' => 'BXL' ]);


  1. Add the package via Composer:
$ composer require tio/laravel
  1. Create a new translation project from the UI.
  2. Copy the initializer into your Laravel app (config/translation.php) or execute php artisan vendor:publish.

The initializer looks like this:

return [
    'key' => env('TRANSLATIONIO_KEY'),
    'source_locale' => 'en',
    'target_locales' => ['fr', 'nl', 'de', 'es']
  1. Add the API key (TRANSLATIONIO_KEY) in your .env file.
  2. Initialize your project and push existing translations to with:
$ php artisan translation:init

If you need to add or remove languages in the future, please read this section about that.



To send new translatable keys/strings and get new translations from, simply run:

$ php artisan translation:sync

Sync and Show Purgeable

If you need to find out what are the unused keys/strings from, using the current branch as reference:

$ php artisan translation:sync_and_show_purgeable

As the name says, this operation will also perform a sync at the same time.

Sync and Purge

If you need to remove unused keys/strings from, using the current branch as reference:

$ php artisan translation:sync_and_purge

As the name says, this operation will also perform a sync at the same time.

Warning: all keys that are not present in the current local branch will be permanently deleted from

Manage Languages

Add or Remove Language

You can add or remove a language by updating 'target_locales' => [] in your config/translation.php file, and executing php artisan translation:sync.

If you want to add a new language with existing translations (ex. if you already have a translated PHP file in your lang directory), you will need to create a new project on and run php artisan translation:init for them to appear.

Edit Language

To edit existing languages while keeping their translations (e.g. changing from en to en-US).

  1. Create a new project on with the correct languages.
  2. Adapt config/translation.php (new API key and languages)
  3. Adapt directory language names in resources/lang (optional: adapt GetText .po headers)
  4. Execute php artisan translation:init and check that everything went fine.
  5. Invite your collaborators in the new project.
  6. Remove the old project.

Since you created a new project, the translation history and tags will unfortunately be lost.

Custom Languages

A custom language is always derived from an existing language. It's useful if you want to adapt some translations to another instance of your application, or to a specific customer.

The structure of a custom language is: existing language code + - + custom text, where custom text can only contain alphanumeric characters and -.

Examples: en-microsoft or fr-BE-custom.

Custom languages can be added and used like any other language.

Change the current locale


The easiest way to change the current locale is with the set.locale Middleware.

// in routes/web.php

// Solution 1: Apply the locale selection to root.
//             =>
Route::get('/', function () {
    return view('welcome');

// Solution 2: Apply the locale selection to many routes.
//             =>
Route::middleware('set.locale')->group(function () {
    Route::get('/', function () {
        return view('welcome');

// Solution 3: prefix your routes with the locale and apply it.
//             =>
//             =>
Route::prefix('{locale?}')->middleware('set.locale')->group(function() {
    Route::get('/', function () {
        return view('welcome');

First time the user will connect, it will automatically set the locale extracted from the browser HTTP_ACCEPT_LANGUAGE value, and keep it in the session between requests.

The set.locale Middleware code is here, feel free to adapt it with your own locale management.


Change the current locale with:

use Tio\Laravel\Facade as Translation;


Frontend Localization

Using this Package

This package is also able to cover frontend localization (React, Vue, ...).

There are several ways to pass the translation strings from the backend to the frontend: JavaScript serialization, data- HTML attributes, JSON files etc.

The easiest strategy when dealing with React/Vue would be to pass the corresponding translations as props when mounting the components.


  • You can structure the i18n props with multiple levels of depth and pass the subtree as props to each of your sub-components.
  • It also works great with server-side rendering of your components.

Using our official React & JavaScript package

As is directly integrated in the great Lingui internationalization framework, you can also consider frontend localization as a completely different localization project.

Please read more about this on:

Advanced Configuration Options

The config/translation.php file can take several optional configuration options.

Some options are described below but for an exhaustive list, please refer to translation.php.

Ignored PHP keys

If you would like to ignore specific PHP keys, or even entire PHP files or subdirectories from the source language, you can use the ignored_key_prefixes option.

For example:

return [
    'ignored_key_prefixes' => [
        'validation',        // ignore the whole validation.php file.
        'validation.custom', // ignore the "custom" subtree in validation.php file.
        'subfolder/more',    // ignore the whole subfolder/more.php file.


To run the specs with oldest dependencies:

$ composer update --no-interaction --prefer-stable --prefer-lowest
$ ./vendor/bin/phpunit

To run the specs with latest dependencies:

$ composer update --no-interaction --prefer-stable
$ ./vendor/bin/phpunit


Please read the CONTRIBUTING file.

List of clients for

These implementations were usually started by contributors for their own projects. Some of them are officially supported by and some are not yet supported. However, they are quite well documented.

Thanks a lot to these contributors for their hard work!

Ruby on Rails (Ruby)

Officially Supported on

Credits: @aurels, @michaelhoste

Laravel (PHP)

Officially Supported on

Credits: @armandsar, @michaelhoste

React, React Native and JavaScript

Officially Supported on is directly integrated in the great Lingui internationalization project.


If you want to create a new client for your favorite language or framework, please read our Create a Library guide and use the special init and sync endpoints.

You can also use the more traditional API.

Feel free to contact us on [email protected] if you need some help or if you want to share your library.


The MIT License (MIT). Please see License File for more information.

  • 1. Support for multiple JSON files

    We have a very large application that has multiple JSON translation files, registered with Lang::addJsonPath(). These files are split based on multiple modules within the app.

    It looks like it'd be relatively simple to update GettextPOGenerator::jsonFiles() to use all the registered JSON paths. Something like:

    $paths = [$this->application['path.lang']];
    $loader = Lang::getLoader();
    if ($loader instanceof FileLoader) {
      foreach ($loader->jsonPaths() as $jsonPath) {
        $paths[] = $jsonPath;
    foreach ($paths as $path) {
      foreach (glob($path . DIRECTORY_SEPARATOR . '*.json') as $filename) {
        $files[] = $filename;

    The trickier issue would be resolving which JSON file to write back to on sync. Is this something you're interested in supporting? I've been digging around in GettextTranslationSaver and it seems like it'd take a bit of a refactor to support this use-case.

    Reviewed by inxilpro at 2021-04-19 17:19
  • 2. Gettext support

    Hey @armandsar, I added Gettext support to this package.

    A lot of Gettext syntaxes are now supported. You can see how in that file: tests/fixtures/gettext/example.php.

    As you can see, some are quite classic (_("") or _n("", "", number)) and some are added for easier interpolation (_i("hello %s", "world")).

    There are some tests for both client/server behaviour but also to test GetText functions.

    You'll see that there are also sync_and_purge and sync_and_show_purgeable methods in the package. They work like to the ones in Ruby:

    I also renamed php artisan translations:xxx to php artisan translation:xxx for better consistency, I hope you don't mind.

    Please tell me if you see something weird in the package, I certainly did some mistakes.

    Also, to change the language in your Laravel application, you need to do:

    $t = new TranslationIO(config('translationio'));

    Do you know if there is a way to do something like TranslationIO::setLocale('fr') instead? I think I saw something like this somewhere but I'm not very good with Facades and PHP meta-programming.

    Reviewed by MichaelHoste at 2018-02-24 12:15
  • 3. Folder "app" doest not exists. Gettext scan aborted.

    With a vanilla Laravel 8.10.0 project, I am getting the following error when calling translation:init

    Init started
      Folder "app" doest not exists. Gettext scan aborted.
      at /var/www/project/vendor/tio/laravel/src/GettextPOGenerator.php:52
         49▕         // Extract GetText strings from project
         50▕         foreach ($directories as $dir) {
         51▕             if (!is_dir($dir)) {
      ➜  52▕                 throw new \Exception('Folder "' . $dir . '" doest not exists. Gettext scan aborted.');
         53▕             }
         55▕             foreach ($this->scanDir($dir) as $file) {
         56▕                 if (strstr($file, '.blade.php')) {
          +18 vendor frames
      19  /var/www/project/artisan:37

    The config which directories to scan is unchanged with 'gettext_parse_paths' => ['app', 'resources'],

    Reviewed by smares at 2020-11-13 14:08
  • 4. Allow subdirectories for translation PHP files

    Accept the Laravel 5 subdirectories structure: {{ trans('foo/bar/foo.key') }}

    More info here:

    (with more tests for sync and sourceEdits)

    I also debugged the SourceEditException that should have been SourceEditSyncException, and some behaviour that was wrong (sourceEdit must been executed before Sync to deal with more situations).

    I hope the changes are ok with you.

    Next, I'll find a way to use the Gettext syntax.

    I'm still not sure if I'll use eusonlito/laravel-Gettext or build something myself with oscarotero/Gettext. Any thoughts?

    Reviewed by MichaelHoste at 2018-01-11 17:39
  • 5. Allows source edits from

    Hello @armandsar,

    Here is a pull request to allow source edits from (read here for more info:

    The main idea is to change source text AND translations from a centralised place. It allows copywriting from the marketing/management team without annoying developers.

    Also, I added a snippet to pretty print translation files. So they are easier to read.

    If you have any comment on the produced code, please tell me. As you know, I'm not very confortable with PHP since that's not my language of choice.

    I think this package is already mature enough to be distributed to the Laravel community. I intend to create in the following month(s) and start to look for beta-testers.

    So you know, I think the package still need to deal with special translation management of Laravel >5 with sub-folders and keys like "this/is/". But I doubt I lot of users use that feature so it can certainly wait.

    I added my name as author on the composer file, I hope you don't mind.

    Oh, and Happy Christmas ! 🎅 🎄

    Reviewed by MichaelHoste at 2017-12-24 11:11
  • 6. Update README file

    Hello @armandsar,

    I updated the README file for more consistency between and

    I hope you'll like it that way. Feel free to amend it!

    You'll notice that I removed --dev from the composer require command. If I'm not wrong, we need to require the package in production in order to be able to use GetText syntaxes like t__ and n__.

    FYI now that the package seems ready, I will create a specific landing page for Laravel ( and start a beta-test period to gather feedbacks (I'll reach the Laravel community). I'll keep you in touch.

    Thanks again for your support!

    I just increased your trial period on until 2050. Feel free to create as many free Rails/Laravel projects as you want ;-)

    Reviewed by MichaelHoste at 2018-03-07 17:04
  • 7. Laravel 9 upgrade

    In reading the Laravel 9 upgrade, they are moving the lang directory from resources/lang to the project directory. Are you going to implement this change?

    Reviewed by rbruhn at 2022-03-26 17:08
  • 8. php artisan translation:init suceeds, php artisan translation:sync tells me to init first

    After I init the translation (seemingly successfully, see output below), the backend still shows the "setup" page. If i try to php artisan translation:sync it tells me: {"error":"This project has not been initialized yet. Please use the \"init\" operation."} wven though I already initialized.

    My translation.php

    return [
        'key' => env('TRANSLATIONIO_KEY'),
        'source_locale' => 'de-CH',
        'target_locales' => ['fr-FR'],
        /* Directories to scan for Gettext strings */
        'gettext_parse_paths' => ['app', 'resources'],
        /* Where the Gettext translations are stored */
        'gettext_locales_path' => 'resources/lang/gettext'

    The key is in my .env

    How i start the initialization: $ docker-compose exec app php artisan translation:init

    The output I get

    Init started
    Init ended with success
    Use this URL to translate:

    Do your logs give any insight on what might go wrong? Thanks in advance :)

    BTW I use Laravel 8 and the official php docker image "php:8.0-fpm"

    Reviewed by sandrotanner at 2022-01-26 16:41
  • 9. File that is mentioned in 'ignored_key_prefixes' is removed after sync

    Hi! I am using the v1.12 of your package, and PHP 7.3.23.

    I have a translation.php file as follows:

    	'source_locale' => 'de',
        'target_locales'       => ['en'],
        | # Ignored PHP key prefixes.
        | Ex: * 'validation':        ignore the whole validation.php file.
        |     * 'validation.custom': ignore the "custom" subtree in validation.php file.
        |     * 'subfolder/more':    ignore the whole subfolder/more.php file.
        'ignored_key_prefixes' => ['legacy', 'validation'],

    So, I want to translate from german to english. The validation.php file is only available in the en, but not in the de folder (as I just need this file for internalt tests). So I have some structure like this:


    But although validation is mentioned in the ignored_key_prefixes, the en/validation.php file is removed after I call php artisan translation:sync. My structure after syncing is:


    If I understand correctly, the file en/validation.php should not be touched, because it is ignored, so I think I found a bug here?

    Reviewed by stefanschindler at 2020-11-06 08:35
  • 10. Strings inside blade attributes not recognized

    We've encountered an issue where having a blade component with a translated string as a attribute. Example code below:

    <x-form-row :label="t('Name')"></x-form-row>

    This unfortunately won't get picked up when running the sync command. There are ways around this obviously but I just wondered if anyone has an idea on if this could be solved?

    Reviewed by antonhedling at 2021-02-13 09:33
  • 11. Default locale independent to translation setup

    This PR makes application locale set in config('app.locale') independent to translation setup. This way one can set any default language he/she wants when working locally or in a server while syncing with the way defined in config('translation').


    • Working locally with Greek locale (set in config('app.locale')) enabled, using gettext/json strings in english, while syncing with source language English and target languages Greek and Polish
    • Auto-deploying in 2 different application servers with default languages Polish and Greek respectively without any change in translation setup

    This shouldn't break previous behavior as long as the config('app.locale')) == config('translation.source_locale'), while giving the flexibility mentioned above.

    Having English as source_locale even someone is not using them at all (best practice for easy translations in any language) is also possible through this PR

    Reviewed by nikosv at 2019-01-30 08:59
  • 12. How do I add new segments to a pre-existing project?


    This isn't a bug report but simply a question. We've been using this package for a while now and everything works well. However I need to add a couple of hundred new translations (that I already have as .php files). However, when I run the sync command, I only get the source texts imported. All my translation files are overwritten with empty data from I guess this is the way it's intended since it seems to use as a "source of truth".

    But still, I don't really have the time to add all these manually. Is there a way to sort of "re-init" or sync with the codebase as the source? Or is the only solution to create a new project from scratch?

    Reviewed by antonhedling at 2022-03-09 08:15
  • 13. Working with variable translation keys


    I'm wondering if there is a way to register translation keys that come from other sources rather than being hardcoded. Example use case is having a set of data (e.g. API or local constants), which need to be translated, but they would need to be changed over time.

    I would envision a need for a separate scanning tool, that would require a script to be fully functional and therefore would be able to read variables/constants runtime.

    Use example:

    class User  {
        const ROLE_ADMIN = 'admin';
    rtp('enums.user-roles', User::ROLE_ADMIN);
    'scan_runtime' => [
    msgctxt "enums.user-roles"
    msgid "admin"
    msgstr ""

    If one wants to change the value of ROLE_ADMIN to let's say, administrator, it would need to be done in just one place. In theory, is this something that you would be eager to have as a part of your package?

    Reviewed by sybbear at 2020-11-20 16:12
  • 14. remove array-align

    this PR optionally uses for dumping the translations to ensure compatibility of the formats

    also handle case when a JSON file is invalid

    Reviewed by lsmith77 at 2019-08-27 14:08
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

Apr 14, 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

Jan 15, 2022
Manage Laravel translation files
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

May 19, 2022
A Gui To Manage Laravel Translation Files
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

Apr 1, 2022
A GUI for managing JSON translation files in your laravel projects.
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

May 19, 2022
[virion] Language management library for automatic translation
[virion] Language management library for automatic translation

libtranslator :: library for automatic translation ✔️ Multilingual support for plugin messages ✔️ Translation language is set according to the player

Feb 15, 2022
Internationalization tools, particularly message translation.

Aura.Intl The Aura.Intl package provides internationalization (I18N) tools, specifically package-oriented per-locale message translation. Installation

Apr 1, 2022
Provides support for message translation and localization for dates and numbers.

The I18n library provides a I18n service locator that can be used for setting the current locale, building translation bundles and translating messages. Additionally, it provides the Time and Number classes which can be used to output dates, currencies and any numbers in the right format for the specified locale.

Mar 3, 2022
The Translation component provides tools to internationalize your application.

Translation Component The Translation component provides tools to internationalize your application. Getting Started $ composer require symfony/transl

May 25, 2022
Filament Translations - Manage your translation with DB and cache
Filament Translations - Manage your translation with DB and cache

Filament Translations Manage your translation with DB and cache, you can scan your languages tags like trans(), __(), and get the string inside and tr

Apr 22, 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

May 28, 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.

May 19, 2022
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

May 26, 2022
[Deprecated] A Laravel package for multilingual models
[Deprecated] A Laravel package for multilingual models

This package has been deprecated. But worry not. You can use Astrotomic/laravel-translatable. Laravel-Translatable If you want to store translations o

Apr 20, 2022
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

Feb 13, 2022
Package to manage Laravel translations locally
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

Jan 8, 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

Dec 21, 2021
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.

Nov 11, 2021
Weblate translation provider for Symfony Translation.

Weblate Translation Provider This bundle provides a Weblate integration for Symfony Translation. Installation composer require m2mtech/weblate-transla

May 6, 2022
Laravel translation made __('simple').
Laravel translation made __('simple'). 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

May 20, 2022