0

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.

3
  • Weird. The only difference I have is window.Vue = require('vue'); instead of import Vue from 'vue'; and it works for me. Commented Dec 25, 2020 at 14:03
  • Try with this.trans.get('dashboard.headers.name'). Commented Dec 25, 2020 at 14:59
  • tried both, but it doen't seen to make make of a difference. Apparently trans and this.trans are both empty. I am using a single file component, maybe I can not access global properties from there? Commented Dec 25, 2020 at 19:24

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.