\n\n### Additional context\n\n_No response_\n\n### Logs\n\n```shell\n\n```",[3239],{"name":3173,"color":3174},3792,"`switchLocalePath` returns an empty string","2025-08-21T22:49:06Z","https://github.com/nuxt-modules/i18n/issues/3792",0.6716237,{"description":3246,"labels":3247,"number":3255,"owner":3176,"repository":3177,"state":3220,"title":3256,"updated_at":3257,"url":3258,"score":3259},"### Environment\n\n\"@nuxtjs/i18n\": \"^8.0.0-beta.10\",\n\n### Reproduction\n\nI have the following pages:\r\n- `terms.vue`\r\n- `terms-fi.vue`\r\n\r\nand my `nuxt.config.ts` has the following:\r\n```\r\n customRoutes: 'config', // disable custom route with page components\r\n pages: {\r\n terms: {\r\n fi: '/terms-fi',\r\n },\r\n },\r\n```\r\nIt works correctly when going from Finnish to English. Though when I am at `/fi/terms-fi` (the Finnish page) and I switch to english with `switchLocalePath` the routes becomes `terms-fi` and it should just be `terms`\n\n### Describe the bug\n\nError in the route when switching language if custom pages are defined.\n\n### Additional context\n\n_No response_\n\n### Logs\n\n_No response_",[3248,3251,3252],{"name":3249,"color":3250},"🍰 p2-nice-to-have","0e8a16",{"name":3217,"color":3218},{"name":3253,"color":3254},"PR Welcome","40922A",2033,"Custom routes issue with switchLocalePath","2025-05-22T23:35:14Z","https://github.com/nuxt-modules/i18n/issues/2033",0.67544156,{"description":3261,"labels":3262,"number":3264,"owner":3176,"repository":3177,"state":3220,"title":3265,"updated_at":3266,"url":3267,"score":3268},"### Environment\n\n- Operating System: Darwin\n- Node Version: v22.16.0\n- Nuxt Version: 3.17.7\n- CLI Version: 3.26.2\n- Nitro Version: 2.12.2\n- Package Manager: pnpm@10.13.1\n- Builder: -\n- User Config: compatibilityDate, future, devtools, telemetry, debug, runtimeConfig, app, css, postcss, tailwindcss, modules, cms, build, storefront, storefront-ui, svgo, fonts, image, experimental, i18n, opentelemetry, imports, vueuse, components, vue, devServer, ignore, routeRules, vite, hooks, nitro, optimization\n- Runtime Modules: @nuxtjs/i18n@10.0.0, @scayle/storefront-nuxt/module@8.33.2, @scayle/omnichannel-nuxt/module@4.3.2, @nuxtjs/tailwindcss@6.14.0, nuxt-svgo@4.2.4, @nuxt/fonts@0.11.4, @nuxt/image@1.10.0, @vueuse/nuxt@13.5.0, nuxt-swiper@1.2.2, @nuxt/test-utils/module@3.19.2, @nuxt/eslint@1.4.1, @scayle/eslint-auto-explicit-import@0.2.0, @scayle/nuxt-opentelemetry@0.13.10, @scayle/storefront-country-detection@2.0.0, @scayle/storefront-product-detail@1.5.0, @scayle/storefront-product-listing@2.0.1, @scayle/storefront-promotions@2.2.0, @scayle/storefront-search@0.3.0, @scayle/storefront-basket@0.3.0, @scayle/storefront-navigation@0.3.0, @scayle/nuxt-image-provider@0.3.1, @nuxtjs/storybook@8.4.1\n- Build Modules: -\n\n### Reproduction\n\nhttps://stackblitz.com/edit/bobbiegoede-nuxt-i18n-starter-a8x1bxda?file=i18n%2Fi18n.config.ts\n\n### Describe the bug\n\nI use a module that relies on the correct locale during SSR. When I set the strategy to `prefix` and open some site without prefix but with query params, the default locale is missing during SSR. \n\nIn my case, this cause the page to crash. \n\n### Additional context\n\n_No response_\n\n### Logs\n\n```shell\n\n```",[3263],{"name":3173,"color":3174},3733,"Redirects are not properly resolved when the URL contians query params","2025-07-19T09:16:15Z","https://github.com/nuxt-modules/i18n/issues/3733",0.6877239,{"description":3270,"labels":3271,"number":3276,"owner":3176,"repository":3177,"state":3220,"title":3277,"updated_at":3278,"url":3279,"score":3280},"### Environment\n\n``` \n- Operating System: Darwin\n- Node Version: v22.16.0\n- Nuxt Version: 4.0.3\n- CLI Version: 3.28.0\n- Nitro Version: 2.12.4\n- Package Manager: npm@10.9.2\n- Builder: -\n- User Config: compatibilityDate, devtools, modules, css, vite, routeRules, i18n, sanctum, runtimeConfig, uiPro\n- Runtime Modules: @nuxt/eslint@1.8.0, @nuxt/image@1.11.0, @nuxt/scripts@0.11.10, @nuxt/ui-pro@3.3.2, @nuxtjs/i18n@10.0.5, nuxt-auth-sanctum@1.1.2, dayjs-nuxt@2.1.11\n- Build Modules: -\n```\n\n### Reproduction\n\n1. Create translation files in the default location:\n```\ni18n/locales/es.ts\ni18n/locales/en.ts\n```\n\n2. Configure nuxt.config.ts:\n```ts\nrouteRules: {\n \"/\": { prerender: true },\n \"/en\": { prerender: true },\n...\n// We have prerender y routes, because are landings and astatic\n},\n i18n: {\n defaultLocale: \"es\",\n strategy: \"prefix_except_default\",\n baseUrl: process.env.NUXT_PUBLIC_FRONTEND_URL,\n locales: [\n { code: \"en\", name: \"English\", file: \"en.ts\", language: \"en\" },\n { code: \"es\", name: \"Español\", file: \"es.ts\", language: \"es\" },\n ],\n}\n```\n\n3. layouts/default.vue\n```vue\n\u003Cscript lang=\"ts\" setup>\nconst i18nHead = useLocaleHead({\n dir: true,\n seo: true,\n});\nconst { t } = useI18n();\nconst route = useRoute();\nconst config = useRuntimeConfig();\nconst { locale } = useI18n();\nconst title = computed(() =>\n t((route.meta.title as string) ?? \"layout.default.title\", {\n appName: config.public.appName,\n })\n);\ntype Meta = {\n property?: string;\n content: string;\n name?: string;\n};\nconst metaTags = computed\u003CMeta[]>(() => {\n const description = t(\n (route.meta.description as string) ?? \"layout.default.description\"\n );\n\n return [\n ...(i18nHead.value.meta || []),\n {\n name: \"description\",\n content: description,\n },\n {\n property: \"og:title\",\n content: title.value,\n },\n {\n property: \"og:description\",\n content: description,\n },\n {\n property: \"og:image\",\n content: `/media/common/${locale.value}/og.webp`,\n },\n {\n property: \"og:url\",\n content: `${config.public.frontendUrl}${route.fullPath}`,\n },\n {\n property: \"og:locale\",\n content: i18nHead.value.htmlAttrs.lang,\n },\n {\n property: \"og:site_name\",\n content: config.public.appName as string,\n },\n {\n property: \"og:type\",\n content: \"website\",\n },\n {\n name: \"twitter:card\",\n content: \"summary_large_image\",\n },\n {\n name: \"twitter:title\",\n content: title.value,\n },\n {\n name: \"twitter:description\",\n content: description,\n },\n {\n name: \"twitter:image\",\n content: `/media/common/${locale.value}/og.webp`,\n },\n {\n name: \"robots\",\n // Only if we are in production\n content:\n config.public.vercelEnv == \"production\"\n ? \"index, follow\"\n : \"noindex, nofollow\",\n },\n ] as Meta[];\n});\n\nconst links = computed(() => [\n ...(i18nHead.value.link || []),\n { rel: \"icon\", type: \"image/x-icon\", href: \"/favicon.ico\" },\n]);\n\u003C/script>\n\n\u003Ctemplate>\n \u003CHtml :lang=\"i18nHead.htmlAttrs.lang\" :dir=\"i18nHead.htmlAttrs.dir\">\n \u003CHead>\n \u003CTitle>{{ title }}\u003C/Title>\n \u003Ctemplate v-for=\"link in links\" :key=\"link.id\">\n \u003CLink\n :id=\"link.id\"\n :rel=\"link.rel\"\n :href=\"link.href\"\n :hreflang=\"link.hreflang\"\n />\n \u003C/template>\n \u003Ctemplate v-for=\"meta in metaTags\" :key=\"meta.id\">\n \u003CMeta\n :property=\"meta.property\"\n :content=\"meta.content\"\n :name=\"meta.name\"\n />\n \u003C/template>\n \u003C/Head>\n \u003CBody>\n \u003CAppHeader />\n \u003Cslot />\n \u003CAppFooter />\n \u003C/Body>\n \u003C/Html>\n\u003C/template>\n\n\u003Cstyle>\u003C/style>\n```\n\n4. Some page\n```vue\ndefinePageMeta({\n layout: \"default\",\n title: \"essay.meta.title\",\n description: \"essay.meta.description\",\n});\n```\n\n5. Example of translation file:\n```\nexport default {\n appHeader: {\n tools: \"Herramientas\",\n summary: {\n title: \"Resumidor\",\n description: \"Resume textos de forma automática.\",\n },\n....\n```\n\n\n\n### Describe the bug\n\nWhen using the current Nuxt i18n setup (translations inside i18n/locales/es.ts, i18n/locales/en.ts, etc.), translation keys appear in the \u003Chead> instead of resolved translations.\n\nFor example, Google is indexing essay.meta.title instead of the translated string because the SSR HTML is rendered before locale messages are available. The client later fetches /_i18n/es/messages.json, but if that request fails or is delayed, the \u003Ctitle> and \u003Cmeta> remain as raw keys. This is problematic for SEO since crawlers usually index the raw SSR HTML.\n\nWhen inspect with search console:\n\u003Cimg width=\"399\" height=\"76\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9b9fcc11-0244-4eab-a624-1e60ac29d6e3\" />\n\u003Cimg width=\"400\" height=\"223\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/3f70c9a6-ec7e-4a20-9ec1-16dc62958297\" />\nIn google SERP\n\u003Cimg width=\"705\" height=\"151\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/ea3e3b89-9bcf-421d-96cc-5987aff8a64c\" />\n\n### Additional context\n\n#### Documentation issues\n\nIn older versions there was a lazy: true/false option. This no longer exists, but the migration path is unclear.\n\nIt’s not documented whether .ts files (with export default {}) behave the same as .json for SSR vs client-only loading.\n\nThe docs show how to use file/files, but don’t explain how to guarantee SSR has messages ready for SEO-critical content like \u003Chead>.\n\nRight now it’s unclear if the messages are truly lazy-loaded, or if something else prevents them from being available at SSR.\n\n### Logs\n\n```shell\n\n```",[3272,3273],{"name":3173,"color":3174},{"name":3274,"color":3275},"need reproduction","CD234A",3794,"SEO issue with SSR translations and unclear lazy-loading behavior","2025-10-07T14:52:13Z","https://github.com/nuxt-modules/i18n/issues/3794",0.6953133,["Reactive",3282],{},["Set"],["ShallowReactive",3285],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fOhFsuyyxCWAHOlAWnOXCHEo6zoxg1lhRqm34JBRB5Tw":-1},"/nuxt-modules/i18n/3702"]