Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using definePageMeta({ name: ... }) breaks route generation #2581

Closed
Anoesj opened this issue Nov 30, 2023 · 4 comments · Fixed by #2837
Closed

Using definePageMeta({ name: ... }) breaks route generation #2581

Anoesj opened this issue Nov 30, 2023 · 4 comments · Fixed by #2837
Labels
custom route path 🔨 p3-minor-bug Priority 3: a bug in an edge case that only affects very specific usage routing upstream issue v8

Comments

@Anoesj
Copy link

Anoesj commented Nov 30, 2023

Environment


  • Operating System: Linux
  • Node Version: v20.9.0
  • Nuxt Version: 3.8.2
  • CLI Version: 3.10.0
  • Nitro Version: 2.8.0
  • Package Manager: pnpm@8.11.0
  • Builder: -
  • User Config: ssr, experimental, modules, app, runtimeConfig, i18n, imports, typescript, devtools, vite, vue, image
  • Runtime Modules: @nuxtjs/stylelint-module@5.1.0, @pinia/nuxt@0.5.1, nuxt-schema-org@3.2.1, @nuxtjs/i18n@8.0.0-rc.5, @nuxt/image@1.1.0
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/bobbiegoede-nuxt-i18n-starter-jiqdtm?file=app.vue

Note that only the /ja route works here, which is exactly why I'm writing this bug report.

Describe the bug

Let's assume the following base Nuxt i18n configuration with all examples below:

{
  defaultLocale: 'nl',
  lazy: true,
  langDir: 'locales',
  differentDomains: false,
  strategy: 'prefix',
  detectBrowserLanguage: false,
  locales: [
    {
      name: 'Nederlands',
      code: 'nl',
      iso: 'nl',
      file: 'nl.json',
    },
    {
      name: 'English',
      code: 'en',
      iso: 'en',
      file: 'en.json',
    },
    {
      name: 'Français',
      code: 'fr',
      iso: 'fr',
      file: 'fr.json',
    },
    {
      name: 'Deutsch',
      code: 'de',
      iso: 'de',
      file: 'de.json',
    },
  ],
}

A page can be named using:

// pages/products.vue
definePageMeta({
  name: 'products',
});

There are two situations where Nuxt i18n doesn't work nicely with named routes:

  1. customRoutes: 'config' and route translations for products in nuxt.config.ts:
// nuxt.config.ts
customRoutes: 'config',
pages: {
  'products': {
    nl: '/producten',
    en: '/products',
    fr: '/produits',
    de: '/produkte',
  },
}
  1. customRoutes: 'page' and route translations for products inside products.vue using defineI18nRoute:
definePageMeta({
  name: 'products',
});

defineI18nRoute({
  paths: {
    nl: '/producten',
    en: '/products',
    fr: '/produits',
    de: '/produkte',
  },
});

In these scenarios, only last translation route is actually available in the application, so /de/produkte in this case. Why? If we take a look at Nuxt DevTools "Virtual Files" tab and go to #build/routes, we'll find something like this:

