Switching language in laravel 5 / vue app2 - laravel-5

In my laravel 5.6/vue.js 2.5.7 / I use
vue-i18n 7.8 and laravel-vue-i18n-generator for multi language support:
and in resources/assets/js/app.js file I do like:
...
let lang = 'fr';
const i18n = new VueI18n({ // https://github.com/caouecs/Laravel-lang - Additive langs
locale: lang, // set locale
messages : Locale, // set locale messages
})
new Vue({ router, i18n,
data:{
...
In my vue file wnen I need to read my current locale I can use like :
created() {
this.current_locale = this.$i18n;
...
To switch to other locale locale I can use a function like:
switchLocale () {
if (this.$i18n.locale === 'fr') {
this.$i18n.locale = 'en'
} else {
this.$i18n.locale = 'fr'
}
}
The question is where to save current language when I moving to other page? I mean
let lang = 'fr';
at top of my code that is some default locale, but if locale has been changed, where from to read it? Some simple solution please.
To generate prefix in url seems very complicated.
Thanks!

You could use localStorage.
switchLocale () {
if (this.$i18n.locale === 'fr') {
this.$i18n.locale = 'en'
} else {
this.$i18n.locale = 'fr'
}
localStorage.setItem('locale', this.$i18n.locale)
}
And then on the next page:
this.$i18n.locale = localStorage.getItem('locale');

Related

Watch Value In Vue.js 3, Equivalent In Pinia?

I have a checkbox list of domain tlds, such as com, net, io, etc. I also have a search text input, where I can drill down the list of 500 or so domains to a smaller amount. For example, if I start to type co in to my search text input, I will get back results that match co, such as co, com, com.au, etc. I am using Laravel and Vue,js 3 to achieve this with a watcher. It works beautifully. How can an achieve the same within a Pinia store?
Here is my code currently:
watch: {
'filters.searchedTlds': function(after, before) {
this.fetchsearchedTlds();
}
},
This is inside my vue component.
Next is the code to fetch searched tlds:
fetchsearchedTlds() {
self = this;
axios.get('/fetch-checked-tlds', { params: { searchedTlds: self.filters.searchedTlds } })
.then(function (response) {
self.filters.tlds = response.data.tlds;
console.log(response.data.tlds);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
},
And finally, the code inside my Laravel controller:
public function fetchCheckedTlds(Request $request)
{
$data['tlds'] = Tld::where('tld', 'LIKE','%'.$request->input('searchedTlds').'%')->pluck('tld');
return response()->json($data);
}
I am converting my code to use a Pinia store and I am stuck on how to convert my vue component watcher to Pinia?
Many thanks in advance.
To watch a pinia status, you may watch a computed attribute based on pinia or use watch getter
Your pinia may look like the one below.
~/store/filters.js
export const useFilters = defineStore('filters', {
state: () => {
return {
_filters: {},
};
},
getters: {
filters: state => state._filters,
},
...
}
In where you want to watch
<script setup>
import { computed, watch } from 'vue';
import { useFilters } from '~/store/filters.js';
const filters = useFilters();
// watch a computed attributes instead
const searchedTlds = computed(() => {
return filters.filters?.searchedTlds || '';
});
watch(
searchedTlds,
(newValue, oldValue) {
fetchsearchedTlds();
}
);
// or use watch getter
watch(
() => {
return filters.filters?.searchedTlds || '';
},
(newValue, oldValue) {
fetchsearchedTlds();
}
);
</script>
The first parameter of watch() can be a single ref or a getter function, or an array of getter functions, for more details, please view the Watch Source Types.

Use package.json version in MD files for Vue Press

I'm trying to utilise the package.json version tag inside of my *.md files which get later compiled into HTML, however I can't seem to figure out how to do this. My plugin.js files contains the following which I thought I could utilise:
const { version } = require('../../package.json')
module.exports = (/*options, ctx*/) => ({
async enhanceAppFiles () {
const code = `export default ({ Vue }) => {
Vue.mixin({
computed: {
$version () {
return '${version}'
}
}
})
}`
return [{
name: 'vuepress-plugin-vue-cli-plugin-p11n',
content: code
}]
}
})
I tried using version and $version inside of my *.md files with little luck, has anyone else got this issue?
The easiest way to achieve this, it's simply put the version into themeConfig and let VuePress do its thing
// .vuepress/config.js
const { version } = require('../../package')
module.exports = {
themeConfig: {
version: version
}
}
and use it in markdown like
{{ $themeConfig.version }}
However, it seems like that themeConfig isn't meant for this, so you can also create your own computed properties
// .vuepress/enhanceApp.js
const { version } = require('../../package')
export default ({ Vue }) => {
Vue.mixin({
computed: {
$version: function() {
return version
}
}
})
}
and use it like
{{ $version }}

Laravel compact in vue

I want to know how can I pass variables to vue component in laravel?
When we work with blade we can pass variables like:
$now = Carbon::now();
return view('xxxxxxxx', compact('now');
That way I can use $now in xxxxxxxx blade file. But what about vue components? we usually return data by json for components and with axios route we get that info no way to specify such data for exact component of us?
What if I want to use $now = Carbon::now(); in single.vue component?
How can I make that happen?
Update
Here is what I want to do with timing as carbon cannot be used (based on comments) I want to use moment.js
Logic
Let users bid if project deadline hasn't arrived
Don't let users bid if project deadline has arrived
template
<template v-if="`${project.deadline | timeAgo}`">
pssed (will be replaced by button is just for test)
</template>
<template v-else>
still have time (will be replaced by button is just for test)
</template>
script
var moment = require('moment');
export default {
data(){
return {
project : '',
}
},
mounted: function() {
// I found this code by google not sure if is currect!
Vue.filter('timeAgo', function(value){
return moment(value) >= fromNow()
});
},
}
Based on my code above here is the results
Try this:
This is my routes, simply I just render a view with some pre-defined variables
Route::get('/', function () {
return view('welcome', [
'now' => Carbon::now(),
'deadline' => Carbon::now()->addHours(2)
]);
});
And this is my view file. Here I have custom element named: example-component. And this is how I passed PHP variables to Vue component using props.
And pass your data to window like so:
<script>window.data = #json(compact('now', 'deadline'))</script>
And this is my Vue component file:
<template>
<h1>
<span v-if="isPassed">This job is passed</span>
<span v-else>You have to finish this job</span>
{{ parsedDeadline | timeFromX(parsedNow) }}
</h1>
</template>
<script>
const moment = require('moment');
export default {
props: {
now: {
type: String,
default: () => window.data.now.date // since `now` is an object, you need to access the `date` property to get plain string date that moment can parse
},
deadline: {
type: String,
default: () => window.data.deadline.date // same as above
}
},
computed: {
parsedNow () {
return moment(this.now)
},
parsedDeadline () {
return moment(this.deadline)
},
isPassed () {
return this.parsedNow.isAfter(this.parsedDeadline)
}
}
}
</script>
Here's the documentation about computed and filters. You may NEVER add a filter in a mounted function since it may leads to memory leak. Here's how I add my filter. In your app.js (assumed you're using default Laravel Vue preset)
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.filter('timeFromX', (a, b) => a.from(b)); // TADAAA...!!!
const app = new Vue({
el: '#app'
});
UPDATE
If you want to try this, you may edit the routes/web.php and change the deadline value:
Route::get('/', function () {
return view('welcome', [
'now' => Carbon::now(),
'deadline' => Carbon::now()->subHours(2), // Passed 2 hours ago
// 'deadline' => Carbon::now()->addHours(2), // In 2 hours
]);
});
Checkout the Carbon docs here about addition and subtraction.
UPDATE II
If you got error in app.js from the code above, maybe your transpiler doesn't know about arrow-parens.
// Looks like arrow-parens not working, see code below
// Vue.filter('timeFromX', (a, b) => a.from(b)); // TADAAA...!!!
// Change it to this ???
Vue.filter('timeFromX', function (a, b) {
return a.from(b);
});

{{ obj.data }} not displaying in vue template after axios get

I am trying to build a carousel using Laravel 5.6 and Vue.js. I can call the data from db, and console.log response.data. It works like expect it to. Script below.
<script>
$(document).ready(function() {
$("#availability").owlCarousel();
});
export default {
props: {
areaId: null,
tutorId: null,
},
data () {
return {
availability: []
}
},
methods: {
getAvailability () {
var that = this;
axios.get( '/' + this.areaId + '/' + this.tutorId + '/availability').then((response) => {
console.log(response.data)
that.availability = response.data;
});
}
},
mounted () {
this.getAvailability();
}
}
</script>
Now I would expect to be able to display the data like
{{availability.monday_begin}}
but it displays nothing, empty tags.
When I add a second .data to response, so change
that.availability = response.data;
to
that.availability = response.data.data;
The data object shows up as undefined in the vue-dev tools, and {{ availability.monday_begin }} throws an error cannot read property of undefined.
I also tried adding a v-if to the template, based on a couple different articles I read, but nothing I tried worked.
Thanks for your help.

Loading lang files in Laravel depending on prefix/session

I build a multilanguage site with 3 languages (mk - default, sq and en) and ended up with the following code in routes.php:
$languages = array('en', 'sq');
$locale = Request::segment(1);
if(in_array($locale, $languages)){
\App::setLocale($locale);
}else{
$locale = null;
}
// Set the session here
Session::put('locale', $locale);
Route::group(array('prefix' => $locale), function()
{
Route::get('/', array('as' => 'home', 'uses' => 'Controllers\Frontend\FrontendController#getIndex'));
// .... other routes
});
My default locale is 'mk' and I also have 2 other languages in Land folder, sq and en.
While the routing works fine, problem is when loading lang files. It works for default language mk set in app.php and for en but won't switch for sq translation, and instead it loads the en lang files.
Example:
URL: http://website.com loads mk lang files
URL: http://website.com/en loads en lang files
URL: http://website./sq loads en lang files instead of sq <--- PROBLEM
Among other code, I have the following in the view:
{{{ URL::route('home') }}}
The controller is usual:
public function getIndex($locale = null)
{
$data = array();
return View::make('frontend.frontpage', $data);
}
My question: why the sq language files aren't loaded when the URI parameter is changed to sq?
Question: "Loading lang files in Laravel depending on prefix/session"
#Pat's answer (in comment) solved my issue (Loading lang files in Laravel depending on prefix/session)
In short, using https://github.com/mcamara/laravel-localization eases creating multilangugage website with Lavarel.

Resources