ErikL
ErikL

Reputation: 2041

Laravel Localization To Vue

I'm building a vua/laravel application that should be available in multiple languages. I have all files defined in my language files, and am able to use them in blade templates, but I'm having a hard time using them in my vue components.

I found a good package for it: https://github.com/kg-bot/laravel-localization-to-vue

Installed it and configured it. I then added this to my bootstrap.js, since that seems to be the most logical place for it:

window.messages = axios.get('http://localhost:8083/js/localization.js')

I see that the ajax call is performed and the response contains proper JSON

I then added this to my main blade template:

<script>
    window.default_locale = "{{ config('app.locale') }}";
    window.fallback_locale = "{{ config('app.fallback_locale') }}";
</script>

and added this to app.js:

import Vue from 'vue';
import Lang from 'lang.js';

const default_locale = window.default_language;
const fallback_locale = window.fallback_locale;
const messages = window.messages;

Vue.prototype.trans = new Lang( { messages, locale: default_locale, fallback: fallback_locale } );

According to the documentation, you should now be able to use it in any vue component, but when I try to use it like this:

<tr>
    <th>{{ trans.get('dashboard.headers.name') }}</th>
</tr>

I get this error:

[Vue warn]: Error in render: "TypeError: Cannot read property 'get' of null"

Any idea where I'm going wrong?


UPDATE:

figured out the first issue. You have to add this line:

Vue.prototype.trans = new Lang( { messages, locale: default_locale, fallback: fallback_locale } );

before creating the vue instance:

const app = new Vue({
    el: '#app'
});

I was doing it afterwards.

I am however now facing a next issue, I expected that this would now give me a proper result:

{{ trans.get('dashboard.headers.name') }}

but it just returns dashboard.headers.name', console.log(this.trans.has('dashboard.headers.name'))also returns false.

if I look at the result from the ajax call, it seems that the key is there alright:

enter image description here

But it seems lang.js requires a slightly different format:

{
        'en.greetings': {
            'hi': 'Hi',
            'hello': 'Hello'
        },
        'it.greetings': {
            'hi': 'Salve'
        }
    }
});

so the kg-bot/laravel-localization-to-vue package is just not exporting the data in a way that lang.js understands. It turned out I had to change it to use the toFlat method instead of the toArray method to get the translations in the right format:

enter image description here

However, the translations are still not working. When I replace

window.messages = axios.get('http://localhost:8083/js/localization.js')

by just placing the response of the ajax call in messages, it is working, so apparently it doen't like the promise that is assigned to it now.

Upvotes: 0

Views: 5049

Answers (2)

DonVitoCorleone
DonVitoCorleone

Reputation: 31

I'm the creator of that package and I see you have issues with getting right format of messages. Is there any specific reason why do you use AJAX request and not compiling them together with Vue.js components?

I might also consider adding an option to request format of the messages when doing AJAX call, eg. localhost/messages/array or localhost/messages/flat if you open an issue about this on GitHub.

Upvotes: 1

ErikL
ErikL

Reputation: 2041

It seems I figured out how to get it working. The examples in the documentation just seem to be full of errors.

After adding Vue.prototype.trans before creating the vue instance, there are 2 more things needed:

kg-bot/laravel-localization-to-vue exports data in a format that is not supported by lang.js. There is a function in /vendor/kg-bot/laravel-localization-to-vue/src/Classes/ExportLocalizations.php that can export it in the proper format, but as far as I can see, there's no way to configure the package to export to that format when a ajax call is requesting the translations.

so to fix that, I created my own export class:

/app/Exports/ExportLocalizations.php

<?php

namespace App\Exports;

use KgBot\LaravelLocalization\Facades\ExportLocalizations as ExportLocalizationsBase;

/**
 * Class ExportLocalizations
 * @package App\Exports
 */
class ExportLocalizations extends ExportLocalizationsBase {

    /**
     * @return mixed
     */
    public static function exportToFlat()
    {
        return ExportLocalizationsBase::export()->toFlat();
    }
}

Created a route file for it:

/routes/exports.php

<?php

use Illuminate\Support\Facades\Route;

Route::get(config('laravel-localization.routes.prefix'),  'ExportLocalizations@exportToFlat')->name(config('laravel-localization.routes.name'))
    ->middleware(config('laravel-localization.routes.middleware'));

and added the route to routeService provider:

protected function mapExportRoutes()
    {
        Route::middleware('web')
            ->namespace('App\Exports')
            ->group(base_path('routes/exports.php'));
    }

So now the ajax call was giving the response in the format that lang.js could understand, but 'messages' was a promise instead of the actual ajax call response, and that didn't seem to work.

To fix that, I replaced:

window.messages = axios.get('http://localhost:8083/js/localization.js')

with:

axios.get('http://localhost:8083/js/localization.js')
    .then(function (response) {
        let messages = response.data;
        Vue.prototype.trans = new Lang({messages, locale: default_locale, fallback: fallback_locale});

        const app = new Vue({
            el: '#app'
        });
    })

now the lang instance and Vue instance will be created after the messages have been retrieved.

This is not ideal, because it slows down the application a bit, but at least it's working

Upvotes: 0

Related Questions