Hey, does anyone know if it is possible to translate data added to html from vue.js script file? So for exmaple if I have in my vue.js the following:
const app= new Vue({
el: '.main__page',
data: {
season: "summer",
}
})
and then in html: <h1 v-model="season"></h1>
how would I be able to translate the "season" variable?
I am sure, I have seen it somewhere, but can't find it anymore.
Thanks.
where does your vue.js data get generated?
in a script.js file that is load via html <script> tag.
You could provide the translation strings using a dynamically generated js file which could be used by your Vue js code
Okay, that sounds good. Is there an example somewhere with such a file?
@th-ink I would suggest looking at a library like Vue I18n which takes a messages variable, and either doing what @mjauvin suggested and dynamically generating a messages file and using that to populate the messages variable, or creating a October plugin to provide an API to get the messages dynamically. Unfortunately, I don't have any examples to show you, but my company is trying out such a method at the moment, and if it works easy enough, I'll see if I can make an example of it somewhere.
@bennothommo @th-ink here's something I did up on a project a while ago.
In Plugin.php boot():
// Clear the /author-plugin/translation-messages cache whenever a message updates
Message::extend(function ($model) {
$model->bindEvent('model.afterSave', function () {
Cache::forget('author.plugin.translation-messages');
});
});
in routes.php
use RainLab\Translate\Classes\Translator;
use RainLab\Translate\Models\MessageExport;
use RainLab\Translate\Models\Locale as LocaleModel;
Route::get('/author-plugin/translation-messages', function () {
// Store the generated data in the cache, cache will be manually emptied whenever a message updates
// Cache::forget('author.plugin.translation-messages');
$cacheData = Cache::rememberForever('author.plugin.translation-messages', function () {
$translator = Translator::instance();
$availableLocales = array_keys(LocaleModel::listEnabled());
$activeLocale = $translator->getLocale();
$fallbackLocale = $translator->getDefaultLocale();
// NOTE: The actual message code is stored under "x" in the message data, the code column is
// used in the database and turns any symbols into ".", which would turn the key account.create_header
// into account.create.header. Thus we must request the "x" column and use it as the code
$messageData = (new MessageExport())->exportData(MessageExport::getColumns() + ['x']);
$messagesByLocale = [];
foreach ($messageData as $message) {
foreach ($availableLocales as $locale) {
if (!empty($message[$locale])) {
array_set($messagesByLocale, $locale . '.' . $message['x'], $message[$locale]);
}
}
}
$responseData = [
'locale' => $activeLocale,
'fallbackLocale' => $fallbackLocale,
'messages' => $messagesByLocale,
];
return [
'data' => base64_encode(json_encode($responseData)),
'etag' => md5($activeLocale . $fallbackLocale . implode('|', array_dot($messagesByLocale))),
'last_modified' => now()->timestamp,
];
});
// Set the proper caching headers on the messages
$response = Response::make();
$response->header('Content-Type', 'application/json');
$response->header('Cache-Control', 'private, max-age=604800');
$response->setLastModified((new DateTime())->setTimestamp($cacheData['last_modified']));
$response->setEtag($cacheData['etag']);
$response->setPublic();
$modified = !$response->isNotModified(App::make('request'));
if ($modified) {
$response->setContent(base64_decode($cacheData['data']));
}
return $response;
});
in Vue initialization:
import Vue from 'vue';
import VueI18n from 'vue-i18n';
window.myVueComponent.initComponent = function (vueParams) {
$.getJSON('/author-plugin/translation-messages').done(function (data) {
vueParams.i18n = new VueI18n(data || {});
}).always(function () {
new Vue(vueParams);
});
}
Technically speaking we could probably add a JSON endpoint to this plugin to get all site translations.
Thanks @bennothommo and @LukeTowers, I will try it out.
Most helpful comment
@bennothommo @th-ink here's something I did up on a project a while ago.
In
Plugin.phpboot():in
routes.phpin Vue initialization: