From b310be901efa0a3013bfb47fb4d27e10799cfb3f Mon Sep 17 00:00:00 2001 From: Togetic <31132515+Togetic@users.noreply.github.com> Date: Sun, 28 Jun 2026 11:45:52 +0200 Subject: [PATCH] fix(compactRoutes): key NuxtPage by interpolated pattern, not full path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With `experimental.compactRoutes`, the route-locale-detect plugin set `meta.key` to the full resolved path, so the `` key changed on every child navigation and Vue remounted the whole nested subtree — parent state was lost and `onBeforeMount`/`onBeforeUnmount` re-fired — on non-default locales only (the default-locale tree isn't compact, so Nuxt's stable interpolated key was used there). Key by the record's own interpolated pattern instead, matching Nuxt's default `` keying. Nested parents now stay mounted across child navigation and still remount when the locale param actually changes (e.g. `/de/x` -> `/fr/x`), preserving the original intent from #3957. Fixes #4001 --- src/runtime/plugins/route-locale-detect.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/runtime/plugins/route-locale-detect.ts b/src/runtime/plugins/route-locale-detect.ts index b8cd85ee6..4d9c219fd 100644 --- a/src/runtime/plugins/route-locale-detect.ts +++ b/src/runtime/plugins/route-locale-detect.ts @@ -16,7 +16,12 @@ export default defineNuxtPlugin({ const router = useRouter() for (const route of router.getRoutes()) { if (route.meta?.__i18nCompact && route.meta.key == null) { - route.meta.key = (r: { path: string }) => r.path + // Key by the record's own interpolated pattern (mirrors Nuxt's default `` + // keying) instead of the full resolved path, so nested parent pages stay mounted + // across child navigation and only remount when the locale param actually changes. + const pattern = route.path.replace(/(:\w+)\([^)]+\)/g, '$1').replace(/(:\w+)[?+*]/g, '$1') + route.meta.key = (r: { params: Record }) => + pattern.replace(/:\w+/g, m => r.params[m.slice(1)]?.toString() || '') } } }