From 449a2e8493e0311d29b8ea2975018c33c808148f Mon Sep 17 00:00:00 2001 From: Divine <48183131+divine@users.noreply.github.com> Date: Tue, 20 Jul 2021 11:54:35 +0300 Subject: [PATCH] refactor!: replace onlyOnNoPrefix and onlyOnRoot with redirectOn (#1210) --- docs/content/en/browser-language-detection.md | 4 +-- docs/content/en/migrating.md | 2 ++ docs/content/en/options-reference.md | 10 ++++--- src/helpers/constants.js | 12 ++++++-- src/index.js | 5 ++-- src/templates/options.d.ts | 3 +- src/templates/plugin.main.js | 11 ++++---- test/browser.test.js | 28 +++++++++---------- test/module.test.js | 4 +-- types/index.d.ts | 4 +-- 10 files changed, 48 insertions(+), 35 deletions(-) diff --git a/docs/content/en/browser-language-detection.md b/docs/content/en/browser-language-detection.md index 60d6959ba..611db8a41 100644 --- a/docs/content/en/browser-language-detection.md +++ b/docs/content/en/browser-language-detection.md @@ -13,14 +13,14 @@ By default, **nuxt-i18n** attempts to redirect users to their preferred language detectBrowserLanguage: { useCookie: true, cookieKey: 'i18n_redirected', - onlyOnRoot: true, // recommended + redirectOn: 'root', // recommended } }] ``` -For better SEO, it's recommended to set `onlyOnRoot` to `true`. With it 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. +For better SEO, it's recommended to set `redirectOn` to `root`. With it 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. diff --git a/docs/content/en/migrating.md b/docs/content/en/migrating.md index 79eb97a26..b3db5a6ee 100644 --- a/docs/content/en/migrating.md +++ b/docs/content/en/migrating.md @@ -17,6 +17,8 @@ Follow this guide to upgrade from one major version to the other. ### `seo` option has been removed. Use `$nuxtI18nHead({ addDirAttribute: true, addSeoAttributes: true })` instead. +### `onlyOnRoot` and `onlyOnNoPrefix` has been removed. It's features are combined into `redirectOn` instead. Use `redirectOn: 'all|root|no prefix'` instead. + ## Upgrading from 5.x to 6.x ### Global SEO features are now disabled by default diff --git a/docs/content/en/options-reference.md b/docs/content/en/options-reference.md index 6a993c4a5..deec64fc7 100644 --- a/docs/content/en/options-reference.md +++ b/docs/content/en/options-reference.md @@ -160,7 +160,7 @@ Directory that contains translation files to load. Can be used with or without l ## `detectBrowserLanguage` - type: `object` -- default: `{ alwaysRedirect: false, fallbackLocale: '', onlyOnRoot: false, useCookie: true, cookieCrossOrigin: false, cookieDomain: null, cookieKey: 'i18n_redirected', cookieSecure: false }` +- default: `{ alwaysRedirect: false, fallbackLocale: '', redirectOn: 'all', useCookie: true, cookieCrossOrigin: false, cookieDomain: null, cookieKey: 'i18n_redirected', cookieSecure: false }` Enables browser language detection to automatically redirect visitors to their preferred locale as they visit your site for the first time. @@ -168,15 +168,17 @@ See also [Browser language detection](/browser-language-detection) for a guide. -Note that for better SEO it's recommended to set `onlyOnRoot` to true. +Note that for better SEO it's recommended to set `redirectOn` to `root`. Supported properties: - `alwaysRedirect` (default: `false`) - Set to always redirect to the value stored in the cookie, not just on first visit. - `fallbackLocale` (default: `null`) - If none of the locales match the browser's locale, use this one as a fallback. -- `onlyOnRoot` (default: `false`) - Set to `true` (recommended for improved SEO) to only attempt to detect the browser locale on the root path (`/`) of the site. Only effective when using strategy other than `'no_prefix'`. -- `onlyOnNoPrefix` (default: `false`) - This is a more permissive variant of `onlyOnRoot` that will attempt to detect the browser locale on the root path (`/`) and also on paths that have no locale prefix (like `/foo`). Only effective when `onlyOnRoot` is not enabled and using strategy other than `'no_prefix'`. +- `redirectOn` (default: `all`) - Supported options: + - `all` - detect browser locale on all paths. + - `root` (recommended for improved SEO) - only detect the browser locale on the root path (`/`) of the site. Only effective when using strategy other than `'no_prefix'`. + - `no prefix` - a more permissive variant of `root` that will detect the browser locale on the root path (`/`) and also on paths that have no locale prefix (like `/foo`). Only effective when using strategy other than `'no_prefix'`. - `useCookie` (default: `true`) - If enabled, a cookie is set once the user has been redirected to browser's preferred locale, to prevent subsequent redirections. Set to `false` to redirect every time. - `cookieKey` (default: `'i18n_redirected'`) - Cookie name. - `cookieDomain` (default: `null`) - Set to override the default domain of the cookie. Defaults to the **host** of the site. diff --git a/src/helpers/constants.js b/src/helpers/constants.js index 9cb98c68b..a0bf78be4 100644 --- a/src/helpers/constants.js +++ b/src/helpers/constants.js @@ -17,6 +17,15 @@ export const STRATEGIES = { NO_PREFIX: STRATEGY_NO_PREFIX } +const REDIRECT_ON_ALL = 'all' +const REDIRECT_ON_ROOT = 'root' +const REDIRECT_ON_NO_PREFIX = 'no prefix' +export const REDIRECT_ON_OPTIONS = { + ALL: REDIRECT_ON_ALL, + ROOT: REDIRECT_ON_ROOT, + NO_PREFIX: REDIRECT_ON_NO_PREFIX +} + export const COMPONENT_OPTIONS_KEY = 'nuxtI18n' /** @type {Options} */ @@ -40,8 +49,7 @@ export const DEFAULT_OPTIONS = { cookieKey: 'i18n_redirected', cookieSecure: false, fallbackLocale: '', - onlyOnNoPrefix: false, - onlyOnRoot: false, + redirectOn: 'all', useCookie: true }, differentDomains: false, diff --git a/src/index.js b/src/index.js index 0d083e1b2..3cf47361e 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ import { readdirSync } from 'fs' import merge from 'lodash.merge' // @ts-ignore import { directive as i18nExtensionsDirective } from '@intlify/vue-i18n-extensions' -import { COMPONENT_OPTIONS_KEY, DEFAULT_OPTIONS, ROOT_DIR, STRATEGIES } from './helpers/constants' +import { COMPONENT_OPTIONS_KEY, DEFAULT_OPTIONS, ROOT_DIR, STRATEGIES, REDIRECT_ON_OPTIONS } from './helpers/constants' import { buildHook, createExtendRoutesHook } from './core/hooks' import { formatMessage } from './templates/utils-common' @@ -53,7 +53,8 @@ export default function (moduleOptions) { const templatesOptions = { Constants: { COMPONENT_OPTIONS_KEY, - STRATEGIES + STRATEGIES, + REDIRECT_ON_OPTIONS }, nuxtOptions: { isUniversalMode: nuxtOptions.mode === 'universal', diff --git a/src/templates/options.d.ts b/src/templates/options.d.ts index 8189a70ff..9213ab722 100644 --- a/src/templates/options.d.ts +++ b/src/templates/options.d.ts @@ -1,11 +1,12 @@ import Vue from 'vue' import { ComponentOptions } from 'vue/types/options' -import { STRATEGIES } from '../helpers/constants' +import { STRATEGIES, REDIRECT_ON_OPTIONS } from '../helpers/constants' import { LocaleFileExport, ResolvedOptions } from '../../types/internal' interface ModuleConstants { COMPONENT_OPTIONS_KEY: keyof Pick, 'nuxtI18n'> STRATEGIES: typeof STRATEGIES + REDIRECT_ON_OPTIONS: typeof REDIRECT_ON_OPTIONS } interface ModuleNuxtOptions { diff --git a/src/templates/plugin.main.js b/src/templates/plugin.main.js index 5ee35bdc1..506ab76cb 100644 --- a/src/templates/plugin.main.js +++ b/src/templates/plugin.main.js @@ -55,8 +55,7 @@ export default async (context) => { const { alwaysRedirect, fallbackLocale, - onlyOnNoPrefix, - onlyOnRoot, + redirectOn, useCookie, cookieKey, cookieDomain, @@ -181,9 +180,9 @@ export default async (context) => { } if (getLocaleFromRoute(route) === locale) { - // If "onlyOnRoot" or "onlyOnNoPrefix" is set and strategy is "prefix_and_default", prefer unprefixed route for + // If "redirectOn" is "all" and strategy is "prefix_and_default", prefer unprefixed route for // default locale. - if (!(onlyOnRoot || onlyOnNoPrefix) || locale !== options.defaultLocale || options.strategy !== Constants.STRATEGIES.PREFIX_AND_DEFAULT) { + if (redirectOn === Constants.REDIRECT_ON_OPTIONS.ALL || locale !== options.defaultLocale || options.strategy !== Constants.STRATEGIES.PREFIX_AND_DEFAULT) { return '' } } @@ -287,11 +286,11 @@ export default async (context) => { } if (options.strategy !== Constants.STRATEGIES.NO_PREFIX) { - if (onlyOnRoot) { + if (redirectOn === Constants.REDIRECT_ON_OPTIONS.ROOT) { if (route.path !== '/') { return '' } - } else if (onlyOnNoPrefix) { + } else if (redirectOn === Constants.REDIRECT_ON_OPTIONS.NO_PREFIX) { if (!alwaysRedirect && route.path.match(getLocalesRegex(options.localeCodes))) { return '' } diff --git a/test/browser.test.js b/test/browser.test.js index 9e99c76e6..ef7ad7cde 100644 --- a/test/browser.test.js +++ b/test/browser.test.js @@ -385,7 +385,7 @@ describe(`${browserString} (generate, no subFolders, trailingSlash === false)`, }) for (const target of ['server', 'static']) { - describe(`${browserString} (target ${target}, generate, prefix strategy, alwaysRedirect, onlyOnRoot)`, () => { + describe(`${browserString} (target ${target}, generate, prefix strategy, alwaysRedirect, redirectOn is root)`, () => { /** @type {import('playwright-chromium').ChromiumBrowser} */ let browser /** @type {import('playwright-chromium').Page} */ @@ -403,7 +403,7 @@ for (const target of ['server', 'static']) { detectBrowserLanguage: { alwaysRedirect: true, fallbackLocale: 'en', - onlyOnRoot: true + redirectOn: 'root' } } } @@ -968,7 +968,7 @@ describe(`${browserString} (SPA with router in hash mode)`, () => { }) }) -describe(`${browserString} (onlyOnRoot + alwaysRedirect + no_prefix)`, () => { +describe(`${browserString} (redirectOn is root + alwaysRedirect + no_prefix)`, () => { /** @type {Nuxt} */ let nuxt /** @type {import('playwright-chromium').ChromiumBrowser} */ @@ -982,7 +982,7 @@ describe(`${browserString} (onlyOnRoot + alwaysRedirect + no_prefix)`, () => { detectBrowserLanguage: { useCookie: false, alwaysRedirect: true, - onlyOnRoot: true + redirectOn: 'root' } } } @@ -998,13 +998,13 @@ describe(`${browserString} (onlyOnRoot + alwaysRedirect + no_prefix)`, () => { await nuxt.close() }) - test('onlyOnRoot does not affect locale detection on root path', async () => { + test('redirectOn is root does not affect locale detection on root path', async () => { const page = await browser.newPage({ locale: 'fr' }) await page.goto(url('/')) expect(await (await page.$('body'))?.textContent()).toContain('locale: fr') }) - test('onlyOnRoot does not affect locale detection on sub-path', async () => { + test('redirectOn is root does not affect locale detection on sub-path', async () => { const page = await browser.newPage({ locale: 'fr' }) await page.goto(url('/about')) expect(await (await page.$('#current-page'))?.textContent()).toContain('page: À propos') @@ -1059,7 +1059,7 @@ describe(`${browserString} (alwaysRedirect, prefix)`, () => { }) }) -describe(`${browserString} (onlyOnRoot + prefix_except_default)`, () => { +describe(`${browserString} (redirectOn is root + prefix_except_default)`, () => { /** @type {Nuxt} */ let nuxt /** @type {import('playwright-chromium').ChromiumBrowser} */ @@ -1071,7 +1071,7 @@ describe(`${browserString} (onlyOnRoot + prefix_except_default)`, () => { defaultLocale: 'en', strategy: 'prefix_except_default', detectBrowserLanguage: { - onlyOnRoot: true + redirectOn: 'root' } } } @@ -1131,7 +1131,7 @@ describe(`${browserString} (onlyOnRoot + prefix_except_default)`, () => { }) }) -describe(`${browserString} (onlyOnRoot + alwaysRedirect + prefix_except_default)`, () => { +describe(`${browserString} (redirectOn is root + alwaysRedirect + prefix_except_default)`, () => { /** @type {Nuxt} */ let nuxt /** @type {import('playwright-chromium').ChromiumBrowser} */ @@ -1144,7 +1144,7 @@ describe(`${browserString} (onlyOnRoot + alwaysRedirect + prefix_except_default) strategy: 'prefix_except_default', detectBrowserLanguage: { alwaysRedirect: true, - onlyOnRoot: true + redirectOn: 'root' } } } @@ -1176,7 +1176,7 @@ describe(`${browserString} (onlyOnRoot + alwaysRedirect + prefix_except_default) }) }) -describe(`${browserString} (onlyOnRoot + prefix_and_default)`, () => { +describe(`${browserString} (redirectOn is root + prefix_and_default)`, () => { /** @type {Nuxt} */ let nuxt /** @type {import('playwright-chromium').ChromiumBrowser} */ @@ -1188,7 +1188,7 @@ describe(`${browserString} (onlyOnRoot + prefix_and_default)`, () => { defaultLocale: 'en', strategy: 'prefix_and_default', detectBrowserLanguage: { - onlyOnRoot: true + redirectOn: 'root' } } } @@ -1219,7 +1219,7 @@ describe(`${browserString} (onlyOnRoot + prefix_and_default)`, () => { }) }) -describe(`${browserString} (onlyOnRoot + prefix)`, () => { +describe(`${browserString} (redirectOn is root + prefix)`, () => { /** @type {Nuxt} */ let nuxt /** @type {import('playwright-chromium').ChromiumBrowser} */ @@ -1231,7 +1231,7 @@ describe(`${browserString} (onlyOnRoot + prefix)`, () => { defaultLocale: 'en', strategy: 'prefix', detectBrowserLanguage: { - onlyOnRoot: true + redirectOn: 'root' } } } diff --git a/test/module.test.js b/test/module.test.js index bf90297e8..22a487525 100644 --- a/test/module.test.js +++ b/test/module.test.js @@ -1799,7 +1799,7 @@ describe('prefix + detectBrowserLanguage', () => { }) }) -describe('prefix + detectBrowserLanguage + onlyOnNoPrefix', () => { +describe('prefix + detectBrowserLanguage + redirectOn is no_prefix', () => { /** @type {Nuxt} */ let nuxt @@ -1810,7 +1810,7 @@ describe('prefix + detectBrowserLanguage + onlyOnNoPrefix', () => { strategy: 'prefix', detectBrowserLanguage: { useCookie: true, - onlyOnNoPrefix: true + redirectOn: 'no prefix' } } } diff --git a/types/index.d.ts b/types/index.d.ts index a2a7d38d7..f418bd46d 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -5,6 +5,7 @@ import './vue' export { Locale } export type Strategies = 'no_prefix' | 'prefix_except_default' | 'prefix' | 'prefix_and_default' export type Directions = 'ltr' | 'rtl' | 'auto' +export type RedirectOnOptions = 'all' | 'root' | 'no prefix' export interface LocaleObject extends Record { code: Locale @@ -21,8 +22,7 @@ export interface DetectBrowserLanguageOptions { cookieKey?: string cookieSecure?: boolean fallbackLocale?: Locale | null - onlyOnNoPrefix?: boolean - onlyOnRoot?: boolean + redirectOn?: RedirectOnOptions useCookie?: boolean }