svobik7 / next-roots

Next.js utility to generate i18n routes in the new APP directory.
https://next-roots-svobik7.vercel.app/
MIT License
178 stars 12 forks source link

Feature Request: skip page generation for specific languages #215

Open jmoros opened 4 months ago

jmoros commented 4 months ago

Thank you for your great work on this library! I appreciate the effort you put into maintaining it.

I'd like to propose a new feature: the ability to prevent page generation for specific languages.

By default, the library generates pages for all locales. However, there are cases where this behavior might not be ideal. Here are a few scenarios where skipping certain languages could be useful:

Possible solutions for this feature could include:

Example:

// locales: ['en', 'it']
// routes/example-page/i18n.ts
// This would only generate routes for 'en' language, but NOT for 'it' language
export const routeNames = [
  { locale: 'en', path: 'example-page' }
];

Example:

// locales: ['en', 'it']
// routes/example-page/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', exclude: true } // or { locale: 'it', path: null }
];

Thank you for considering this suggestion. I look forward to hearing your thoughts!

svobik7 commented 4 months ago

Hi @jmoros this is actually great idea 👍 IMO I would go for option 2. where you have explicitly define excluded route names. That is crystal clear then:

// locales: ['en', 'it']
// routes/example-page/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', exclude: true }
];

Will just think about the best naming here. Should it be:

Probably skip: true looks the best.

Do you think you would be able to create a PR for this feature?

zto-sbenning commented 1 month ago

Hi,

Should this setting be inherited by the descendant pages/layouts/templates on this path ? Let's say we have:

// locales: ['en', 'it']
// routes/example-page/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', skip: true }
];

// routes/example-page/example-child/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-child' },
  { locale: 'it', path: 'esempio-figlio' }
];

Should app/example-page/esempio-figlio/page.tsx be generated ? I don't see any use case for this, but I'm asking for clarity.

svobik7 commented 1 month ago

@zto-sbenning skipping child pages automatically would bring more complexity to this task as some inheritance logic would have to be put in place.

I would prefer letting user/developer having granular control. So to answer your question:

Yes, app/example-page/esempio-figlio/page.tsx will be generated.

Also does not see any use-case but the implementation will be easier then, what do you think?

zto-sbenning commented 1 month ago

@svobik7 Yes for sure.

In that case, providing:

// locales: ['en', 'it']
// routes/example-page/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', path: 'pagina-esempio', skip: true } // `path` can still be provided with `skip`
];

// routes/example-page/example-child/i18n.ts
export const routeNames = [
  { locale: 'en', path: 'example-child' },
  { locale: 'it', path: 'esempio-figlio' }
];

Would generate app/it/pagina-esempio/esempio-figlio/page.tsx but not app/it/pagina-esempio/page.tsx.

Should this option concern pages solely, or should it skip the generation of layouts and templates too? Maybe we can consider a more complex API (if needed) to let the user/developer choose what to skip?

(just droping ideas):


export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', path: 'pagina-esempio', skip: true, skipLayout: true, skipTemplate: true }
];

// or

export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', path: 'pagina-esempio', skip: { page: true, layout: true, template: true } }
];

// or

export const routeNames = [
  { locale: 'en', path: 'example-page' },
  { locale: 'it', path: 'pagina-esempio', skip: ["page", "layout", "template"] }
];

However, I would like to hear your thoughts on this.

svobik7 commented 1 month ago

Good points

I like the syntax where I can either:

  1. set skip: true and everything will be skipped
  2. or set skip: {page: true, ...} and choose explicitly what will be skipped

But I am also not sure if we are not overcomplicating that. Is there any real use-case for 2.? Does it makes sense to allow users to skip layouts but not page for example?

zto-sbenning commented 1 month ago

I think we can find some use cases.

Skip layout/template but not page if:

// roots/catalog/layout.tsx
// roots/catalog/[category]/page.tsx
// roots/catalog/[category]/[product]/page.tsx

The layout defines some marketing popups to show on all category/product pages. But for some locales, that marketing content is not ready yet. One might want to skip this layout while keeping the pages underneath.

Skip page but not layout if:

// roots/catalog/layout.tsx
// roots/catalog/page.tsx
// roots/catalog/[category]/page.tsx

The layout defines some side content for the catalog index page and for each category page. The catalog index has marketing contributions from a CMS that are not ready for some locales. However, the categories come from a fully translated PIM. One might want to release the category pages and delay the release of the index page.


I'm not sure if these use cases are legit, and there are certainly workarounds to overcome them (e.g., just throw a redirect in the catalog index if the locale is not yet supported). However, it can be beneficial to have a sitemap directly mapped to the app directory.

I really like your API proposal though!

What do you think?