diff --git a/frontend/src/app.vue b/frontend/src/app.vue index 169fb113aa7..c635c845073 100644 --- a/frontend/src/app.vue +++ b/frontend/src/app.vue @@ -15,6 +15,7 @@ import { useLayout } from "~/composables/use-layout" import { useDarkMode } from "~/composables/use-dark-mode" import VSkipToContentButton from "~/components/VSkipToContentButton.vue" +import LanguageRedirectBanner from '~/components/LanguageRedirectBanner.vue' const config = useRuntimeConfig() @@ -85,6 +86,7 @@ onMounted(() => {
+ diff --git a/frontend/src/components/LanguageRedirectBanner.vue b/frontend/src/components/LanguageRedirectBanner.vue new file mode 100755 index 00000000000..389d74883cb --- /dev/null +++ b/frontend/src/components/LanguageRedirectBanner.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/frontend/src/middleware/language-redirect.global.ts b/frontend/src/middleware/language-redirect.global.ts new file mode 100755 index 00000000000..286e3e13301 --- /dev/null +++ b/frontend/src/middleware/language-redirect.global.ts @@ -0,0 +1,30 @@ +import { + defineNuxtRouteMiddleware, + navigateTo, + useCookie, + useNuxtApp, +} from '#app' + +export default defineNuxtRouteMiddleware((to) => { + const { $i18n } = useNuxtApp() + const availableLocales = $i18n.availableLocales as string[] + + const segments = to.path.split('/').filter(Boolean) + if (!segments.length) return + + const locale = segments[0] + + // Only act on two-letter language codes + if (locale.length !== 2) return + + // Supported locale → do nothing + if (availableLocales.includes(locale)) return + + // Store unsupported locale to show banner + const bannerCookie = useCookie('unsupported_language_code') + bannerCookie.value = locale + + // Redirect to English path (strip the locale) + const newPath = '/' + segments.slice(1).join('/') + return navigateTo(newPath || '/', { redirectCode: 302 }) +})