From be4fdff74818c6f63c4bc2456a7f51d6535b26aa Mon Sep 17 00:00:00 2001 From: Bobbie Goede Date: Wed, 6 Dec 2023 02:55:46 +0100 Subject: [PATCH] fix: module locale option generation breaking SEO (#2598) * fix: module locale option generation breaking SEO * test: add issue #2590 test --- specs/fixtures/issues/2590/app.vue | 43 +++++++++++++++++++ specs/fixtures/issues/2590/i18n.config.ts | 3 ++ .../issues/2590/modules/i18n-module/index.ts | 35 +++++++++++++++ .../2590/modules/i18n-module/lang/en-US.ts | 5 +++ specs/fixtures/issues/2590/nuxt.config.ts | 5 +++ specs/fixtures/issues/2590/package.json | 14 ++++++ specs/issues/2590.spec.ts | 22 ++++++++++ src/gen.ts | 11 ++--- 8 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 specs/fixtures/issues/2590/app.vue create mode 100644 specs/fixtures/issues/2590/i18n.config.ts create mode 100644 specs/fixtures/issues/2590/modules/i18n-module/index.ts create mode 100755 specs/fixtures/issues/2590/modules/i18n-module/lang/en-US.ts create mode 100644 specs/fixtures/issues/2590/nuxt.config.ts create mode 100644 specs/fixtures/issues/2590/package.json create mode 100644 specs/issues/2590.spec.ts diff --git a/specs/fixtures/issues/2590/app.vue b/specs/fixtures/issues/2590/app.vue new file mode 100644 index 000000000..54e7572d1 --- /dev/null +++ b/specs/fixtures/issues/2590/app.vue @@ -0,0 +1,43 @@ + + + diff --git a/specs/fixtures/issues/2590/i18n.config.ts b/specs/fixtures/issues/2590/i18n.config.ts new file mode 100644 index 000000000..2a10cbb66 --- /dev/null +++ b/specs/fixtures/issues/2590/i18n.config.ts @@ -0,0 +1,3 @@ +export default defineI18nConfig(() => ({ + legacy: false +})) diff --git a/specs/fixtures/issues/2590/modules/i18n-module/index.ts b/specs/fixtures/issues/2590/modules/i18n-module/index.ts new file mode 100644 index 000000000..0dbc0956f --- /dev/null +++ b/specs/fixtures/issues/2590/modules/i18n-module/index.ts @@ -0,0 +1,35 @@ +import { createResolver, defineNuxtModule, installModule } from '@nuxt/kit' + +export default defineNuxtModule({ + async setup(options, nuxt) { + const { resolve } = createResolver(import.meta.url) + + nuxt.hook('i18n:registerModule', registerModule => + registerModule({ + langDir: resolve('lang'), + locales: [ + { + code: 'en', + iso: 'en-US', + file: 'en-US.ts', + name: 'English' + } + ] + }) + ) + + await installModule('@nuxtjs/i18n', { + lazy: true, + defaultLocale: 'en', + experimental: { + jsTsFormatResource: true + }, + detectBrowserLanguage: { + useCookie: true, + cookieKey: 'i18n_lang', + redirectOn: 'root' + }, + vueI18n: './i18n.config.ts' + }) + } +}) diff --git a/specs/fixtures/issues/2590/modules/i18n-module/lang/en-US.ts b/specs/fixtures/issues/2590/modules/i18n-module/lang/en-US.ts new file mode 100755 index 000000000..28b11b92c --- /dev/null +++ b/specs/fixtures/issues/2590/modules/i18n-module/lang/en-US.ts @@ -0,0 +1,5 @@ +export default defineI18nLocale(async () => { + return { + welcome: 'welcome translated' + } +}) diff --git a/specs/fixtures/issues/2590/nuxt.config.ts b/specs/fixtures/issues/2590/nuxt.config.ts new file mode 100644 index 000000000..3d49d7080 --- /dev/null +++ b/specs/fixtures/issues/2590/nuxt.config.ts @@ -0,0 +1,5 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + devtools: { enabled: false }, + modules: ['./modules/i18n-module'] +}) diff --git a/specs/fixtures/issues/2590/package.json b/specs/fixtures/issues/2590/package.json new file mode 100644 index 000000000..733066968 --- /dev/null +++ b/specs/fixtures/issues/2590/package.json @@ -0,0 +1,14 @@ +{ + "name": "nuxt3-test-issues-2473", + "private": true, + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview" + }, + "devDependencies": { + "@nuxtjs/i18n": "latest", + "nuxt": "latest" + } +} diff --git a/specs/issues/2590.spec.ts b/specs/issues/2590.spec.ts new file mode 100644 index 000000000..4495aabdb --- /dev/null +++ b/specs/issues/2590.spec.ts @@ -0,0 +1,22 @@ +import { test, expect, describe } from 'vitest' +import { fileURLToPath } from 'node:url' +import { URL } from 'node:url' +import { setup } from '../utils' +import { renderPage } from '../helper' + +describe('#2590', async () => { + await setup({ + rootDir: fileURLToPath(new URL(`../fixtures/issues/2590`, import.meta.url)), + browser: true + }) + + test('Locale ISO code is required to generate alternate link', async () => { + const { page } = await renderPage('/') + + // html tag `lang` attribute + expect(await page.getAttribute('html', 'lang')).toMatch('en') + + // html tag `dir` attribute + expect(await page.getAttribute('html', 'dir')).toMatch('ltr') + }) +}) diff --git a/src/gen.ts b/src/gen.ts index 197b0cf6d..cf7506c68 100644 --- a/src/gen.ts +++ b/src/gen.ts @@ -25,11 +25,12 @@ const generateVueI18nConfiguration = (config: Required): }) } -function simplifyLocaleOptions(nuxt: Nuxt, locales: LocaleObject[]) { - const hasObjectLocales = nuxt.options._layers.some( - layer => layer?.config?.i18n?.locales?.some(x => typeof x !== 'string') - ) +function simplifyLocaleOptions(nuxt: Nuxt, options: NuxtI18nOptions) { + const hasObjectLocales = + nuxt.options._layers.some(layer => layer?.config?.i18n?.locales?.some(x => typeof x !== 'string')) || + options?.i18nModules?.some(module => module?.locales?.some(x => typeof x !== 'string')) + const locales = (options.locales ?? []) as LocaleObject[] // eslint-disable-next-line @typescript-eslint/no-unused-vars return locales.map(({ meta, ...locale }) => { if (!hasObjectLocales) { @@ -94,7 +95,7 @@ export function generateLoaderOptions(nuxt: Nuxt, { nuxtI18nOptions, vueI18nConf const generatedNuxtI18nOptions = { ...nuxtI18nOptions, - locales: simplifyLocaleOptions(nuxt, (nuxtI18nOptions?.locales ?? []) as unknown as LocaleObject[]) + locales: simplifyLocaleOptions(nuxt, nuxtI18nOptions) } delete nuxtI18nOptions.vueI18n