svobik7/next-roots

Generating route names for dynamic content

ncostaramos opened this issue ยท 6 comments

Hello there,

Firstly, let me thank you for this piece of code, it is solving some very basic questions. :)

However, I have some doubts, namely, is it possible to create routing with dynamically generate routes?

I'm not sure if this is a feature request or if I'm missing something.

Allow me to explain.
I'm building a LanguageSwitcher component with the objective to have this functionality:

  1. User is in "/" (default language), clicks in targetLanguage in the LanguageSwitcher and there's a link to redirect him to "/es".

  2. User is in "/about" (static page in the default language), clicks in targetLanguage and link redirects him to "/es/sobre".

  3. User is in "/categories/cat-example" (dynamic page which renders categories through generateStaticParams), clicks in targetLanguage and links him directly to "/es/categorias/categoria-ejemplo".

So, basicaly, what I'd need would be a way to get the current route and fetch the correspondent href in the target language. This works for static content but I couldn't find a way to generate route names for dynamic content.

For reference, in the 3rd example, I'm fetching the content from an outside source depending on the locale.

I couldn't find a solution for this in the example from the repo.

Thank you for your time!

Hi @ncostaramos,

it is possible but you always have to provide translated slug because that is something next-roots is not aware of.

Imo I would fetch all possible translated slugs together with the current content so that you can pass it to getHref.

it could be sth like:

// based on your routes it can be sth like
router.getHref('/categories/[categorySlug]', { locale: 'es', categorySlug: content.slugs.es })

Hello there @svobik7.
Thanks for answering so soon.

I've tried implementing the solution above (which I noticed, I was already trying it in my code).

However, with the code below, running:

router.getHref(
     '/categories/[categorySlug]', 
     {
          locale: 'en',
          categorySlug: 'category-1'
     }
);

Returns '/categories', instead of the intended '/categories/category-1'.

As so, I believe now that the issue rests with generateRouteNames(), which will feed the routes to the schema, which will then be "exposed" to getHref (if I got this right...).

However, it looks that I can't put my head around the generateRouteNames() function for dynamic content.

I've tried:

// .../categories/[categorySlug]/i18n.ts

import { getCategorias } from "@/app/lib/utils/serverFunctions"

export async function generateRouteNames() {

  const catsEN = await getCategorias('en');
  if (!catsEN) return [];

  type Path = {
    locale: string;
    path: string;
  };

  const paths: Path[] = [];

  catsEN.map((cat: any) => {
    paths.push({ locale: 'en', path: cat.slug });
  })

  return paths;
}

Which returns:

[
     {locale: 'en', path: 'category-1'},
     {locale: 'en', path: 'category-2'},
     {locale: 'en', path: 'category-3'},
]

And I've also tried a similar function but with the following return:

{locale: 'en', path: [
     'category-1',
     'category-2',
     'category-3'
]}

Needless to say, that didn't work. :)

Am I completely missing something obvious here?

Thank you once again.

Jon1VK commented

There is no need for i18n file under dynamic segment folders. What you should do, is this

  1. Remove /categories/[categorySlug]/i18n.ts file.
  2. Make sure the page /categories/[categorySlug]/page.ts exists
  3. Remove .next folder to be sure .next has not cached previous schema next roots generates
  4. Run next roots generator
  5. Try again calling router.getHref
router.getHref('/categories/[categorySlug]', { locale: 'en', categorySlug: 'category-1' })

Part 3 and 4 are the steps that solved my problems when router.getHref was returning wrong hrefs.

Dynamic category slug is translated by giving translated value for the router.getHref just like svobik7 did in his example above. Your data has to store all translation slugs so that you can fetch the correct data also with the translated slugs.

Jon1VK commented

To be more precise, your LanguageSwitcher should be implemented in a way that it already knows the dynamic slug in another language.

I did this in one project. The way I did this was with parallel routes. In my solution I would have a parallel route for '/@languageLinks/categories/[categorySlug]/page.ts' and also for other segments, for example '/@languageLinks/categories/page.ts'. In each these pages I would generate the correct translated language links for the LanguageSwitcher and return the LanguageSwitcher with correct links. Then I would render the props.languageLinks in the correct place in the root layout.ts layout.

Hopefully this guides you towards right direction. Generic LanguageSwitcher is not easy thing to implement.

@Jon1VK thank you for explanation. @nunocpr let us know if it helps.

Thanks, you guys are the best. :)

I've managed to display everything I needed for now. Still getting used to the app structuring and its caveats.

Thanks again!