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

fix: switch locale path loses query parameters #46

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions packages/vue-i18n-routing/src/compatibles/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isVue3, isRef, unref, isVue2 } from 'vue-demi'
import { DEFAULT_DYNAMIC_PARAMS_KEY } from '../constants'
import { getLocale, getLocaleRouteName, getRouteName } from '../utils'

import { getI18nRoutingOptions, resolve } from './utils'
import { getI18nRoutingOptions, resolve, routeToObject } from './utils'

import type { RoutingProxy, PrefixableOptions, SwitchLocalePathIntercepter } from './types'
import type { Strategies, I18nRoutingOptions } from '../types'
Expand Down Expand Up @@ -298,23 +298,24 @@ export function switchLocalePath(this: RoutingProxy, locale: Locale): string {
const { switchLocalePathIntercepter, dynamicRouteParamsKey } = getI18nRoutingOptions(this.router, this)

// prettier-ignore
const { params, ...routeCopy } = isVue3
const routeValue = isVue3
? (route as RouteLocationNormalizedLoaded) // for vue-router v4
: isRef<Route>(route) // for vue-router v3
? route.value
: route
const routeCopy = routeToObject(routeValue)
const langSwitchParams = getLocalizableMetaFromDynamicParams(route, dynamicRouteParamsKey)[locale] || {}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const _baseRoute: any = {
name,
params: {
...params,
...routeCopy.params,
...langSwitchParams
}
}
if (isVue2) {
_baseRoute.params[0] = params.pathMatch
_baseRoute.params[0] = routeCopy.params.pathMatch
}

const baseRoute = assign({}, routeCopy, _baseRoute)
Expand Down
22 changes: 21 additions & 1 deletion packages/vue-i18n-routing/src/compatibles/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type { RoutingProxy } from './types'
import type { I18nRoutingGlobalOptions } from '../extends/router'
import type { Strategies } from '../types'
import type { Locale } from '@intlify/vue-i18n-bridge'
import type { VueRouter, Router } from '@intlify/vue-router-bridge'
import type { VueRouter, Router, Route, RouteLocationNormalizedLoaded } from '@intlify/vue-router-bridge'

export function getI18nRoutingOptions(
router: Router | VueRouter,
Expand Down Expand Up @@ -58,6 +58,26 @@ function split(str: string, index: number) {
return result
}

/**
* NOTE:
* Nuxt route uses a proxy with getters for performance reasons (https://github.com/nuxt/nuxt/pull/21957).
* Spreading will result in an empty object, so we make a copy of the route by accessing each getter property by name.
*/
export function routeToObject(route: Route | RouteLocationNormalizedLoaded) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below is your Description on this PR:

Does not work for @nuxtjs/i18n or maybe it is a Nuxt related issue, I noticed that the route object was a proxy and accessing each property did work. So I added a function to destructure each property by name instead of using a spread operator.
Unfortunately I don't know why the behaviour is like this, and I don't think I can add tests for this case as it may be Nuxt related.

Let’s write the comment !, so maintainer can understand the background when we read this code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a short description now, hopefully it is informative enough.

const { fullPath, query, hash, name, path, params, meta, redirectedFrom, matched } = route
return {
fullPath,
params,
query,
hash,
name,
path,
meta,
matched,
redirectedFrom
}
}

/**
* NOTE:
* vue-router v4.x `router.resolve` for a non exists path will output a warning.
Expand Down