Skip to content

Commit

Permalink
refactor: merge and restructure runtime routing logic
Browse files Browse the repository at this point in the history
  • Loading branch information
BobbieGoede committed Dec 24, 2024
1 parent 5a93507 commit 9ad2c6d
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 227 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"lint:eslint": "eslint .",
"test": "pnpm build && run-s test:types test:unit test:spec",
"test:types": "tsc --noEmit",
"test:unit": "vitest run test",
"test:unit": "vitest run test -c vitest.config.test.ts",
"test:spec": "vitest run specs"
},
"pnpm": {
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import {
getHreflangLinks,
getOgUrl,
localeHead
} from '../routing/compatibles/head'
import { getRouteBaseName, localePath, localeRoute, switchLocalePath } from '../routing/compatibles/routing'
} from '../routing/head'
import { getRouteBaseName, localePath, localeRoute, switchLocalePath } from '../routing/routing'
import { findBrowserLocale } from '../routing/utils'
import { getComposer } from '../compatibility'
import type { Ref } from 'vue'
import type { Locale } from 'vue-i18n'
import type { resolveRoute } from '../routing/compatibles/routing'
import type { resolveRoute } from '../routing/routing'
import type { I18nHeadMetaInfo, I18nHeadOptions, LocaleObject, SeoAttributesOptions } from '#internal-i18n-types'
import type { HeadParam } from '../utils'
import type { RouteLocationAsRelativeI18n, RouteLocationRaw, RouteLocationResolvedI18n, RouteMapI18n } from 'vue-router'
Expand Down
11 changes: 5 additions & 6 deletions src/runtime/plugins/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ import {
wrapComposable,
defineGetter
} from '../internal'
import { inBrowser, resolveBaseUrl } from '../routing/utils'
import { extendI18n } from '../routing/extends/i18n'
import { createLocaleFromRouteGetter } from '../routing/extends/router'
import { createLocaleFromRouteGetter, resolveBaseUrl } from '../routing/utils'
import { extendI18n } from '../routing/i18n'
import { createLogger } from 'virtual:nuxt-i18n-logger'
import { getI18nTarget } from '../compatibility'
import { resolveRoute } from '../routing/compatibles/routing'
import { localeHead } from '../routing/compatibles/head'
import { resolveRoute } from '../routing/routing'
import { localeHead } from '../routing/head'
import { useLocalePath, useLocaleRoute, useRouteBaseName, useSwitchLocalePath, useLocaleLocation } from '../composables'

