-
Notifications
You must be signed in to change notification settings - Fork 473
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: rename locale property `iso` to `language` * refactor: rename parameters * fix: locale `language` merging * docs: expand `iso` rename explanation
- Loading branch information
1 parent
c906a8d
commit df93837
Showing
10 changed files
with
562 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
docs/content/docs/5.v9/2.guide/5.browser-language-detection.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
--- | ||
title: Browser language detection | ||
description: Detect user browser's language. | ||
--- | ||
|
||
By default, Nuxt i18n module attempts to redirect users to their preferred language by detecting their browser's language. This is controlled by the `detectBrowserLanguage` option. | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
detectBrowserLanguage: { | ||
useCookie: true, | ||
cookieKey: 'i18n_redirected', | ||
redirectOn: 'root' // recommended | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
::callout{icon="i-heroicons-light-bulb"} | ||
For better SEO, it's recommended to set `redirectOn` to `root` (which is the default value). When set, the language detection is only attempted when the user visits the root path (`/`) of the site. This allows crawlers to access the requested page rather than being redirected away based on detected locale. It also allows linking to pages in specific locales. | ||
:: | ||
|
||
Browser language is detected either from `navigator` when running on client-side, or from the `accept-language` HTTP header. Configured `locales` (or locales `language` and/or `code` when locales are specified in object form) are matched against locales reported by the browser (for example `en-US,en;q=0.9,no;q=0.8`). If there is no exact match for the full locale, the language code (letters before `-`) are matched against configured locales. | ||
|
||
To prevent redirecting users every time they visit the app, **Nuxt i18n module** sets a cookie using the detected locale. You can change the cookie's name by setting `detectBrowserLanguage.cookieKey` option to whatever you'd like, the default is _i18n_redirected_. | ||
|
||
```ts [nuxt.config.ts] | ||
i18n: { | ||
detectBrowserLanguage: { | ||
useCookie: true, | ||
cookieKey: 'my_custom_cookie_name' | ||
} | ||
} | ||
``` | ||
|
||
If you'd rather have users be redirected to their browser's language every time they visit the app, disable the cookie by setting `detectBrowserLanguage.useCookie` to `false`. | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
detectBrowserLanguage: { | ||
useCookie: false | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
To completely disable the browser's language detection feature, set `detectBrowserLanguage` to `false`. | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
// ... | ||
detectBrowserLanguage: false | ||
} | ||
}) | ||
``` | ||
|
||
To redirect the user every time they visit the app and keep their selected choice, enable `alwaysRedirect`: | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
// ... | ||
detectBrowserLanguage: { | ||
useCookie: true, | ||
alwaysRedirect: true | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
To use the cookie within a cross-origin environment (e.g. in an iFrame), you can set `cookieCrossOrigin: true`. This will change the cookie settings from `SameSite=Lax` to `SameSite=None; Secure`. | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
detectBrowserLanguage: { | ||
useCookie: true, | ||
cookieCrossOrigin: true | ||
} | ||
} | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
--- | ||
title: SEO | ||
description: When the `useLocaleHead` is called, @nuxtjs/i18n attempts to add some metadata to improve your pages SEO. Here's what it does. | ||
--- | ||
|
||
**Nuxt i18n module** provides the `useLocaleHead` composable function. Calling this composable function returns a function which you can use to generate SEO metadata to optimize locale-related aspects of the app for the search engines. | ||
|
||
Here are the specific optimizations and features that it enables: | ||
|
||
- `lang` attribute for the `<html>` tag | ||
- `hreflang` alternate link generation | ||
- OpenGraph locale tag generation | ||
- canonical link generation | ||
|
||
[Read more about those features below](#feature-details) | ||
|
||
## Requirements | ||
|
||
To leverage the SEO benefits, you must configure the `locales` option as an array of objects, where each object has an `language` option set to the locale language tags: | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
locales: [ | ||
{ | ||
code: 'en', | ||
language: 'en-US' | ||
}, | ||
{ | ||
code: 'es', | ||
language: 'es-ES' | ||
}, | ||
{ | ||
code: 'fr', | ||
language: 'fr-FR' | ||
} | ||
] | ||
} | ||
}) | ||
``` | ||
|
||
You must also set the `baseUrl` option to your production domain in order to make alternate URLs fully-qualified: | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
baseUrl: 'https://my-nuxt-app.com' | ||
} | ||
}) | ||
``` | ||
|
||
(Note that `baseUrl` can also be set to a function. Check [`baseUrl` documentation](/docs/options/routing#baseurl).) | ||
|
||
## Setup | ||
|
||
The `useLocaleHead` is a composable function, Calling that composable function returns a function that returns metadata that is handled by [Head management](https://nuxt.com/docs/getting-started/seo-meta) that is integrated within Nuxt. That metadata can be specified the `setup` function in various places within Nuxt: | ||
|
||
- [`app.vue`](https://nuxt.com/docs/guide/directory-structure/app) | ||
- Vue components of [`pages`](https://nuxt.com/docs/guide/directory-structure/pages) directory | ||
- Vue components of [`layouts`](https://nuxt.com/docs/guide/directory-structure/layouts) directory | ||
|
||
To enable SEO metadata, declare a `setup` function in one of the places specified above and make it return the result of a `useLocaleHead` function call. | ||
|
||
To avoid duplicating the code, it's recommended to set globally with [Meta Components](https://nuxt.com/docs/getting-started/seo-meta#components) in [layout components](https://nuxt.com/docs/guide/directory-structure/layouts) and override some values per-page Vue component like [`definePageMeta`](https://nuxt.com/docs/guide/directory-structure/pages#page-metadata), if necessary. | ||
|
||
::code-group | ||
|
||
```vue [app.vue] | ||
<template> | ||
<NuxtLayout> | ||
<NuxtPage /> | ||
</NuxtLayout> | ||
</template> | ||
``` | ||
|
||
```vue [layouts/default.vue] | ||
<script setup> | ||
const route = useRoute() | ||
const { t } = useI18n() | ||
const head = useLocaleHead({ | ||
addDirAttribute: true, | ||
identifierAttribute: 'id', | ||
addSeoAttributes: true | ||
}) | ||
const title = computed(() => t(route.meta.title ?? 'TBD', t('layouts.title')) | ||
); | ||
</script> | ||
<template> | ||
<div> | ||
<Html :lang="head.htmlAttrs.lang" :dir="head.htmlAttrs.dir"> | ||
<Head> | ||
<Title>{{ title }}</Title> | ||
<template v-for="link in head.link" :key="link.id"> | ||
<Link :id="link.id" :rel="link.rel" :href="link.href" :hreflang="link.hreflang" /> | ||
</template> | ||
<template v-for="meta in head.meta" :key="meta.id"> | ||
<Meta :id="meta.id" :property="meta.property" :content="meta.content" /> | ||
</template> | ||
</Head> | ||
<Body> | ||
<slot /> | ||
</Body> | ||
</Html> | ||
</div> | ||
</template> | ||
``` | ||
|
||
```vue [pages/index.vue] | ||
<script setup> | ||
definePageMeta({ | ||
title: 'pages.title.top' // set resource key | ||
}) | ||
const { locale, locales, t } = useI18n() | ||
const switchLocalePath = useSwitchLocalePath() | ||
const availableLocales = computed(() => { | ||
return locales.value.filter(i => i.code !== locale.value) | ||
}) | ||
</script> | ||
<template> | ||
<div> | ||
<p>{{ t('pages.top.description') }}</p> | ||
<p>{{ t('pages.top.languages') }}</p> | ||
<nav> | ||
<template v-for="(locale, index) in availableLocales" :key="locale.code"> | ||
<span v-if="index"> | </span> | ||
<NuxtLink :to="switchLocalePath(locale.code)"> | ||
{{ locale.name ?? locale.code }} | ||
</NuxtLink> | ||
</template> | ||
</nav> | ||
</div> | ||
</template> | ||
``` | ||
|
||
:: | ||
|
||
Check out the options you can pass to the `useLocaleHead` in the [API documentation](/docs/api#uselocalehead) | ||
|
||
That's it! | ||
|
||
If you also want to add your own metadata, you have to call `useHead`. When you call `useHead` with the additional metadata, `useHead` will merge it global metadata that has already defined. | ||
|
||
```vue [pages/about/index.vue] | ||
<script setup> | ||
// define page meta for layouts/default.vue | ||
definePageMeta({ | ||
title: 'pages.title.about' | ||
}) | ||
useHead({ | ||
meta: [{ property: 'og:title', content: 'this is og title for about page' }] | ||
}) | ||
</script> | ||
<template> | ||
<h2>{{ $t('pages.about.description') }}</h2> | ||
</template> | ||
``` | ||
|
||
## Feature details | ||
|
||
- `lang` attribute for the `<html>` tag | ||
|
||
Sets the correct `lang` attribute, equivalent to the current locale's `language` value, in the `<html>` tag. | ||
|
||
- `hreflang` alternate link | ||
|
||
Generates `<link rel="alternate" hreflang="x">` tags for every configured locale. The locales' `language` value are used as `hreflang` values. | ||
|
||
A "catchall" locale hreflang link is provided for each locale group (e.g. `en-*`). By default, it is the first locale provided, but another locale can be selected by setting `isCatchallLocale` to `true` on that specific locale object in your **Nuxt i18n module** configuration. [More on hreflang](https://support.google.com/webmasters/answer/189077) | ||
|
||
An example without selected "catchall" locale: | ||
|
||
```ts {}[nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
locales: [ | ||
{ | ||
code: 'en', | ||
language: 'en-US' // Will be used as "catchall" locale by default | ||
}, | ||
{ | ||
code: 'gb', | ||
language: 'en-GB' | ||
} | ||
] | ||
} | ||
}) | ||
``` | ||
|
||
Here is how you'd use `isCatchallLocale` to selected another locale: | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
locales: [ | ||
{ | ||
code: 'en', | ||
language: 'en-US' | ||
}, | ||
{ | ||
code: 'gb', | ||
language: 'en-GB', | ||
isCatchallLocale: true // This one will be used as catchall locale | ||
} | ||
] | ||
} | ||
}) | ||
``` | ||
|
||
In case you already have an `en` locale `language` set, it'll be used as the "catchall" without doing anything | ||
|
||
```ts [nuxt.config.ts] | ||
export default defineNuxtConfig({ | ||
i18n: { | ||
locales: [ | ||
{ | ||
code: 'gb', | ||
language: 'en-GB' | ||
}, | ||
{ | ||
code: 'en', | ||
language: 'en' // will be used as "catchall" locale | ||
} | ||
] | ||
} | ||
}) | ||
``` | ||
|
||
- OpenGraph Locale tag generation | ||
|
||
Generates `og:locale` and `og:locale:alternate` meta tags as defined in the [Open Graph protocol](http://ogp.me/#optional). | ||
|
||
- Canonical link | ||
|
||
Generates `rel="canonical"` link on all pages to specify the "main" version of the page that should be indexed by search engines. This is beneficial in various situations: | ||
|
||
- When using the `prefix_and_default` strategy there are technically two sets of pages generated for the default locale -- one prefixed and one unprefixed. The canonical link will be set to the unprefixed version of the page to avoid duplicate indexation. | ||
- When the page contains query parameters, the canonical link will **not include** the query params by default. This is typically the right thing to do as various query params can be inserted by trackers and should not be part of the canonical link. This can be overridden by using the `canonicalQueries` option. For example: | ||
|
||
```vue | ||
<script setup> | ||
const i18nHead = useLocaleHead({ | ||
addSeoAttributes: { | ||
canonicalQueries: ['foo'] | ||
} | ||
}) | ||
useHead({ | ||
htmlAttrs: { | ||
lang: i18nHead.value.htmlAttrs!.lang | ||
}, | ||
link: [...(i18nHead.value.link || [])], | ||
meta: [...(i18nHead.value.meta || [])] | ||
}) | ||
</script> | ||
``` | ||
|
||
[More on canonical](https://support.google.com/webmasters/answer/182192#dup-content) |
Oops, something went wrong.