Skip to content

Commit 7a49460

Browse files
committedOct 16, 2024·
fix(nuxt-i18n-micro): broken route generation
Fixes #367
1 parent a0a3063 commit 7a49460

File tree

3 files changed

+98
-7
lines changed

3 files changed

+98
-7
lines changed
 

‎src/module.ts

+1
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ declare module 'vue-router' {
608608
include: normalizeFilters(config.include),
609609
exclude: normalizeFilters(config.exclude),
610610
},
611+
isI18nMicro: i18nModule === 'nuxt-i18n-micro',
611612
})
612613
if (!pageSource.length) {
613614
pageSource.push(nuxt.options.app.baseURL || '/')

‎src/util/nuxtSitemap.ts

+35-7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface NuxtPagesToSitemapEntriesOptions {
3434
defaultLocale: string
3535
strategy: 'no_prefix' | 'prefix_except_default' | 'prefix' | 'prefix_and_default'
3636
isI18nMapped: boolean
37+
isI18nMicro: boolean
3738
filter: CreateFilterOptions
3839
}
3940

@@ -46,18 +47,41 @@ interface PageEntry extends SitemapUrl {
4647
function deepForEachPage(
4748
pages: NuxtPage[],
4849
callback: (page: NuxtPage, fullpath: string, depth: number) => void,
50+
opts: NuxtPagesToSitemapEntriesOptions,
4951
fullpath: string | undefined | null = null,
5052
depth: number = 0,
5153
) {
52-
pages.forEach((page: NuxtPage) => {
53-
let currentPath: string | null
54-
if (page.path.startsWith('/'))
54+
pages.forEach((page) => {
55+
let currentPath
56+
if (page.path.startsWith('/')) {
5557
currentPath = page.path
56-
else
58+
}
59+
else {
5760
currentPath = page.path === '' ? fullpath : `${fullpath!.replace(/\/$/, '')}/${page.path}`
58-
callback(page, currentPath || '', depth)
59-
if (page.children)
60-
deepForEachPage(page.children, callback, currentPath, depth + 1)
61+
}
62+
63+
let didCallback = false
64+
if (opts.isI18nMicro) {
65+
const localePattern = /\/:locale\(([^)]+)\)/
66+
const match = localePattern.exec(currentPath || '')
67+
if (match) {
68+
const locales = match[1].split('|')
69+
locales.forEach((locale) => {
70+
const subPage = { ...page }
71+
const localizedPath = (currentPath || '').replace(localePattern, `/${locale}`)
72+
subPage.name += opts.routesNameSeparator + locale
73+
subPage.path = localizedPath
74+
callback(subPage, localizedPath || '', depth)
75+
didCallback = true
76+
})
77+
}
78+
}
79+
if (!didCallback) {
80+
callback(page, currentPath || '', depth)
81+
}
82+
if (page.children) {
83+
deepForEachPage(page.children, callback, opts, currentPath, depth + 1)
84+
}
6185
})
6286
}
6387

@@ -70,6 +94,10 @@ export function convertNuxtPagesToSitemapEntries(pages: NuxtPage[], config: Nuxt
7094
(page, loc, depth) => {
7195
flattenedPages.push({ page, loc, depth })
7296
},
97+
{
98+
...config,
99+
routesNameSeparator: config.routesNameSeparator || '___',
100+
},
73101
)
74102
flattenedPages = flattenedPages
75103
// Removing dynamic routes

‎test/unit/parsePages.test.ts

+62
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,16 @@ const payload: NuxtPage[] = [
194194
describe('page parser', () => {
195195
it('is parsed', () => {
196196
expect(convertNuxtPagesToSitemapEntries(payload, {
197+
filter: {
198+
include: [],
199+
exclude: [],
200+
},
197201
isI18nMapped: true,
198202
autoLastmod: false,
199203
defaultLocale: 'en',
200204
normalisedLocales: normalizeLocales({ locales: [{ code: 'en' }, { code: 'fr' }] }),
201205
strategy: 'no_prefix',
206+
isI18nMicro: false,
202207
})).toMatchInlineSnapshot(`
203208
[
204209
{
@@ -637,4 +642,61 @@ describe('page parser', () => {
637642
]
638643
`)
639644
})
645+
646+
it ('i18n micro', () => {
647+
expect(convertNuxtPagesToSitemapEntries([
648+
{
649+
name: 'index',
650+
path: '/:locale(de|ja)/page',
651+
file: 'playground/pages/index.vue',
652+
children: [],
653+
},
654+
], {
655+
filter: {
656+
include: [],
657+
exclude: [],
658+
},
659+
isI18nMapped: true,
660+
autoLastmod: false,
661+
defaultLocale: 'en',
662+
normalisedLocales: normalizeLocales({ locales: [
663+
{ code: 'en', iso: 'en_EN' },
664+
{ code: 'de', iso: 'de_DE' },
665+
{ code: 'ru', iso: 'ru_RU' },
666+
] }),
667+
strategy: 'prefix_except_default',
668+
isI18nMicro: true,
669+
})).toMatchInlineSnapshot(`
670+
[
671+
{
672+
"_sitemap": "de_DE",
673+
"alternatives": [
674+
{
675+
"href": "/de/page",
676+
"hreflang": "de_DE",
677+
},
678+
{
679+
"href": "/ja/page",
680+
"hreflang": undefined,
681+
},
682+
],
683+
"loc": "/de/page",
684+
},
685+
{
686+
"_sitemap": "index",
687+
"alternatives": [
688+
{
689+
"href": "/de/page",
690+
"hreflang": "de_DE",
691+
},
692+
{
693+
"href": "/ja/page",
694+
"hreflang": undefined,
695+
},
696+
],
697+
"loc": "/ja/page",
698+
},
699+
]
700+
`)
701+
})
640702
})

0 commit comments

Comments
 (0)
Please sign in to comment.