import type { Locale, I18nOptions, Composer, I18n } from 'vue-i18n'
Expand Down Expand Up @@ -108,7 +107,7 @@ export default defineNuxtPlugin({
composer.localeCodes = computed(() => _localeCodes.value)
composer.baseUrl = computed(() => _baseUrl.value)

if (inBrowser) {
if (import.meta.client) {
watch(
composer.locale,
() => {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/plugins/route-locale-detect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { unref } from 'vue'
import { hasPages, isSSG } from '#build/i18n.options.mjs'
import { addRouteMiddleware, defineNuxtPlugin, defineNuxtRouteMiddleware } from '#imports'
import { createLogger } from 'virtual:nuxt-i18n-logger'
import { createLocaleFromRouteGetter } from '../routing/extends/router'
import { detectLocale, detectRedirect, loadAndSetLocale, navigate } from '../utils'
import { createLocaleFromRouteGetter } from '../routing/utils'

import type { NuxtApp } from '#app'
import type { CompatRoute } from '../types'
Expand Down
66 changes: 0 additions & 66 deletions src/runtime/routing/compatibles/utils.ts

This file was deleted.

38 changes: 0 additions & 38 deletions src/runtime/routing/extends/router.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { joinURL } from 'ufo'
import { isArray, isObject } from '@intlify/shared'
import { unref, useNuxtApp, useRuntimeConfig } from '#imports'

import { getNormalizedLocales } from '../utils'
import { getNormalizedLocales } from './utils'
import { getRouteBaseName, localeRoute, switchLocalePath } from './routing'
import { getComposer } from '../../compatibility'
import { getComposer } from '../compatibility'

import type { I18n } from 'vue-i18n'
import type { I18nHeadMetaInfo, MetaAttrs, LocaleObject, I18nHeadOptions } from '#internal-i18n-types'
import type { CommonComposableOptions } from '../../utils'
import type { CommonComposableOptions } from '../utils'

/**
* Returns localized head properties for locale-related aspects.
Expand Down Expand Up @@ -45,7 +45,7 @@ export function localeHead(

const locale = unref(nuxtApp.$i18n.locale)
const locales = unref(nuxtApp.$i18n.locales)
const currentLocale = getNormalizedLocales(locales).find(l => l.code === locale) || {
const currentLocale: LocaleObject = getNormalizedLocales(locales).find(l => l.code === locale) || {
code: locale
}
const currentLanguage = currentLocale.language
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { effectScope } from '#imports'
import { isVueI18n, getComposer } from '../../compatibility'
import { isVueI18n, getComposer } from '../compatibility'

import type { NuxtApp } from 'nuxt/app'
import type { Composer, ComposerExtender, ExportedGlobalComposer, I18n, VueI18n, VueI18nExtender } from 'vue-i18n'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { hasProtocol, parsePath, parseQuery, withTrailingSlash, withoutTrailingS
import { DEFAULT_DYNAMIC_PARAMS_KEY } from '#build/i18n.options.mjs'
import { unref } from '#imports'

import { getI18nTarget } from '../../compatibility'
import { resolve, routeToObject } from './utils'
import { getLocaleRouteName, getRouteName } from '../utils'
import { extendPrefixable, extendSwitchLocalePathIntercepter, type CommonComposableOptions } from '../../utils'
import { getI18nTarget } from '../compatibility'
import { getLocaleRouteName, getRouteName } from './utils'
import { extendPrefixable, extendSwitchLocalePathIntercepter, type CommonComposableOptions } from '../utils'

import type { Strategies, PrefixableOptions } from '#internal-i18n-types'
import type { Locale } from 'vue-i18n'
import type { RouteLocation, RouteLocationRaw, Router, RouteLocationPathRaw, RouteLocationNamedRaw } from 'vue-router'
import type { I18nPublicRuntimeConfig } from '#internal-i18n-types'
import type { CompatRoute } from '../../types'
import type { CompatRoute } from '../types'

const RESOLVED_PREFIXED = new Set<Strategies>(['prefix_and_default', 'prefix_except_default'])

Expand Down Expand Up @@ -241,3 +240,62 @@ export function switchLocalePath(common: CommonComposableOptions, locale: Locale
// custom locale path with interceptor
return switchLocalePathIntercepter(path, locale)
}

function split(str: string, index: number) {
const result = [str.slice(0, index), str.slice(index)]
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: CompatRoute) {
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.
* `router.hasRoute`, which checks for the route can only be a named route.
* When using the `prefix` strategy, the path specified by `localePath` is specified as a path not prefixed with a locale.
* This will cause vue-router to issue a warning, so we can work-around by using `router.options.routes`.
*/
export function resolve(
{ router }: CommonComposableOptions,
route: RouteLocationPathRaw,
strategy: Strategies,
locale: Locale
) {
if (strategy !== 'prefix') {
return router.resolve(route)
}

// if (isArray(route.matched) && route.matched.length > 0) {
// return route.matched[0]
// }

const [rootSlash, restPath] = split(route.path, 1)
const targetPath = `${rootSlash}${locale}${restPath === '' ? restPath : `/${restPath}`}`
const _route = router.options?.routes?.find(r => r.path === targetPath)

if (_route == null) {
return route
}

const _resolvableRoute = assign({}, route, _route)
_resolvableRoute.path = targetPath
return router.resolve(_resolvableRoute)
}
Loading

0 comments on commit 9ad2c6d

Please sign in to comment.