Reputation: 2041
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:
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:
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
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
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