I'm using prerender-spa-plugin
in order to prerender certain pages so I get better SEO from my Vue app.
My goal is to transform the way I'm currently using Vue-i18n
, so I can base it on url param /lang
. Examples: /en/home
or /nl/home
. With this, I would be able to pre-render depending on the language.
I created a prefixer function that adds to every parent route the optional param /:lang?
. Here it is:
const withPrefix = (prefix: string, routes: RouteConfig[]): RouteConfig[] => routes.map((route): RouteConfig => {
// Avoiding mutations
const clonedRoute = { ...route };
// Every route except for '/'
if (clonedRoute.path !== '/') {
clonedRoute.path = prefix + clonedRoute.path;
}
return clonedRoute;
});
In Vue templates, I'm using:
<router-link :to="`/account`">
So I'm trying to manipulate the redirect to the next page according to the lang
param.
First approach
The most logical one is (inside Router's beforeEach
):
const { lang } = to.params;
const redirectTo = lang ? to.fullPath : `${fullToLang}${to.fullPath}`;
if (from.fullPath !== redirectTo) {
next({ path: redirectTo });
} else {
next();
}
But it enters in an endless loop because from is always the same.
Second approach
Using Router
's base
property.
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld";
import Test from "./components/Test";
Vue.config.productionTip = false;
Vue.use(VueRouter);
const router = new VueRouter({
mode: "history",
base: "/en",
routes: [
{
path: ":lang?/",
component: HelloWorld,
beforeEnter: (to, from, next) => {
console.log(1);
next();
}
},
{
path: "/:lang?/nope",
component: Test,
beforeEnter: (to, from, next) => {
console.log(2);
next();
}
},
{
path: "/:lang?/*",
beforeEnter: (to, from, next) => {
console.log(to);
next("/nope");
}
}
]
});
new Vue({
render: h => h(App),
router
}).$mount("#app");
Or better, live: https://codesandbox.io/embed/vue-template-0bwr9
But, I don't understand why it's redirecting to /en/nope
only if the url is not found on the routes (last case). And more, would I have to create a new Router
instance each time I want to change base
?
Third approach
Wrapper component for router-link
injecting :to
based on this.$route.params.lang
.
This would do it for navigation after the app is loaded but not at the first refresh/initialization.
So, how should I resolve this?
~ Solution ~
So yeah, first approach was the correct way to go but I missunderstood how Router behaves with next
and redirects
. The condition should be checking the to
not the from
.
const redirectTo = lang ? to.fullPath : `${fullToLang}${to.fullPath}`;
if (to.fullPath !== redirectTo) {
// Change language at i18n
loadLanguageAsync(toLang as Language);
next({ path: redirectTo });
return;
}
I am not entirely sure what you are asking. But I assume you want to prefix your navigations with the current language param (../en/..) if they do not already have one?
You could resolve this with a beforeEach()
hook and only redirecting if there is no lang
param present.
const { lang } = to.params
if(!lang) {
next({ path: redirectTo })
}
next()
If that's not what you want please clarify and I'll edit my answer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With