nuxt-modules / i18n

I18n module for Nuxt
https://i18n.nuxtjs.org
MIT License
1.73k stars 479 forks source link

Dynamic route parameters do not work with dynamic values #2006

Closed ClementZezukaLivestorm closed 10 months ago

ClementZezukaLivestorm commented 1 year ago

Environment

Reproduction

https://stackblitz.com/edit/github-njnv2g?file=pages/blog/[slug].vue

Describe the bug

Hello!

According to this page of the documentation, to set translations for route params we must use definePageMeta.

However, definePageMeta cannot reference the component or values defined on it.

To be crystal clear, variables cannot be injected inside this function and this makes the feature impossible to use at this stage.

It seems like a regression compare to the function i18n/setRouteParams of the version of the module on Nuxt 2 and the documentation is not clear about it.

Is it something that you plan to fix in the future?

Thanks for reading me!

Additional context

No response

Logs

[nuxt] [request error] [unhandled] [500] routes is not defined
  at eval (./pages/blog/[slug].vue:3:5)  
  at ViteNodeRunner.directRequest (file://./node_modules/vite-node/dist/client.mjs:348:11)  
  at async ViteNodeRunner.cachedRequest (file://./node_modules/vite-node/dist/client.mjs:188:14)  
  at async ViteNodeRunner.dependencyRequest (file://./node_modules/vite-node/dist/client.mjs:237:14)  
  at async eval (./virtual:nuxt:/home/projects/github-njnv2g/.nuxt/routes.mjs:1:216)  
  at async ViteNodeRunner.directRequest (file://./node_modules/vite-node/dist/client.mjs:348:5)  
  at async ViteNodeRunner.cachedRequest (file://./node_modules/vite-node/dist/client.mjs:188:14)  
  at async ViteNodeRunner.dependencyRequest (file://./node_modules/vite-node/dist/client.mjs:237:14)  
  at async eval (./node_modules/nuxt/dist/pages/runtime/plugins/router.js:19:31)  
  at async ViteNodeRunner.directRequest (file://./node_modules/vite-node/dist/client.mjs:348:5)
vladyslavprosolupov commented 1 year ago

Had the same issue lately. The temporary solution that I came up with is tricky/messy and doesn't work on server-side.

As you mentioned definePageMeta cannot reference the component or values defined on it as it's a compiler macro, which is compiled away during build. However you can access route-meta directly and overwrite it.

const route = useRoute()
const slug = flatten(route.params.slug)
const { data: page } = await useAsyncData('pageSlug', () =>
  useApi().publicPagesSimplePagesRetrieve(slug)
)

route.meta.nuxtI18n = {
  pl: { slug: page.value?.slug_pl },
  en: { slug: page.value?.slug_en }
}

As I said earlier it does not return correct SEO headers from server (link-alternates, etc) + language-switcher doesn't have correct path (you have to wrap it in ClientOnly in order to work properly).

This is clearly an Issue and should be fixed in the nearest time.

ClementZezukaLivestorm commented 1 year ago

@vladyslavprosolupov Thanks for taking time to answer!

I tried what was described here by @adriaanvanrossum, it worked like a charm.

In my opinion, the documentation should mention his chunk of code as this is currently one of the best / elegant ways to deal with dynamic route parameters.

vladyslavprosolupov commented 1 year ago

@ClementZezukaLivestorm thanks for sharing this, I haven't thought of redefining head meta directly from page! Clever hack, but still, I believe, it should be somehow possible by default.

ClementZezukaLivestorm commented 1 year ago

@vladyslavprosolupov I 100% agree.

ThornWalli commented 1 year ago

Hello,

What is the current status here?

I'm a little concerned that defining dynamic routes in nuxt@3 will be a bit more difficult.

Background: There will definitely be websites that get their content from the CMS, including the routes.

In the previous version, you could ideally overwrite the dynamic routes in the async data of a page in the store.

This is now defined by definePageMeta, but this is unsuitable for the use of adding dynamic routes (macro functions lose the scope in the setup and cannot build on existing data there) and can therefore only be used if you know the routes and this fixed built into the project.

I wonder what you thought about the macro functions in general, a bit ugly to distribute them in the code that defines one scope and ends up somewhere completely different.

That's why I think the tag "Nice-To-Have" should be viewed a bit critically here 😉 it's a functionality that is essential for larger pages 🙂

Using this line of code route.meta.nuxtI18n = blog.value?.languages || {}; doesn't seem like a real workaround either.

There is some change in the client, but on the SSR (Initial) there are discrepancies very quickly.

My Page Setup:

import { useHead, usePageContent, useRoute, useLocaleHead } from '#imports';

const { fetch } = usePageContent();
const { components, pageMeta } = await fetch();

const route = useRoute();

if (pageMeta?.nuxtI18n) {
  route.meta.nuxtI18n = pageMeta?.nuxtI18n;
}

const i18nHead = useLocaleHead({
  identifierAttribute: 'id',
  addSeoAttributes: true
});

useHead({
  ...i18nHead.value,
  title: () => pageMeta.title
});

image

PS: I only see the correct values in the language switch when the client routes change.

BobbieGoede commented 10 months ago

With #2580 merged and released in rc.9 I will close this issue.

Try out the new useSetI18nParams composable, more detailed example of its usage here! Internally it works in a similar way to the workarounds described here, but improves on it by updating meta tags during SSR as well.

If you run into any bugs please open a new issue with a minimal reproduction 💪