@koehler8/cms 1.0.0-beta.23 β 1.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Header.vue +10 -2
- package/src/router/index.js +24 -0
package/package.json
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
<li v-for="locale in availableLocales" :key="locale">
|
|
98
98
|
<a
|
|
99
99
|
class="locale-option"
|
|
100
|
-
:href="
|
|
100
|
+
:href="localeHref(locale)"
|
|
101
101
|
@click="handleLocaleLinkClick(locale)"
|
|
102
102
|
>
|
|
103
103
|
<span class="locale-flag" aria-hidden="true">{{ localeEmojis[locale] || 'π' }}</span>
|
|
@@ -120,7 +120,7 @@ import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref, useSlots,
|
|
|
120
120
|
import { resolveAsset } from '../utils/assetResolver.js';
|
|
121
121
|
import { trackEvent } from '../utils/analytics.js';
|
|
122
122
|
import { getExtensionComponent } from '../extensions/extensionLoader.js';
|
|
123
|
-
import { availableLocales as siteLocales } from '../utils/loadConfig.js';
|
|
123
|
+
import { availableLocales as siteLocales, baseLocale as siteBaseLocale } from '../utils/loadConfig.js';
|
|
124
124
|
|
|
125
125
|
const slots = useSlots();
|
|
126
126
|
const hasActionsSlot = computed(() => Boolean(slots.actions));
|
|
@@ -129,6 +129,14 @@ const isLangOpen = ref(false);
|
|
|
129
129
|
const isHeaderCompact = ref(false);
|
|
130
130
|
const currentLocale = ref('');
|
|
131
131
|
const availableLocales = computed(() => siteLocales.map((code) => code.trim()).filter(Boolean));
|
|
132
|
+
|
|
133
|
+
// The base locale is served at the unprefixed root path (`/`) β clicking
|
|
134
|
+
// the dropdown item for it should NOT navigate to `/{baseLocale}` because
|
|
135
|
+
// that URL doesn't pre-render and would 404. Build the link path
|
|
136
|
+
// accordingly: base β `/`, others β `/{locale}`.
|
|
137
|
+
const localeHref = (locale) => {
|
|
138
|
+
return locale === siteBaseLocale ? '/' : `/${locale}`;
|
|
139
|
+
};
|
|
132
140
|
const localeLabels = {
|
|
133
141
|
en: 'English',
|
|
134
142
|
fr: 'FranΓ§ais',
|
package/src/router/index.js
CHANGED
|
@@ -5,6 +5,19 @@ import Home from '../components/Home.vue';
|
|
|
5
5
|
|
|
6
6
|
import { availableLocales, baseLocale } from '../utils/loadConfig.js';
|
|
7
7
|
|
|
8
|
+
// Test for `/{baseLocale}` or `/{baseLocale}/...` paths β these no longer
|
|
9
|
+
// pre-render or match the locale layout (the canonical URL for the base
|
|
10
|
+
// locale is unprefixed). Used by the router guard to redirect in-SPA
|
|
11
|
+
// navigation so external clicks land on the canonical URL instead of the
|
|
12
|
+
// SPA catch-all β 404 path.
|
|
13
|
+
function stripBaseLocalePrefix(targetPath, base) {
|
|
14
|
+
if (!base || !targetPath) return null;
|
|
15
|
+
const root = `/${base}`;
|
|
16
|
+
if (targetPath === root) return '/';
|
|
17
|
+
if (targetPath.startsWith(`${root}/`)) return targetPath.slice(root.length) || '/';
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
const LocaleLayout = {
|
|
9
22
|
name: 'LocaleLayout',
|
|
10
23
|
render() {
|
|
@@ -85,6 +98,17 @@ function normalizeLocale(value = '') {
|
|
|
85
98
|
|
|
86
99
|
export function applyRouterGuards(router, localePrefixes = computeLocalePrefixes()) {
|
|
87
100
|
router.beforeEach((to) => {
|
|
101
|
+
// SPA-side redirect for stale base-locale-prefixed URLs. When a user
|
|
102
|
+
// navigates inside the app to `/en/about` (and `en` is base), the URL
|
|
103
|
+
// doesn't pre-render and the catch-all renders the 404 page. Rewrite
|
|
104
|
+
// to the canonical unprefixed equivalent. Direct external hits to
|
|
105
|
+
// these URLs still need an Amplify customRule on the host side β see
|
|
106
|
+
// CLAUDE.md "URL hygiene".
|
|
107
|
+
const stripped = stripBaseLocalePrefix(to.path, baseLocale);
|
|
108
|
+
if (stripped !== null && stripped !== to.path) {
|
|
109
|
+
return { path: stripped, replace: true };
|
|
110
|
+
}
|
|
111
|
+
|
|
88
112
|
const rawLocale = (to.params.locale || '').toString().trim();
|
|
89
113
|
|
|
90
114
|
if (rawLocale) {
|