In a vanilla Laravel installation you can use language files to localize your app. The Laravel documentation refers to any string in a language file as a language line. You can fetch the value of any language line easily with Laravel's handy trans-function.

trans('messages.welcome'); // fetches the string in the welcome-key of the messages-lang-file.

In our projects a client sometimes wants to change the value of such a language line. But as we don't want to let the client edit php files we had to come up with another way of storing localized strings.

Our new laravel-translation-loader package will enable the language lines to be stored in the database. In this way you can build a GUI around that to let the client manipulate the values. When using our package can still use all the features of the trans function you know and love.

Once the package is installed you'll have a language_lines table where all localized values can be stored. There's a LanguageLine model included. Here's how you can create a new LanguageLine:

use Spatie\TranslationLoader\LanguageLine;

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

The cool thing is that that can still keep using the default language files as well. If a requested translation is present in both the database and the language files, the database version will be returned by the trans function.

While creating the package we also kept an eye on performance. When requesting a language line from a group we will retrieve all language lines from a group. In this way we avoid a separate query from each language line. We'll also cache the whole group to avoid querying the database from language lines in subsequent requests. Whenever a language line in a group is created, updated or deleted, we'll invalidate the cache of the group.

The package is also easy to extend. Image you want to store your translations not in a php-files or the database, but in a yaml-file or csv-file or... you can create your own translation provider.

A translation provider can be any class that implements the Spatie\TranslationLoader\TranslationLoaders\TranslationLoader-interface. It contains only one method:

namespace Spatie\TranslationLoader\TranslationLoaders;

interface TranslationLoader
{
    /*
     * Returns all translations for the given locale and group.
     */
    public function loadTranslations(string $locale, string $group): array;
}

Translation providers can be registered in the translation_loaders key of the config file.

Take a look at the readme of the package on GitHub to learn all the options. Be sure to also check out the list of Laravel packages our team has previously made.