@@ -5,7 +5,8 @@ import { parse as parseSFC } from '@vue/compiler-sfc'
55import { parseAndWalk } from 'oxc-walker'
66import { mkdir , readFile , writeFile } from 'node:fs/promises'
77import { parseSegment , toVueRouterSegment } from 'unrouting'
8- import { localizeRoutes , shouldLocalizeRoutes } from './routing'
8+ import { createRouteResourcesCollector , localizeRoutes } from './routing'
9+ import type { RouteResources } from './routing'
910import { logger } from './utils'
1011import { dirname , parse as parsePath , resolve } from 'pathe'
1112import { createRoutesContext , resolveOptions } from 'vue-router/unplugin'
@@ -15,24 +16,20 @@ import type { Nuxt, NuxtPage, ResolvedNuxtTemplate } from '@nuxt/schema'
1516import type { EditableTreeNode , Options as TypedRouterOptions } from 'vue-router/unplugin'
1617import type { NuxtI18nOptions } from './types'
1718import type { I18nNuxtContext } from './context'
18- import type { ComputedRouteOptions , LocalizableRoute , RouteOptionsResolver } from './kit/gen'
19+ import type { ComputedRouteOptions , RouteOptionsResolver } from './kit/gen'
1920import type { I18nRoute } from './runtime/composables'
2021import { type CallExpression , type ExpressionStatement , type ObjectExpression , parseSync } from 'oxc-parser'
2122
2223export class NuxtPageAnalyzeContext {
2324 config : NuxtI18nOptions [ 'pages' ]
2425 pages : Map < string , { path : string , name ?: string } > = new Map ( )
25- pathToConfig : Record < string , Record < string , string | boolean > | undefined > = { }
26- fileToPath : Record < string , string > = { }
2726
2827 constructor ( config : NuxtI18nOptions [ 'pages' ] ) {
2928 this . config = config || { }
3029 }
3130
3231 addPage ( page : NuxtPage , path : string , name ?: string ) {
3332 this . pages . set ( page . file ! , { path, name } )
34- const p = path === 'index' ? '/' : '/' + path . replace ( / \/ i n d e x $ / , '' )
35- this . fileToPath [ page . file ! ] = p
3633 }
3734}
3835
@@ -42,20 +39,22 @@ type NarrowedNuxtPage = Omit<NuxtPage, 'redirect' | 'children'> & {
4239}
4340
4441export async function setupPages ( { localeCodes, options, normalizedLocales } : I18nNuxtContext , nuxt : Nuxt ) {
45- const routeResources = {
46- i18nPathToPath : { } ,
42+ let routeResources : RouteResources = {
43+ localizedPaths : [ ] ,
4744 pathToI18nConfig : { } ,
48- disabledI18nPathToPath : { } ,
45+ i18nPathToPath : { } ,
46+ disabledPaths : [ ] ,
4947 }
5048
5149 addTemplate ( {
5250 filename : 'i18n-route-resources.mjs' ,
5351 write : true ,
5452 getContents : ( ) => {
5553 return `// Generated by @nuxtjs/i18n
54+ export const localizedPaths = ${ JSON . stringify ( routeResources . localizedPaths , null , 2 ) } ;
5655export const pathToI18nConfig = ${ JSON . stringify ( routeResources . pathToI18nConfig , null , 2 ) } ;
57- export const i18nPathToPath = ${ JSON . stringify ( routeResources . i18nPathToPath , null , 2 ) }
58- export const disabledI18nPathToPath = ${ JSON . stringify ( routeResources . disabledI18nPathToPath , null , 2 ) } ;`
56+ export const i18nPathToPath = ${ JSON . stringify ( routeResources . i18nPathToPath , null , 2 ) } ;
57+ export const disabledPaths = ${ JSON . stringify ( routeResources . disabledPaths , null , 2 ) } ;`
5958 } ,
6059 } )
6160 if ( ! localeCodes . length ) { return }
@@ -104,21 +103,18 @@ export const disabledI18nPathToPath = ${JSON.stringify(routeResources.disabledI1
104103 normalizeRouteMeta ( ctx , pages , localeCodes , options . customRoutes ?? 'page' , nuxt . vfs )
105104
106105 const resolver = createPureOptionsResolver ( ctx , options . defaultLocale , options . customRoutes )
106+ const resources = createRouteResourcesCollector ( )
107107
108108 const localizationOptions = {
109109 ...options ,
110110 locales : normalizedLocales ,
111111 optionsResolver : resolver ,
112112 compactRoutes : ! ! options . experimental ?. compactRoutes ,
113+ onLocalize : resources . collect ,
113114 }
114115
115116 const localizedPages = localizeRoutes ( pages as NarrowedNuxtPage [ ] , localizationOptions )
116117
117- // Build path config from original pages (not localized copies)
118- if ( shouldLocalizeRoutes ( localizationOptions ) ) {
119- buildPathToConfig ( ctx , localeCodes , resolver , pages as LocalizableRoute [ ] )
120- }
121-
122118 // keep root when using prefixed routing without prerendering
123119 const indexPage = pages . find ( x => x . path === '/' )
124120 if ( options . strategy === 'prefix' && indexPage != null ) {
@@ -129,28 +125,7 @@ export const disabledI18nPathToPath = ${JSON.stringify(routeResources.disabledI1
129125 // (the boolean form is kept, it marks routes with disabled localization at runtime)
130126 stripRouteMetaI18n ( localizedPages )
131127
132- const invertedMap = { } as Record < string , Record < string , string | false > >
133- const localizedMapInvert : Record < string , string > = { }
134- const notLocalizedMapInvert : Record < string , string > = { }
135- for ( const [ path , localeConfig ] of Object . entries ( ctx . pathToConfig ) ) {
136- const resPath = resolveRoutePath ( path )
137- invertedMap [ resPath ] ??= { }
138- let hasLocalized = false
139- for ( const [ locale , localePath ] of Object . entries ( localeConfig ! ) ) {
140- const localized = localePath === true ? path : localePath
141- invertedMap [ resPath ] [ locale ] = localized && resolveRoutePath ( localized )
142- if ( invertedMap [ resPath ] [ locale ] ) {
143- localizedMapInvert [ invertedMap [ resPath ] [ locale ] ] = resPath
144- hasLocalized = true
145- }
146- }
147- if ( ! hasLocalized ) {
148- notLocalizedMapInvert [ resPath ] = resPath
149- }
150- }
151- routeResources . i18nPathToPath = localizedMapInvert
152- routeResources . pathToI18nConfig = invertedMap
153- routeResources . disabledI18nPathToPath = notLocalizedMapInvert
128+ routeResources = resources . toResources ( )
154129
155130 await updateTemplates ( {
156131 filter : ( template : ResolvedNuxtTemplate ) => template . filename === 'i18n-route-resources.mjs' ,
@@ -388,49 +363,6 @@ export function createPureOptionsResolver(
388363 }
389364}
390365
391- /**
392- * Post-processing step: builds ctx.pathToConfig from the original (pre-localized) routes.
393- * Call this after localizeRoutes() with the same resolver used for localization.
394- */
395- export function buildPathToConfig (
396- ctx : NuxtPageAnalyzeContext ,
397- localeCodes : string [ ] ,
398- resolver : RouteOptionsResolver ,
399- routes : LocalizableRoute [ ] ,
400- ) : void {
401- for ( const route of routes ) {
402- if ( route . file ) {
403- const res = resolver ( route , localeCodes )
404- const localeCfg = res ?. srcPaths
405- const mappedPath = ctx . fileToPath [ route . file ]
406- if ( mappedPath ) {
407- ctx . pathToConfig [ mappedPath ] ??= { } as Record < string , string | boolean >
408- for ( const l of localeCodes ) {
409- ctx . pathToConfig [ mappedPath ] [ l ] ??= localeCfg ?. [ l ] ?? false
410- }
411- for ( const l of res ?. locales ?? [ ] ) {
412- ctx . pathToConfig [ mappedPath ] [ l ] ||= true
413- }
414- }
415- }
416- if ( route . children ?. length ) {
417- buildPathToConfig ( ctx , localeCodes , resolver , route . children )
418- }
419- }
420- }
421-
422- /**
423- * Function factory, returns a function based on the `customRoutes` option property.
424- * @deprecated Use createPureOptionsResolver + buildPathToConfig instead.
425- */
426- export function getRouteOptionsResolver (
427- ctx : NuxtPageAnalyzeContext ,
428- defaultLocale : string ,
429- customRoutes : NuxtI18nOptions [ 'customRoutes' ] ,
430- ) : RouteOptionsResolver {
431- return createPureOptionsResolver ( ctx , defaultLocale , customRoutes )
432- }
433-
434366function resolveRoutePath ( path : string ) : string {
435367 const tokens = parseSegment ( path . slice ( 1 ) )
436368 return '/' + toVueRouterSegment ( tokens )
@@ -592,7 +524,7 @@ function getRouteOptions(
592524 }
593525 }
594526
595- return { locales, paths, srcPaths : resolvedOptions . paths }
527+ return { locales, paths }
596528}
597529
598530/**
0 commit comments