How to use Laravel translations in JavaScript, in case of SPA application

By default Laravel has a folder in resources/lang that contains all the translations used in the application. We want to use these translations in JS, for example in the case of a SPA application.

We will use a web route where we will render translations only for the current language in the application.

We define this route right in in web.php

Route::get('js/translations.js', function () {
    $lang = config('app.locale');
    $strings = \Illuminate\Support\Facades\Cache::rememberForever('lang_'.$lang.'.js', function () use($lang) {
        $files = [
            resource_path('lang/' . $lang . '/common.php'),
            resource_path('lang/' . $lang . '/validation.php'),
        ];
        $strings = [];

        foreach ($files as $file) {
            $name = basename($file, '.php');
            $strings[$name] = require $file;
        }

        return $strings;
    });
    header('Content-Type: text/javascript');
    echo('window.i18n = ' . json_encode($strings) . ';');
    exit();
})->name('translations');

Pay attention to 2 things.

  1. We use Cache to store translations.
  2. We include only the files we need to translate, in our case: common.php and validation.php


In a blade, header or footer file, before the main scripts:

<script src="{{ route('translations') }}"></script>

 

Now we need to create a JS function that will help us easily translate from anywhere in our JS application. Make sure you have the lodash plugin installed. If not: 

 

npm i --save lodash

 

Now we will write this in our main script, let's say app.js

import getLodash from "lodash/get";
import eachRightLodash from "lodash/eachRight";
import replaceLodash from "lodash/replace";


window.translate = function(string, args){
let value = getLodash(window.i18n, string);

eachRightLodash(args, (paramVal, paramKey) => {
value = replaceLodash(value, `:${paramKey}`, paramVal);
});
return value;
}

Now we can call our function anywhere in the application to translate a key, for example:

translate('common.years', { nr: 10 });
// The result will be: 10 years

If you use VueJS, we can create a prototype:

Vue.prototype.trans = (string, args) => {
     return window.translate(string, args);
};

Then in a VueJS component:

computed:{
 years(){
      return this.trans('common.years', { nr: 10 });
  }
}