` and `og:property`. \r\n\r\n```html\r\n\u003Clink id=\"i18n-alt-it\" rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-it\" hreflang=\"it\">\r\n\u003Clink id=\"i18n-alt-de\" rel=\"alternate\" href=\"https://www.dummy.com/de/blog-1-de\" hreflang=\"de\">\r\n\u003Clink id=\"i18n-xd\" rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-it\" hreflang=\"x-default\">\r\n\u003Clink id=\"i18n-can\" rel=\"canonical\" href=\"https://www.dummy.com/it/blog-1-ita\">\r\n\u003Cmeta id=\"i18n-og-url\" property=\"og:url\" content=\"https://www.dummy.com/it/blog-1-ita\">\r\n\u003Cmeta id=\"i18n-og\" property=\"og:locale\" content=\"it\">\r\n\u003Cmeta id=\"i18n-og-alt-en\" property=\"og:locale:alternate\" content=\"en\">\r\n\u003Cmeta id=\"i18n-og-alt-de\" property=\"og:locale:alternate\" content=\"de\">\r\n```\n\n### Additional context\n\nWow, that's good, but why only whit `setI18nParams` and not in the othter pages? If i don't use `setI18nParams` i have to set all this code on `App.vue`\r\n```js\r\nconst localeHead = useLocaleHead({\r\n addSeoAttributes: true,\r\n addDirAttribute: true,\r\n})\r\n\r\nuseHead({\r\n htmlAttrs: () => localeHead.value.htmlAttrs ?? {},\r\n link: () => localeHead.value.link ?? [],\r\n meta: () => localeHead.value.meta ?? []\r\n})\r\n```\r\n\r\nSo either everything is handled automatically or everything is handled via the mix of `useLocaleHead` and `useHead`\n\n### Logs\n\n_No response_",[3240,3243],{"name":3241,"color":3242},"🍰 p2-nice-to-have","0e8a16",{"name":3244,"color":3245},"scope: seo","30CDE0",2780,"closed","`setI18nParams` automatically adds `\u003Clink rel=\"alternate\" />`","2025-05-25T10:23:03Z","https://github.com/nuxt-modules/i18n/issues/2780",0.6425828,{"description":3253,"labels":3254,"number":3258,"owner":3178,"repository":3179,"state":3247,"title":3259,"updated_at":3260,"url":3261,"score":3262},"### Describe the feature\n\n# Description\n\nCurrently, the `useLocaleHead` composable in the `nuxt3-i18n` module automatically generates various meta tags, including `og:url`, based on non-configurable logic. While this works for many use cases, it creates challenges when custom logic is required.\n\n## Use Case\n\nIn our project, we manually determine the `og:url` using project-specific logic. We set this custom `og:url` using the [useSeoMeta](https://nuxt.com/docs/api/composables/use-seo-meta) method. However, when using `useLocaleHead` with default properties, it adds a second `og:url` meta tag, which cannot be disabled or customized without affecting other tags.\n\nSetting `seo: false` in `useLocaleHead` disables all SEO-related meta tags, including `og:locale:alternate` tags and `og:locale` for the current page. This is problematic because we only want to disable the automatic generation of `og:url`, while retaining the other meta tags provided by `useLocaleHead`.\n\nThe relevant behavior can be seen in the following code snippet: \n\nhttps://github.com/nuxt-modules/i18n/blob/d239bdd3db8c9790e6d11dd3848213674c4590a3/src/runtime/routing/compatibles/head.ts#L63-L72\n\n## PR\n\nI’d be happy to contribute a pull request (PR) to implement this feature if the idea is welcomed.\n\n### Additional information\n\n- [x] Would you be willing to help implement this feature?\n- [ ] Could this feature be implemented as a module?\n\n### Final checks\n\n- [x] Read the [contribution guide](https://nuxt.com/docs/community/contribution) (The contribution guideline of nuxt-modules/i18n is compliant with Nuxt too).\n- [x] Check existing [discussions](https://github.com/nuxt-modules/i18n/discussions) and [issues](https://github.com/nuxt/nuxt/issues).",[3255,3256,3257],{"name":3175,"color":3176},{"name":3201,"color":3202},{"name":3244,"color":3245},3277,"Feature Request: Add fine-grained control for `og:url` and other Open Graph meta tags in `useLocaleHead`","2025-06-08T01:44:39Z","https://github.com/nuxt-modules/i18n/issues/3277",0.66632825,{"description":3264,"labels":3265,"number":3268,"owner":3178,"repository":3179,"state":3247,"title":3269,"updated_at":3270,"url":3271,"score":3272},"### 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```",[3266,3267],{"name":3189,"color":3190},{"name":3201,"color":3202},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.6665428,{"description":3274,"labels":3275,"number":3278,"owner":3178,"repository":3179,"state":3247,"title":3279,"updated_at":3280,"url":3281,"score":3282},"### Environment\r\n\r\n------------------------------\r\n- Operating System: Darwin\r\n- Node Version: v20.11.0\r\n- Nuxt Version: 3.10.1\r\n- CLI Version: 3.10.0\r\n- Nitro Version: 2.8.1\r\n- Package Manager: yarn@4.0.1\r\n- Builder: -\r\n- User Config: modules, i18n, devtools\r\n- Runtime Modules: @nuxtjs/i18n@8.1.0\r\n- Build Modules: -\r\n------------------------------\r\n\r\n\r\n### Reproduction\r\n\r\nhttps://stackblitz.com/edit/github-c7te5q-rzxba2\r\n\r\n### Describe the bug\r\n\r\n`useLocaleHead` doesn't work with `useSetI18nParams` because `\u003Clink rel=\"alternate\" />` aren't sync. \r\n\r\n### Additional context\r\n\r\nif i go from Homepage `/it` to the blog page `/it/blog-1-ita` using the **Go at Blog Page** button, the alternate links don't change; but i've set all the i18nParams\r\n```js\r\nsetI18nParams({\r\n it: { blog: 'blog-1-it' },\r\n de: { blog: 'blog-1-de' },\r\n en: false,\r\n})\r\n```\r\n\r\nIf i refresh the page when i'm in the blog page, the `\u003Clink rel=\"alternate\" />` are duplicated (and also `canonical`).\r\n```html\r\n\u003Clink rel=\"alternate\" href=\"https://www.dummy.com/en/blog-1-ita\" hreflang=\"en\" data-hid=\"7fcee50\">\r\n\u003Clink rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-ita\" hreflang=\"it\" data-hid=\"08fce45\">\r\n\u003Clink rel=\"alternate\" href=\"https://www.dummy.com/de/blog-1-ita\" hreflang=\"de\" data-hid=\"5d718b2\">\r\n\u003Clink rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-ita\" hreflang=\"x-default\" data-hid=\"6527e7a\">\r\n\u003Clink rel=\"canonical\" href=\"https://www.dummy.com/it/blog-1-ita\" data-hid=\"5cca6f5\">\r\n\r\n\u003Clink id=\"i18n-alt-it\" rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-it\" hreflang=\"it\">\r\n\u003Clink id=\"i18n-alt-de\" rel=\"alternate\" href=\"https://www.dummy.com/de/blog-1-de\" hreflang=\"de\">\r\n\u003Clink id=\"i18n-xd\" rel=\"alternate\" href=\"https://www.dummy.com/it/blog-1-it\" hreflang=\"x-default\">\r\n\u003Clink id=\"i18n-can\" rel=\"canonical\" href=\"https://www.dummy.com/it/blog-1-ita\">\r\n```\r\n\r\n### Logs\r\n\r\n_No response_",[3276,3277],{"name":3241,"color":3242},{"name":3244,"color":3245},2779,"`useSetI18nParams` and `useLocaleHead` `rel=\"alternate\"` aren't sync. ","2025-07-20T20:12:38Z","https://github.com/nuxt-modules/i18n/issues/2779",0.67075914,{"description":3284,"labels":3285,"number":3289,"owner":3178,"repository":3179,"state":3247,"title":3290,"updated_at":3291,"url":3292,"score":3293},"### Environment\n\n- Operating System: Darwin\r\n- Node Version: v18.16.0\r\n- Nuxt Version: 3.6.2\r\n- Nitro Version: 2.5.2\r\n- Package Manager: yarn@1.22.19\r\n- Builder: vite\r\n- User Config: build, css, devtools, modules, nitro, postcss, routeRules, runtimeConfig\r\n- Runtime Modules: @pinia/nuxt@0.4.11, @nuxt/image@1.0.0-rc.1, nuxt-api-party@0.13.0, @nuxtjs/i18n@8.0.0-beta.13\r\n- Build Modules: -\n\n### Reproduction\n\nhttps://github.com/joeykamsteeg/nuxt3-i18n-beforelocaleswitch-hook-not-working\n\n### Describe the bug\n\nThis hook should be triggered on app load (according to the documentation) and with initialSetup property we could hook our own logic how to handle URLs without locale in the URL. This is now not possible.\r\n\r\nIssue was reported earlier (#2248) but was closed without a resolution. \n\n### Additional context\n\n_No response_\n\n### Logs\n\n_No response_",[3286],{"name":3287,"color":3288},"hook","CF3B0A",2260,"Follow up: hook i18n:beforeLocaleSwitch does not use the locale that is return in the function","2025-05-22T19:39:58Z","https://github.com/nuxt-modules/i18n/issues/2260",0.68216485,["Reactive",3295],{},["Set"],["ShallowReactive",3298],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fBYbfyeQveKXT0a_tnZSIIjPd_qn9ywYdvT5NmJ4P_uE":-1},"/nuxt-modules/i18n/2782"]