Dynamic nested pages that have same slug and language tag query

Hello all,

I am trying to figure out the best approach to have the same slug for a dynamic page folder and how one would query that when not being able to use the UID.

For example:
/fr-fr/brussels/royal/gym
/fr-fr/milan/harbour/gym

What is the best method to create two different gym pages that have the same slug for different venues/gym. I can't use UID this method would return a different slug.

I have created a gym.vue file inside the dynamic folder for venue, what is the best method to query gym in relation to the venue? The custom type for gym is repeatable so getSingle won't work. Document Type?

Another quick query on multi lingual. Is there an option to only return the language for the tag and not the country? The request is to only have /fr/ /en/ /de/ etc.. I have a good understanding how to do this in JavaScript but wanted to check if there was a method to return only the language code from Prismic instead?

Thanks :slight_smile:

I solved this by querying the api like so:

        const venueRelation = await $prismic.api.query(
            $prismic.predicates.at('document.type', 'venue_gym'),
            { lang: store.state.lang }
        )
        const result = venueRelation.results.find(gym => params.venue === gym.data.venue_relation.uid)

Please let me know if there's a way to query it smarter than this :slight_smile:

Any concerns with not having a UID for each repeatable page?

Still looking for a tidy solution for the language code if possible

Hey Jake,

Let me break this down by starting with the language question — something I've played with in the past, myself. The way I see it, you have two options:

  1. Create a "languages" object that you reference in your queries, like this:
const langs = {
  en: "en-us",
  fr: "fr-fr",
  de: "de-de"
}

Then, import/reference that when you make your query:

{ lang: langs[params.lang] }
  1. Query and manipulate the langs from the API

If you query your endpoint (https://your-repo-name.cdn.prismic.io/api/v2), you'll get a bunch of meta information about your repo. You can do this with the $prismic object in Vue/Nuxt. I think it's either $prismic.getApi() or $prismic.client.getApi() (both might work). The response will include a languages object that you can manipulate to get your languages. It would look something like this:

const getLangs = async () => {
  const apiMeta = await $prismic.client.getApi()
  const langs = {}
  apiMeta.languages.forEach((langObj) => {
    langCode = langObj.id.split('-')[0]
    langs[langCode] = langObj.id
  })
  return langs
}

const langs = await getLangs()

This method is nice because it's dynamic — you can add more languages to your repo without changing the code. You'd have to call this on each page, and then use the same method as above to query the language:

{ lang: langs[params.lang] }

Let me know what you think of that for your languages. In the meantime, I'll think about the rest of your query.

Best,
Sam

Hey Sam,

Thanks for taking the time to get back to me and your useful info on lang code, I'll give it a try shortly.

I resolved my /gym query with something like this:
I create a field in the page for 'slug' and use this to return the correct content.
In the parent page I have a group of fields for content relation to create my fetchLinks.

            const relatedPagesFromClub = await $prismic.api.getByUID('club', params.club,
            {
                fetchLinks: 'club_menu',
                lang: store.state.lang
            }
        )

        const correctPage = relatedPagesFromClub.data.club_menu.find(Page => params.uid === Page.link.slug)

        const result = await $prismic.api.query($prismic.predicates.at('document.id', correctPage.link.id,
            {
                lang: store.state.lang
            }
        ))

'result' always returns an array of objects (always one) compared to a single object when querying a UID. But this seems fine and everything is working well.

Thanks again
Jake

Hey jake,

I came up with one potentially more elegant solution for the language code: you can set a custom locale in your repo settings, and create your own code, so you could create an "English" locale with the code "en", etc. You'd have to create that locale, copy any content over, then submit a request to us to change your master locale, and delete the original.

For your routing, could you help me understand your hierarchy a little bit? From your query, I understand it looks something like this:

.
└── en
    ├── brussels
    │   ├── royal
    │   │   └── gym
    │   └── other
    │       └── gym
    └── milan
        ├── harbour
        │   └── gym
        └── other
            └── gym

With the document tree repeated across multiple languages. Is that correct?

Sam

Hey Jake,

I've taken a close look at your question, and I think I understand. Here's what I would do:

If, in your Nuxt project, your pages directory looks like this:

~/pages/_lang/_city/_location/gym.vue

That will give you a params object that includes:

{
  location: _location,
  lang: _lang,
  city: _city
}

Then, in Prismic, you could include these fields in your "gym" custom type:

- location (uid field)
- city (dropdown)

You would give each "gym" a unique "location", like "harbour" or "royal", and a "city".

Then, to query the page, your asyncData would look like this:

async asyncData({ $prismic, params, error }) {
  try {
    const gym = (
      await $prismic.api.query([
        $prismic.Predicates.at("document.type", "gym"),
        $prismic.Predicates.at("my.gym.location",params.location),
        $prismic.Predicates.at("my.gym.city", params.city)
      ])
    );
    return { gym };
  } catch (e) {
    error({ statsCode: 404, message: e });
  }
},

The third predicate, which queries for the city, is not necessary to find the document — because the second predicate searches for a unique UID. However, the third predicate will prevent the wrong URL from returning the document (so /en/new-york/royal will return a 404, not /en/brussels/royal).

I'm not sure if I've understood your use-case completely, so please let me know if I've missed the point, or if I'm not being clear :slight_smile:

Sam

Thanks Sam,

If this is helpful to anyone else, this is what I ended up with in the end to get the languages from Prismic,

    const apiLangs = await $prismic.api.languages

    const addLangObj = apiLangs.map((lang) => {
        const langCode = lang.id.split('-')[0]
        lang[langCode] = lang.id
        // removes 'id' and 'name' keys+value from object
        const { id, name, ...onlyLangObj } = lang
        return onlyLangObj
    })

    const reducedLangsObj = Object.assign({}, ...addLangObj)

reducedLangsObj will return a single object with the list of language codes like so: { en: 'en-gb', fr: 'fr-fr' }

1 Like

Thanks again Sam,

Ideally the plan was to have completely dynamic club pages. The client may in the future want to include a page that doesn't fit within a pre defined template. I have a solution above that works quite well, it also accounts for different language slugs, such as family (en) or famille (fr).

This is setup as a page field for 'slug' and then a content relationships ensures to always return the correct page as per club you're on.

1 Like

Okay, cool! Glad you've got it working. Do let me know if there's anything I can help with.

1 Like

This issue has been closed as it has been fixed, Flag if it is not the case for you to reopen.