From a3fb89f61b57006a3f1f5b1eb64e0ed63b0ddea2 Mon Sep 17 00:00:00 2001 From: Bobbie Goede Date: Fri, 13 Sep 2024 17:42:32 +0200 Subject: [PATCH] feat!: configurable `lang` attribute for `useLocaleHead` (#3097) --- .../docs/5.v9/2.guide/19.breaking-changes-in-v9.md | 6 +++++- docs/content/docs/5.v9/2.guide/6.seo.md | 2 ++ docs/content/docs/5.v9/4.api/1.index.md | 6 ++++++ playground/layouts/default.vue | 2 +- playground/pages/index.vue | 2 +- specs/fixtures/basic/pages/index.vue | 1 + specs/fixtures/basic_usage/layouts/default.vue | 1 + specs/fixtures/basic_usage/pages/index.vue | 1 + .../basic_usage/pages/nuxt-context-extension.vue | 2 +- specs/fixtures/issues/2590/app.vue | 1 + specs/fixtures/lazy/pages/index.vue | 2 +- specs/fixtures/restructure/pages/index.vue | 2 +- src/runtime/composables/index.ts | 2 ++ src/runtime/routing/compatibles/head.ts | 10 ++++++---- src/types.ts | 6 ++++++ 15 files changed, 36 insertions(+), 10 deletions(-) diff --git a/docs/content/docs/5.v9/2.guide/19.breaking-changes-in-v9.md b/docs/content/docs/5.v9/2.guide/19.breaking-changes-in-v9.md index 28d435e32..dac7ba993 100644 --- a/docs/content/docs/5.v9/2.guide/19.breaking-changes-in-v9.md +++ b/docs/content/docs/5.v9/2.guide/19.breaking-changes-in-v9.md @@ -59,4 +59,8 @@ Some properties have changed or swapped names to better fit their functionality, | v8 | v9 | Notes | | --- | --- | --- | | `locales` | `domainLocales` | This also changes the environment variable key to `NUXT_PUBLIC_I18N_DOMAIN_LOCALES_{code}_DOMAIN`, see [`runtimeConfig`](/docs/options/runtime-config#domainLocales) | -| `configLocales` | `locales` | | \ No newline at end of file +| `configLocales` | `locales` | | + +## SEO - `useLocaleHead` + +We have added a `addLangAttribute` property to the options parameter of `useLocaleHead` and `$localeHead`, originally this was not configurable on its own. If you want to keep the same behavior, if you were passing `addSeoAttributes`, you will also have to pass `addLangAttribute: true`. See [`useLocaleHead`](/docs/v9/api#useLocaleHead) diff --git a/docs/content/docs/5.v9/2.guide/6.seo.md b/docs/content/docs/5.v9/2.guide/6.seo.md index b61543961..7a4e5a50d 100644 --- a/docs/content/docs/5.v9/2.guide/6.seo.md +++ b/docs/content/docs/5.v9/2.guide/6.seo.md @@ -79,6 +79,7 @@ const route = useRoute() const { t } = useI18n() const head = useLocaleHead({ addDirAttribute: true, + addLangAttribute: true, identifierAttribute: 'id', addSeoAttributes: true }) @@ -245,6 +246,7 @@ useHead({ ```vue diff --git a/playground/pages/index.vue b/playground/pages/index.vue index 45f6898eb..c5f969e0a 100644 --- a/playground/pages/index.vue +++ b/playground/pages/index.vue @@ -99,7 +99,7 @@ definePageMeta({

{{ item }}

-
v-t directive:
+ diff --git a/specs/fixtures/basic/pages/index.vue b/specs/fixtures/basic/pages/index.vue index 009d23cbe..a99a1245e 100644 --- a/specs/fixtures/basic/pages/index.vue +++ b/specs/fixtures/basic/pages/index.vue @@ -8,6 +8,7 @@ import LangSwitcher from '../components/LangSwitcher.vue' const { t } = useI18n() const localePath = useLocalePath() const i18nHead = useLocaleHead({ + addLangAttribute: true, addDirAttribute: true, identifierAttribute: 'id', addSeoAttributes: { canonicalQueries: ['page'] }, diff --git a/specs/fixtures/basic_usage/layouts/default.vue b/specs/fixtures/basic_usage/layouts/default.vue index 1f96c7bce..c76ea6c80 100644 --- a/specs/fixtures/basic_usage/layouts/default.vue +++ b/specs/fixtures/basic_usage/layouts/default.vue @@ -7,6 +7,7 @@ const route = useRoute() const { t } = useI18n() const head = useLocaleHead({ addDirAttribute: true, + addLangAttribute: true, identifierAttribute: 'id', addSeoAttributes: { canonicalQueries: ['page'] } }) diff --git a/specs/fixtures/basic_usage/pages/index.vue b/specs/fixtures/basic_usage/pages/index.vue index 2bee42e1b..09f439f4e 100644 --- a/specs/fixtures/basic_usage/pages/index.vue +++ b/specs/fixtures/basic_usage/pages/index.vue @@ -64,6 +64,7 @@ definePageMeta({ const i18nHead = useLocaleHead({ addDirAttribute: true, + addLangAttribute: true, identifierAttribute: 'id', addSeoAttributes: { canonicalQueries: ['page'] } }) diff --git a/specs/fixtures/basic_usage/pages/nuxt-context-extension.vue b/specs/fixtures/basic_usage/pages/nuxt-context-extension.vue index 3bcae8aac..2e03bdb5f 100644 --- a/specs/fixtures/basic_usage/pages/nuxt-context-extension.vue +++ b/specs/fixtures/basic_usage/pages/nuxt-context-extension.vue @@ -6,6 +6,6 @@

{{ $nuxt.$switchLocalePath('ja') }}

{{ $nuxt.$localePath('nuxt-context-extension', 'nl') }}

{{ JSON.stringify($nuxt.$localeRoute()) }}

-

{{ $nuxt.$localeHead({}) }}

+

{{ $nuxt.$localeHead({ addLangAttribute: true }) }}

diff --git a/specs/fixtures/issues/2590/app.vue b/specs/fixtures/issues/2590/app.vue index 54e7572d1..4c4bdb115 100644 --- a/specs/fixtures/issues/2590/app.vue +++ b/specs/fixtures/issues/2590/app.vue @@ -9,6 +9,7 @@ const { locale, locales, setLocale } = useI18n() const head = useLocaleHead({ addDirAttribute: true, + addLangAttribute: true, addSeoAttributes: true }) diff --git a/specs/fixtures/lazy/pages/index.vue b/specs/fixtures/lazy/pages/index.vue index 85bcae3a6..d90267eb8 100644 --- a/specs/fixtures/lazy/pages/index.vue +++ b/specs/fixtures/lazy/pages/index.vue @@ -6,7 +6,7 @@ import LangSwitcher from '../components/LangSwitcher.vue' const { t } = useI18n() const localePath = useLocalePath() -const i18nHead = useLocaleHead({ addSeoAttributes: { canonicalQueries: ['page'] } }) +const i18nHead = useLocaleHead({ addLangAttribute: true, addSeoAttributes: { canonicalQueries: ['page'] } }) const { data, refresh } = useAsyncData('home', () => Promise.resolve({ aboutPath: localePath('about'), diff --git a/specs/fixtures/restructure/pages/index.vue b/specs/fixtures/restructure/pages/index.vue index 85bcae3a6..d90267eb8 100644 --- a/specs/fixtures/restructure/pages/index.vue +++ b/specs/fixtures/restructure/pages/index.vue @@ -6,7 +6,7 @@ import LangSwitcher from '../components/LangSwitcher.vue' const { t } = useI18n() const localePath = useLocalePath() -const i18nHead = useLocaleHead({ addSeoAttributes: { canonicalQueries: ['page'] } }) +const i18nHead = useLocaleHead({ addLangAttribute: true, addSeoAttributes: { canonicalQueries: ['page'] } }) const { data, refresh } = useAsyncData('home', () => Promise.resolve({ aboutPath: localePath('about'), diff --git a/src/runtime/composables/index.ts b/src/runtime/composables/index.ts index ee6c63bdc..b3b247856 100644 --- a/src/runtime/composables/index.ts +++ b/src/runtime/composables/index.ts @@ -135,6 +135,7 @@ export type LocaleHeadFunction = (options: I18nHeadOptions) => ReturnType { @@ -156,6 +157,7 @@ export function useLocaleHead({ function updateMeta() { metaObject.value = localeHead(common, { addDirAttribute, + addLangAttribute, addSeoAttributes, identifierAttribute }) diff --git a/src/runtime/routing/compatibles/head.ts b/src/runtime/routing/compatibles/head.ts index 7b9faad7b..e298c5faa 100644 --- a/src/runtime/routing/compatibles/head.ts +++ b/src/runtime/routing/compatibles/head.ts @@ -23,6 +23,7 @@ export function localeHead( common: CommonComposableOptions, { addDirAttribute = false, + addLangAttribute = false, addSeoAttributes: seoAttributes = true, identifierAttribute: idAttribute = 'hid' }: I18nHeadOptions @@ -36,6 +37,7 @@ export function localeHead( meta: [] } + // skip if no locales or baseUrl is set if (unref(i18n.locales) == null || unref(i18n.baseUrl) == null) { return metaObject } @@ -53,12 +55,12 @@ export function localeHead( metaObject.htmlAttrs.dir = currentDir } + if (addLangAttribute && currentLanguage) { + metaObject.htmlAttrs.lang = currentLanguage + } + // Adding SEO Meta if (seoAttributes && locale && unref(i18n.locales)) { - if (currentLanguage) { - metaObject.htmlAttrs.lang = currentLanguage - } - metaObject.link.push( ...getHreflangLinks(common, unref(locales) as LocaleObject[], idAttribute), ...getCanonicalLink(common, idAttribute, seoAttributes) diff --git a/src/types.ts b/src/types.ts index 6413d9519..6bbf674d0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -343,6 +343,12 @@ export interface SeoAttributesOptions { * @public */ export interface I18nHeadOptions { + /** + * Adds a `lang` attribute to the HTML element. + * + * @defaultValue false + */ + addLangAttribute?: boolean /** * Adds a `dir` attribute to the HTML element. *