Skip to content

Commit af34482

Browse files
authored
fix: skip localizing routeRules redirect stub pages (#4048)
1 parent 1d37825 commit af34482

2 files changed

Lines changed: 56 additions & 2 deletions

File tree

src/pages.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export const disabledPaths = ${JSON.stringify(routeResources.disabledPaths, null
8181

8282
const projectLayer = nuxt.options._layers[0]
8383
const typedRouter = await setupExperimentalTypedRoutes(options, nuxt)
84+
// nuxt's pages runtime dir is a sibling of `appDir` in its dist
85+
const stubFile = resolve(nuxt.options.appDir, '../pages/runtime/component-stub')
8486

8587
nuxt.options.experimental.extraPageMetaExtractionKeys ??= []
8688
nuxt.options.experimental.extraPageMetaExtractionKeys.push('i18n')
@@ -102,7 +104,7 @@ export const disabledPaths = ${JSON.stringify(routeResources.disabledPaths, null
102104
// normalize per-mode route options into route meta before localization
103105
normalizeRouteMeta(ctx, pages, localeCodes, options.customRoutes ?? 'page', nuxt.vfs)
104106

105-
const resolver = createPureOptionsResolver(ctx, options.defaultLocale, options.customRoutes)
107+
const resolver = createPureOptionsResolver(ctx, options.defaultLocale, options.customRoutes, stubFile)
106108
const resources = createRouteResourcesCollector()
107109

108110
const localizationOptions = {
@@ -352,9 +354,13 @@ export function createPureOptionsResolver(
352354
ctx: NuxtPageAnalyzeContext,
353355
defaultLocale: string,
354356
customRoutes: NuxtI18nOptions['customRoutes'],
357+
/** extensionless path of nuxt's page component stub */
358+
stubFile?: string,
355359
): RouteOptionsResolver {
356360
const cache = new Map<string, ComputedRouteOptions | undefined>()
357361
return (route, localeCodes) => {
362+
// skip - stub pages nuxt injects for `routeRules` redirects, the rules only match unprefixed paths (#3606)
363+
if (stubFile && route.file?.replace(/\.\w+$/, '') === stubFile) { return undefined }
358364
const key = `${route.file ?? route.name ?? route.path}::${localeCodes.join(',')}`
359365
if (cache.has(key)) { return cache.get(key) }
360366
const resolved = getRouteOptions(route, localeCodes, ctx, defaultLocale, customRoutes)

test/pages/route_localization.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, it, expect } from 'vitest'
22
import { createRouteResourcesCollector, localizeRoutes } from '../../src/routing'
33
import { localizeSingleRoute, createRouteContext, canCompactRoute } from '../../src/kit/gen'
4-
import { collectCompactPrerenderRoutes } from '../../src/pages'
4+
import { collectCompactPrerenderRoutes, createPureOptionsResolver, NuxtPageAnalyzeContext } from '../../src/pages'
55
import { createMockOptionsResolver, createTestConfig, getNormalizedLocales } from './utils'
66

77
import type { LocalizableRoute, LocalizeRouteParams } from '../../src/kit/gen'
@@ -639,6 +639,54 @@ describe('createRouteResourcesCollector', () => {
639639
})
640640
})
641641

642+
// nuxt injects stub pages for `routeRules` redirects, the rules only match unprefixed paths (#3606)
643+
describe.each([false, true])('routeRules redirect stubs (compactRoutes: %s)', (compactRoutes) => {
644+
const stubFile = '/app/node_modules/nuxt/dist/pages/runtime/component-stub'
645+
646+
function makeConfig(resolver: ReturnType<typeof createPureOptionsResolver>) {
647+
return createTestConfig({
648+
locales: ['en', 'fr'],
649+
strategy: 'prefix_except_default',
650+
defaultLocale: 'en',
651+
optionsResolver: resolver,
652+
compactRoutes,
653+
})
654+
}
655+
656+
it('passes stubs through unlocalized and keeps them out of route resources', () => {
657+
const resolver = createPureOptionsResolver(new NuxtPageAnalyzeContext({}), 'en', 'config', stubFile)
658+
const collector = createRouteResourcesCollector()
659+
const result = localizeRoutes(
660+
[
661+
{ path: '/about', name: 'about', file: '/pages/about.vue' },
662+
{ _sync: true, path: '/old-path', file: `${stubFile}.js` },
663+
],
664+
{ ...makeConfig(resolver), onLocalize: collector.collect },
665+
)
666+
667+
const stubs = result.filter(r => r.path.includes('old-path'))
668+
expect(stubs).toHaveLength(1)
669+
expect(stubs[0]!.path).toBe('/old-path')
670+
expect(result.find(r => r.path === (compactRoutes ? '/:locale(fr)/about' : '/fr/about'))).toBeDefined()
671+
672+
const resources = collector.toResources()
673+
expect(resources.localizedPaths).not.toContain('/old-path')
674+
expect(resources.disabledPaths).not.toContain('/old-path')
675+
})
676+
677+
it('does not skip a project page named component-stub', () => {
678+
const resolver = createPureOptionsResolver(new NuxtPageAnalyzeContext({}), 'en', 'config', stubFile)
679+
const result = localizeRoutes(
680+
[{ path: '/runtime/component-stub', name: 'stub-page', file: '/pages/runtime/component-stub.vue' }],
681+
makeConfig(resolver),
682+
)
683+
expect(result.find(r => r.name === 'stub-page___en')).toBeDefined()
684+
expect(
685+
result.find(r => r.path === (compactRoutes ? '/:locale(fr)/runtime/component-stub' : '/fr/runtime/component-stub')),
686+
).toBeDefined()
687+
})
688+
})
689+
642690
// ---------------------------------------------------------------------------
643691
// e) canCompactRoute
644692
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)