diff --git a/src/module.ts b/src/module.ts index 44fbcc0..2b8f2cb 100644 --- a/src/module.ts +++ b/src/module.ts @@ -608,6 +608,7 @@ declare module 'vue-router' { include: normalizeFilters(config.include), exclude: normalizeFilters(config.exclude), }, + isI18nMicro: i18nModule === 'nuxt-i18n-micro', }) if (!pageSource.length) { pageSource.push(nuxt.options.app.baseURL || '/') diff --git a/src/util/nuxtSitemap.ts b/src/util/nuxtSitemap.ts index f0fb56a..dab01a6 100644 --- a/src/util/nuxtSitemap.ts +++ b/src/util/nuxtSitemap.ts @@ -34,6 +34,7 @@ export interface NuxtPagesToSitemapEntriesOptions { defaultLocale: string strategy: 'no_prefix' | 'prefix_except_default' | 'prefix' | 'prefix_and_default' isI18nMapped: boolean + isI18nMicro: boolean filter: CreateFilterOptions } @@ -46,18 +47,41 @@ interface PageEntry extends SitemapUrl { function deepForEachPage( pages: NuxtPage[], callback: (page: NuxtPage, fullpath: string, depth: number) => void, + opts: NuxtPagesToSitemapEntriesOptions, fullpath: string | undefined | null = null, depth: number = 0, ) { - pages.forEach((page: NuxtPage) => { - let currentPath: string | null - if (page.path.startsWith('/')) + pages.forEach((page) => { + let currentPath + if (page.path.startsWith('/')) { currentPath = page.path - else + } + else { currentPath = page.path === '' ? fullpath : `${fullpath!.replace(/\/$/, '')}/${page.path}` - callback(page, currentPath || '', depth) - if (page.children) - deepForEachPage(page.children, callback, currentPath, depth + 1) + } + + let didCallback = false + if (opts.isI18nMicro) { + const localePattern = /\/:locale\(([^)]+)\)/ + const match = localePattern.exec(currentPath || '') + if (match) { + const locales = match[1].split('|') + locales.forEach((locale) => { + const subPage = { ...page } + const localizedPath = (currentPath || '').replace(localePattern, `/${locale}`) + subPage.name += opts.routesNameSeparator + locale + subPage.path = localizedPath + callback(subPage, localizedPath || '', depth) + didCallback = true + }) + } + } + if (!didCallback) { + callback(page, currentPath || '', depth) + } + if (page.children) { + deepForEachPage(page.children, callback, opts, currentPath, depth + 1) + } }) } @@ -70,6 +94,10 @@ export function convertNuxtPagesToSitemapEntries(pages: NuxtPage[], config: Nuxt (page, loc, depth) => { flattenedPages.push({ page, loc, depth }) }, + { + ...config, + routesNameSeparator: config.routesNameSeparator || '___', + }, ) flattenedPages = flattenedPages // Removing dynamic routes diff --git a/test/unit/parsePages.test.ts b/test/unit/parsePages.test.ts index 6adefc4..10985db 100644 --- a/test/unit/parsePages.test.ts +++ b/test/unit/parsePages.test.ts @@ -194,11 +194,16 @@ const payload: NuxtPage[] = [ describe('page parser', () => { it('is parsed', () => { expect(convertNuxtPagesToSitemapEntries(payload, { + filter: { + include: [], + exclude: [], + }, isI18nMapped: true, autoLastmod: false, defaultLocale: 'en', normalisedLocales: normalizeLocales({ locales: [{ code: 'en' }, { code: 'fr' }] }), strategy: 'no_prefix', + isI18nMicro: false, })).toMatchInlineSnapshot(` [ { @@ -637,4 +642,61 @@ describe('page parser', () => { ] `) }) + + it ('i18n micro', () => { + expect(convertNuxtPagesToSitemapEntries([ + { + name: 'index', + path: '/:locale(de|ja)/page', + file: 'playground/pages/index.vue', + children: [], + }, + ], { + filter: { + include: [], + exclude: [], + }, + isI18nMapped: true, + autoLastmod: false, + defaultLocale: 'en', + normalisedLocales: normalizeLocales({ locales: [ + { code: 'en', iso: 'en_EN' }, + { code: 'de', iso: 'de_DE' }, + { code: 'ru', iso: 'ru_RU' }, + ] }), + strategy: 'prefix_except_default', + isI18nMicro: true, + })).toMatchInlineSnapshot(` + [ + { + "_sitemap": "de_DE", + "alternatives": [ + { + "href": "/de/page", + "hreflang": "de_DE", + }, + { + "href": "/ja/page", + "hreflang": undefined, + }, + ], + "loc": "/de/page", + }, + { + "_sitemap": "index", + "alternatives": [ + { + "href": "/de/page", + "hreflang": "de_DE", + }, + { + "href": "/ja/page", + "hreflang": undefined, + }, + ], + "loc": "/ja/page", + }, + ] + `) + }) })