0
votes

I have the following code:

import Router from 'vue-router';

let mainRoutes = [
    {path: '/first', component: () => import('./pages/First')},
    
    {path: '/second', component: () => import('./pages/Second')},
    
    {path: '/third', component: () => import('./pages/Third')},
  
];

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  scrollBehavior() {
    return {x: 0, y: 0}
  },

  routes: [
    {
        path: '/:lang',
        component: () => import('./layouts/Main'),

        children: mainRoutes,
        meta: {requiresAuth: true, permissions: true}
    },
    {
        path: '*',
        component: () => import('@/pages/errors/404')
    }
  ]
})

router.beforeEach((to, from, next) => {
    if (!to.query.lang) {
        to.query.lang= 'ru';
        next({ path: to.path, query: to.query });
      } else {
        next();
      }
});

export default router

What I want:

Every time some route is entered, I want the vue-router to check whether it has the lang param or not. If not, I want it to place 'ru' in there, if yes then proceed and show the page with the necessary lang (the part which i18n is responsible for).

The problem is that it doesn't recognize ':lang' as a param for the children routes for some reason, so if I try to go to 'test.test/ru', it returns the lang param ok, but if I try 'test.test/ru/first' it doesn't see it and returns 404.

Everything works in case I put :lang param before every child component but it's not really practical. Is there any better way to solve this issue?

2

2 Answers

1
votes

With a code like this you should get the effect you want.

import Vue from 'vue';
import VueI18n from 'vue-i18n';
import VueRouter from 'vue-router';
import Router from './Router.vue';
import En from './translation/En.vue';
import Ru from './translation/Ru.vue';

Vue.use(VueI18n);
Vue.use(VueRouter);
Vue.use(VueBus);

const messages = {
  en: En,
  ru: Ru,
};

const i18n = new VueI18n({
  fallbackLocale: 'ru',
  locale: 'ru',
  messages,
});

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/:lang',
      component: {
        render: (h) => h('router-view'),
      },
      children: [your children route],
});

router.beforeEach((to, from, next) => {
  const { lang } = to.params;

  if (!['en', 'fr'].includes(lang)) {
    return next(i18n.locale);
  }

  if (i18n.locale !== lang) {
    i18n.locale = lang;
  }

  return next();
});

I'm not sure but without i18n I think it's that :

...
router.beforeEach((to, from, next) => {
 const { lang } = to.params;

 if (!['en', 'ru'].includes(lang)) {
  route.params.lang = 'ru';
  router.push({ name: route.name });
 }
});
0
votes

I've finally found a solution!

If you have some param in the main route, your children routes shouldn't start with a '/' symbol, but simply with the correct route, for instance

let mainRoutes = [
    {path: 'first', component: () => import('./pages/First')},
    
    {path: 'second', component: () => import('./pages/Second')},
    
    {path: 'third', component: () => import('./pages/Third')},
  
];

const router = new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  scrollBehavior() {
    return {x: 0, y: 0}
  },

  routes: [
    {
        path: '/:lang',
        component: () => import('./layouts/Main'),

        children: mainRoutes,
        meta: {requiresAuth: true, permissions: true}
    },
  ]
})