Next.js: Impossible to programmatically switch language via router.push in dynamic routes

Created on 12 Nov 2020  路  2Comments  路  Source: vercel/next.js

Bug report

Describe the bug

I currently have a menu bar with a switch language button globally in my code. There, I'm using the push strategy suggested in the docs Transition between locales:

router.push('/another', '/another', { locale: 'fr' })

This approach works for most of my site but for dynamic routes.

In some cases I have the same page (/tag/[slug]) in both PT and EN:

  • /tag/css/
  • /pt/tag/css

It would work fine by just doing:

const { pathname, push } = useRouter()

const switchLocale = nextLocale => push(pathname, pathname, { locale: nextLocale })

However I get an error:

Unhandled Runtime Error

Error: The provided `href` (/blog/[slug]) value is missing query values (slug) to be interpolated properly. Read more: https://err.sh/vercel/next.js/href-interpolation-failed

My first guess would be pass query as options, however it does not accept it.

To Reproduce

  1. Access this codesandbox: https://codesandbox.io/s/next-js-dynamic-route-push-bug-cx1zd
  2. Click to navigate to /blog/foo (Post in English)
  3. Than click in the button to switch to portuguese
  4. See error

Expected behavior

Be able to pass to push the query params so I can have a consistent way to transition between locales.

Screenshots

Screenshot from 2020-11-12 22-54-39

System information

  • Version of Next.js: 10.0.2-canary.12
bug

Most helpful comment

Hi, to achieve this you should use pathname and the query for the href argument and then the asPath for the second argument. Currently you're passing the page name twice which doesn't allow the dynamic route params to be parsed correctly as they aren't provided as an argument.

const { pathname, asPath, query } = useRouter()

// you can do interpolation
router.push({ pathname, query }, asPath, { locale: nextLocale });

All 2 comments

Hi, to achieve this you should use pathname and the query for the href argument and then the asPath for the second argument. Currently you're passing the page name twice which doesn't allow the dynamic route params to be parsed correctly as they aren't provided as an argument.

const { pathname, asPath, query } = useRouter()

// you can do interpolation
router.push({ pathname, query }, asPath, { locale: nextLocale });

Hey @ijjk thanks for the tip, in this way works...

I think this edge case should be documented as part of the internalization route or at least the error page at shows up in the error.

Now it seems a little puzzle.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lixiaoyan picture lixiaoyan  路  3Comments

havefive picture havefive  路  3Comments

kenji4569 picture kenji4569  路  3Comments

knipferrc picture knipferrc  路  3Comments

olifante picture olifante  路  3Comments