Laravel Localization with Vue.js

TLDR; In this post we will discuss how we can harness the power of Laravel Localization in a Single Page Application built with VueJS.

Posted by Mohamed Irfan on 2019-Dec-17

Localization on Laravel from Server Side

Laravel's localization features provide a convenient way to retrieve the corresponding strings according to the app locale set, since the server has all those translation strings in it, it is just a matter of pointing out the file and the key, so that we can retrieve the data, and print it on a page where we want to. For more details on how the translations are being retrieved check the official documentation on Laravel localization.

But when it comes to the client-side, if we rely on the server to handle the translation every time, we are going to make so many requests to the server, to get the document translated when the language is being changed by the client each time, and it doesn’t sound good as efficient. For instance, consider a Single Page Application where the page has language preferences, it’s better to have the translated files in the client-side and let the client do the translation by a client-side scripting languages like JavaScript.

So the idea is to have all the translated files in the server as a JSON file in the client-side and do the fetching there at the client without letting the server to handle everything.

Let’s try it with Laravel

So as it’s mentioned earlier we already have the localization feature in laravel, we can use those files and convert those files to a JSON file and then the rest is up to the client.

Generate the JSON file required

Let’s install Lang js via composer to convert the PHP key-value pair to JSON file.

composer require mariuzzo/laravel-js-localization

Add the service provider in config/app.php

Mariuzzo\LaravelJsLocalization\LaravelJsLocalizationServiceProvider::class

Now we can generate the JSON files by the following artisan command

(note that this creates the file in a specified folder check the official documentation)

php artisan lang:js resources/js/vue-translations.js --no-lib --quiet

We have to run this command when we build the Vue files, We can make use of laravel mix to do the job,

Install webpcak shell plugin first if it is not installed yet,

npm install --save-dev webpack-shell-plugin

Install Vue Lang.js

So we are going to try it with Vue.js and a node package from the client-side.Assuming Vue.js is already installed in the project.

Let's use a node package called vue-lang-js

yarn add @eli5/vue-lang-js or npm install @eli5/vue-lang-js

Then in webpack.mix.js file, 

const WebpackShellPlugin = require('webpack-shell-plugin');
// Add shell command plugin configured to create JavaScript language file
mix.webpackConfig({
  plugins:
    [
      new WebpackShellPlugin({onBuildStart:['php artisan lang:js resources/js/vue-translations.js --no-lib --quiet'], onBuildEnd:[]})
    ]
});

We can import the lang.js for only the places where we needed to use it, but it’s almost common to have the translation in all the pages, let’s require and import it globally, so we don’t have to import it every time we want.

In the app.js file where you have imported vue globally,  add these lines and import the JSON file generated.

require('lang.js');
import VueLang from '@eli5/vue-lang-js'
// get the data source
import translations from './vue-translations.js';

Vue.use(VueLang, {
  messages: translations, // Provide locale file
  // locale: 'en', // Set locale
  fallback: 'en' // Set fallback lacale
});

Translations

Now it’s just the job to call the function in the vue template which retrieves the correct string, that is, for example

<h2> {{ $trans('file.key') }}</h2>

As mentioned in the Vue Lang js documentation we have alternatives for $trans function too , Like

$t('auth.title')

And it has more information like getting something in the plural form as well. Check it out,

So how could we get the current language and how to set the current language. That’s simple,

  this.$lang.setLocale('en')

To get the current locale,

this.$lang.getLocale()

And one more handy thing that would be useful is to store the current locale somewhere so that we can retrieve it and set the locale when the user comes in again, to do that we can make use of the local storage in the browser.

So when the component gets mounted,

if (localStorage.getItem('locale')) {
  this.$lang.setLocale(localStorage.getItem('locale'));
} else {
  this.$lang.setLocale('en');
}