\n\n### Additional context\n\n_No response_\n\n### Logs\n\n```shell\n\n```",[3246,3247],{"name":3175,"color":3176},{"name":3178,"color":3179},3807,"静态生成时,.output下 locales语言文件是空的","2025-09-05T01:23:11Z","https://github.com/nuxt-modules/i18n/issues/3807",0.6679127,{"description":3254,"labels":3255,"number":3257,"owner":3181,"repository":3182,"state":3224,"title":3258,"updated_at":3259,"url":3260,"score":3261},"### Environment\n\n- Operating System: Linux\n- Node Version: v22.14.0\n- Nuxt Version: 3.18.0\n- CLI Version: 3.28.0\n- Nitro Version: 2.12.5\n- Package Manager: npm@10.9.2\n- Builder: -\n- User Config: compatibilityDate, devtools, modules, i18n, vite\n- Runtime Modules: @nuxt/eslint@1.0.1, @nuxtjs/i18n@10.0.6, @nuxt/image@1.9.0\n- Build Modules: -\n------------------------------\n\n\n### Reproduction\n\n**i18n config**\n```\nconst UA_LOCALE = 'ua';\nconst EN_LOCALE = 'en';\n\nexport const LOCALES = [\n {\n code: EN_LOCALE,\n iso: 'en',\n file: 'en.js',\n hreflang: EN_LOCALE,\n title: 'English',\n },\n {\n code: UA_LOCALE,\n iso: 'uk',\n file: 'ua.js',\n hreflang: 'uk',\n title: 'Українська',\n },\n];\n\nexport default {\n locales: LOCALES,\n defaultLocale: EN_LOCALE,\n strategy: 'prefix_except_default',\n fallbackLocale: EN_LOCALE,\n detectBrowserLanguage: true,\n langDir: './locales',\n restructureDir: '',\n};\n\n```\n\nnuxt.config.js\n```\nimport { defineNuxtConfig } from \"nuxt/config\"\nimport i18nConfig from './config/i18n.config';\n\nexport default defineNuxtConfig({\n compatibilityDate: '2024-11-01',\n devtools: { enabled: true },\n modules: ['@nuxt/eslint', '@nuxtjs/i18n', '@nuxt/image'],\n i18n: i18nConfig,\n vite: {\n css: {\n preprocessorOptions: {\n scss: {\n additionalData: '@use \"~/assets/scss/_variables.scss\" as *;'\n }\n }\n }\n },\n})\n\n```\n**Project is SSR not SSG**\n\n### Describe the bug\n\nOn direct app access i18n request twice for message.json.\n\n\u003Cimg width=\"918\" height=\"241\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/e1267897-7583-47ee-8d94-3286f5f875cc\" />\n\n It calls twice `loadMessages` first time from init, and second after \"locale-changing\" middleware.\n\n\u003Cimg width=\"1591\" height=\"419\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/956c305d-57e9-4a71-a3b6-5e2231a460df\" />\n\nLog from middleware handler\n\n\u003Cimg width=\"1080\" height=\"934\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/228c3154-f653-4190-b9a4-7ce6c197b00d\" />\n\nI faced this problem on big project, i thought maybe i have problems in router or something else, but used it tiny one to be sure\nTried to add and remove lazy: true, detectBrowserLanguage: false also tried.\n\n**Project structure, no custom routing**\n\u003Cimg width=\"1137\" height=\"991\" alt=\"Image\" src=\"https://github.com/user-attachments/assets/9b9385cd-713e-4801-af61-6f8be38c73f1\" />\n\n### Additional context\n\n_No response_\n\n### Logs\n\n```shell\n\n```",[3256],{"name":3175,"color":3176},3813,"Duplicate request on client for messages","2025-09-11T15:30:00Z","https://github.com/nuxt-modules/i18n/issues/3813",0.67290956,{"description":3263,"labels":3264,"number":3267,"owner":3181,"repository":3182,"state":3224,"title":3268,"updated_at":3269,"url":3270,"score":3271},"### 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```",[3265,3266],{"name":3175,"color":3176},{"name":3178,"color":3179},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.67339474,{"description":3273,"labels":3274,"number":3284,"owner":3181,"repository":3182,"state":3224,"title":3285,"updated_at":3286,"url":3287,"score":3288},"### Describe the feature\r\n\r\nAs discussed on Discord with @BobbieGoede and @harlan-zw, there is Harlan's amazing [site-config](https://nuxtseo.com/site-config/getting-started/background) project which aims to provide a central method for general site configuration so not every other module has to implement this itself.\r\n\r\n`nuxt-i18n` allows to specify a `baseUrl`, which is exactly such a reimplementation. I propose to support reading the `i18n.baseUrl` from `site.url` when it is available, keeping the fallback to `i18n.baseUrl`.\r\n\r\nOf course `i18n.baseUrl` *could* be marked as deprecated until the final `v8` release if everything works fine outsourcing the `baseUrl` to `nuxt-site-config` to keep a separation of concerns.\r\n\r\n### Additional information\r\n\r\n- [x] Would you be willing to help implement this feature?\r\n- [ ] Could this feature be implemented as a module?\r\n\r\n### Final checks\r\n\r\n- [X] Read the [contribution guide](https://nuxt.com/docs/community/contribution) (The contribution guideline of nuxt-modules/i18n is compliant with Nuxt too).\r\n- [X] Check existing [discussions](https://github.com/nuxt-modules/i18n/discussions) and [issues](https://github.com/nuxt/nuxt/issues).",[3275,3278,3281],{"name":3276,"color":3277},"need discussion","E9EC2E",{"name":3279,"color":3280},"PR Welcome","40922A",{"name":3282,"color":3283},"scope: configuration","b60205",2474,"feat: support `nuxt-site-config`","2025-07-03T13:00:13Z","https://github.com/nuxt-modules/i18n/issues/2474",0.67569286,["Reactive",3290],{},["Set"],["ShallowReactive",3293],{"$fTRc1wZytZ_XrK4EfJfei_Sz-An4H4Yy6syhVxH_PVJc":-1,"$fiebAbWTGt4l36Rpti4CWbZ7nFX5-_6WG3NDZW9IG0xo":-1},"/nuxt-modules/i18n/3727"]