i18n icon indicating copy to clipboard operation
i18n copied to clipboard

URL with URL-encoded characters like %23 gets decoded when changing locale

Open 0x2c9 opened this issue 1 year ago • 4 comments

Environment


  • Operating System: Linux
  • Node Version: v18.18.0
  • Nuxt Version: 3.11.2
  • CLI Version: 3.11.1
  • Nitro Version: 2.9.6
  • Package Manager: [email protected]
  • Builder: -
  • User Config: devtools, modules, i18n, ssr
  • Runtime Modules: @nuxtjs/[email protected]
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/i18n-url-encoding-issue?file=app.vue

Describe the bug

If an URL contains an URL-encoded character like "%23" and we switch the language, the url gets decoded and converted into a "#" which breaks for example the $route.params usage.

  1. Open Reproduction
  2. Click "Go to my-blog-post%23number1-someid" link
  3. Change locale
  4. Observe $route.params

Before locale change the route params are: (which vue-router already decodes correctly) { "slug": "my-blog-post#number1-someid" }

after locale change: { "slug": "my-blog-post" }

and we get a route hash #number1-someid

You can also open the preview in a new tab to see the decoding in the URL bar.

The only other issue I found which could be maybe related to this is: https://github.com/nuxt-modules/i18n/issues/2698

Additional context

No response

Logs

No response

0x2c9 avatar Apr 12 '24 10:04 0x2c9

It's been a while back since I dived into debugging and figuring out a solution for #2698 but from what I remember the core cause of your issue is the same, I should probably update the issue description.

The module internally uses $router.resolve to retrieve the localized route based on the passed argument. In some cases the resolve function is used more than once with a previous resolved result, unfortunately doing so loses information:

const router = useRouter()
const arg = '/en/blog/my-blog-post%23number1-someid'
const resolved1 = router.resolve(arg)
const resolved2 = router.resolve(resolved1)

console.table({ arg, resolved1: resolved1.fullPath, resolved2: resolved2.fullPath })

Would result in this

key value
arg /en/blog/my-blog-post%23number1-someid
resolved1 /en/blog/my-blog-post%23number1-someid
resolved2 /en/blog/my-blog-post#number1-someid

I have some working concepts that deal with this issue from a while ago but they involve some larger changes to the routing logic, it will take time to test and see which solution makes most sense. So unfortunately I won't have a solution in the short term! Will let you know if I find any workarounds to use instead.

BobbieGoede avatar Apr 12 '24 13:04 BobbieGoede

Kind a same issue here, where the output of localePath now containers %3F at the end.

memic84 avatar Apr 19 '24 09:04 memic84

@memic84 What are you passing to localePath?

BobbieGoede avatar Apr 19 '24 09:04 BobbieGoede

@BobbieGoede my mistake, for reason a question mark was appended in the route name. Fixed and not a module issue.

memic84 avatar Apr 19 '24 12:04 memic84

Closing this as duplicate, let's keep tracking it here #2698

BobbieGoede avatar Sep 26 '24 10:09 BobbieGoede