Nuxt.js | How to handle routing for multiple multilingual slug

Hello :love_you_gesture:,

I've been reading the nuxt tutorials (pretty clear) and started to play around with the nuxt-multilanguage-site repository. It's feel really cool ! But I'm now facing an issue by trying to set multiple dynamic paths.

The repository is perfect for generating pages with custom paths per language, like for an about page:

www.site.com/en-gb/about
www.site.com/fr-fr/a-propos

But on top of that, I would like to add 2 other CT:

  • blog-post (Repeat type)

  • blog-landing (Single type) (will be the listing page for my blog-posts)

I've setted up something working nicely with this tree:

pages/
├─ _lang/
│ ├─ index.vue
│ ├─ _uid.vue
│ ├─ blog/
│ │ ├─ index.vue
│ │ ├─ _uid.vue
├─ _uid.vue
├─ index.vue

But here, blog is hardcoded, and for SEO purpose I would preffer having the blog slug being dynamicly retreived from the uid of the blog-landing.

The goal is to be able to get this

www.site.com/en-gb/blog/
www.site.com/en-gb/blog/uid678
www.site.com/fr-fr/articles/
www.site.com/fr-fr/articles/uid123

// and also keep my other pages like my about page:

www.site.com/en-gb/about
www.site.com/fr-fr/a-propos

I'm not sure how to handle this use case. Do you have any leads on this ?

Thanks for time :pray:

Hi Allan,

Welcome to the community! I'll be happy to help you with this.

I think you'll want to check out our article on creating complex URL's with the route resolver:
https://prismic.io/docs/technologies/route-resolver-nuxtjs

This should show you how to build the structure you need. Let me know if you've got any questions.

Thanks

Hi @Phil

Thanks for your time, this helping hand is really appreciate !

I tried the Router Resolver, and so have converted my previous link-resolver.js:

export default function (doc) {
  if (doc.type === 'blog-landing')  return `/${doc.lang}/blog`;
  if (doc.type === 'blog-post')     return `/${doc.lang}/blog/${doc.uid}`;
  if (doc.type === 'homepage')      return `/${doc.lang}`;
  if (doc.type === 'page')          return `/${doc.lang}/${doc.uid}`;

  return '/not-found';
}

into the route resolver's format:

apiOptions: {
  routes: [
    {type: 'blog-landing', path: '/:lang/blog'      },
    {type: 'blog-post',    path: '/:lang/blog/:uid' },
    {type: 'homepage',     path: '/:lang'           },
    {type: 'page',         path: '/:lang/:uid'      }
  ]
}

Everyting still working fine except that I can't use $prismic.linkResolver(altLang) for exemple. Shouldn't it work whether using Link or Route Resolver ?
From what I understand, Link and Route resolver do the same job but Route's one allow more configuration. Or maybe I'm wrong and both are required ? But the configuration would seems redundant.

Anyway that's not a blocking point for the moment, I guess. So, let's say I first want to implement the URL schema for my blog listing page:

www.site.com/en-gb/blog
www.site.com/fr-fr/articles

I guess I need to change my directory blog to _blog, and in my Router Resolver:

{ 
  type: 'blog-landing', 
  path: '/:lang/:blog'
  resolvers: {
    blog: 'blog.uid'
  }
}

But it seems to break nuxt, even homepage becomes unreachable. I must be misundersting something but not sure what.

I think the issue might be that you need a basic linkresolver which returns null so that it falls back on the route resolver for everything.

Indeed, I could add both. But I'm still stuck trying to get multiples dynamic slugs at the same level

//        |¯ UID of my english 'blog-landing' CT instance
//        |    |¯ UID of an english 'blog-post' CT instance
URL/gb-en/blog/my-en-article

//        |¯ blog: UID of my french version the 'blog-landing'
//        |        |¯ UID of a french version my 'blog-post' item
URL/fr-fr/articles/my-fr-article


// AND also a dynamic route for other type of page
URL/fr-fr/any-page-fr-fr

So with the basic linkResolver I think I can go with this:

if (doc.type === 'blog-landing') return `${doc.lang}/${doc.uid}`;
if (doc.type === 'blog-post') return `${doc.lang}/${doc.data.relationlink.uid}/${doc.uid}`;
// and for other page
if (doc.type === 'classic-template') return `${doc.lang}/${doc.uid}`;

So my project folder tree would be:

└──  _lang/
    ├──  _classic-template-uid.vue  # Dynamic slug here
    └──  _blog-landing-uid/ # Dynamic slug here in the same place
        ├──  index.vue
        └──  _blog-post-uid.vue

But I wonder how does Nuxt distinguish the difference between a route which could concerns either the blog-landing or a classic-template.
In other words, whether the nuxt router should resolve for _classic-template-uid.vue or _blog-landing-uid/index.vue with this kind of url: URL/fr-fr/foobar

Hello Allan,

Basically, when doing 2 folders with a wildcard ( _ ) at the same level this tells Nuxt that any query can go here.
So when you have _first and _second folders it will resolve your route this way:

  • If the query is anything then go to _first
  • If the query is anything then go to _second

But as the first check always pass, so it will always resolve to the _first folder

The following approaches possible in this case:

  1. Validate the response returned by each level using this . If the _first folder returns 404, then it can fallback to _second.

  2. Or you can avoid having to wildcard directory at the same level.

Let me know if you have any doubt.

Priyanka

Hello Priyanka,

I can't go with the second solution. As I want dynamic slug, it would lead me to have '/x/:first/:uid' and '/y/:second/:uid'. But x,y wouldn't have any meaning and would seems strange for the SEO team.
I'll explore the second one level. So if I get it, you mean something like this:

async validate({$prismic, params}){
    let doc = await $prismic.api.getByUID('classic-template', params.uid,  { lang : params.lang })
    return doc !== undefined
}

I never thought about this one, it could be a solution, I will try it

Hello,@allan_leonard,

It looks good to me, you need to move to the next level if this method returns false. Give this a try and let me know.

Priyanka

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.