import { default as indexZVoLS0zmLOMeta } from "/path/to/project/pages/products.vue?macro=true";
export default [
  {
    name: indexZVoLS0zmLOMeta?.name ?? "products",
    path: indexZVoLS0zmLOMeta?.path ?? "/products",
    meta: indexZVoLS0zmLOMeta || {},
    alias: indexZVoLS0zmLOMeta?.alias || [],
    redirect: indexZVoLS0zmLOMeta?.redirect || undefined,
    component: () => import("/path/to/project/pages/products.vue").then(m => m.default || m)
  },
  {
    name: indexZVoLS0zmLOMeta?.name ?? "products___nl",
    path: indexZVoLS0zmLOMeta?.path ?? "/nl/producten",
    meta: indexZVoLS0zmLOMeta || {},
    alias: indexZVoLS0zmLOMeta?.alias || [],
    redirect: indexZVoLS0zmLOMeta?.redirect || undefined,
    component: () => import("/path/to/project/pages/products.vue").then(m => m.default || m)
  },
  {
    name: indexZVoLS0zmLOMeta?.name ?? "products___en",
    path: indexZVoLS0zmLOMeta?.path ?? "/en/products",
    meta: indexZVoLS0zmLOMeta || {},
    alias: indexZVoLS0zmLOMeta?.alias || [],
    redirect: indexZVoLS0zmLOMeta?.redirect || undefined,
    component: () => import("/path/to/project/pages/products.vue").then(m => m.default || m)
  },
  {
    name: indexZVoLS0zmLOMeta?.name ?? "products___fr",
    path: indexZVoLS0zmLOMeta?.path ?? "/fr/produits",
    meta: indexZVoLS0zmLOMeta || {},
    alias: indexZVoLS0zmLOMeta?.alias || [],
    redirect: indexZVoLS0zmLOMeta?.redirect || undefined,
    component: () => import("/path/to/project/pages/products.vue").then(m => m.default || m)
  },
  {
    name: indexZVoLS0zmLOMeta?.name ?? "products___de",
    path: indexZVoLS0zmLOMeta?.path ?? "/de/produkte",
    meta: indexZVoLS0zmLOMeta || {},
    alias: indexZVoLS0zmLOMeta?.alias || [],
    redirect: indexZVoLS0zmLOMeta?.redirect || undefined,
    component: () => import("/path/to/project/pages/products.vue").then(m => m.default || m)
  },

As we can see here, the page name we specified ourselves takes precedence over the name Nuxt i18n generated. As all these routes will eventually have { name: 'products' }, the last route with that name will become the only one that's actually registered in the router.

Not sure what the best solutions would be here. Might be:

  • Improve documentation
  • Somehow don't let user decided page name take precedence in #build/routes
  • ...

Additional context

No response

Logs

No response

@BobbieGoede
Copy link
Collaborator

Unfortunately we can't do much to make this work as is, whenever a name is set using definePageMeta it is read directly from file and generated as you already found out (source code).

After trying to find a solution I think I can expand the defineI18nRoute parameter to also accept a name property so it can still be used to resolve routes, but we would still need to make sure that no name is set using definePageMeta.

@BobbieGoede BobbieGoede added ❗ p4-important Priority 4: bugs that violate documented behavior, or significantly impact perf routing and removed pending triage labels Dec 15, 2023
@BobbieGoede BobbieGoede changed the title Custom route translations don't play nicely with named page components using definePageMeta Using definePageMeta({ name: ... }) breaks route generation Dec 15, 2023
@BobbieGoede BobbieGoede added upstream issue 🔨 p3-minor-bug Priority 3: a bug in an edge case that only affects very specific usage and removed ❗ p4-important Priority 4: bugs that violate documented behavior, or significantly impact perf labels Dec 22, 2023
@BobbieGoede
Copy link
Collaborator

The proper fix for this issue will require some changes upstream in Nuxt, related issue nuxt/nuxt#24770

@BobbieGoede
Copy link
Collaborator

With nuxt/nuxt#25210 merged, it will be possible to use named routes while using the i18n module once Nuxt v3.10 has been released. You will have to enable the scanPageMeta experimental Nuxt feature in your nuxt config like so: experimental: { scanPageMeta: true }.

You can already try it out by installing the Nuxt nightly release, I've changed your reproduction to demonstrate here.

I'll add this to the docs after Nuxt's release, maybe I'll wait for #2740 to be finished/merged first. After all that is done, I think we'll be able close this issue 😄

@Rigo-m
Copy link

Rigo-m commented Jan 31, 2024

@BobbieGoede is there an equivalent for i18n?
I.e.: I want to write a quick module that scans defineI18nRoute and programmatically change it based on environment logic, can I do it somehow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
custom route path 🔨 p3-minor-bug Priority 3: a bug in an edge case that only affects very specific usage routing upstream issue v8
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants