Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: alwaysRedirect in detectBrowserLanguage #1668

Merged
merged 1 commit into from
Nov 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export default defineNuxtConfig({
defaultLocale: 'en',
// strategy: 'no_prefix',
// strategy: 'prefix',
strategy: 'prefix_and_default',
// rootRedirect: '/ja/about-ja',
// strategy: 'prefix_and_default',
// parsePages: false,
dynamicRouteParams: true,
pages: {
Expand All @@ -62,15 +62,17 @@ export default defineNuxtConfig({
}
},
// differentDomains: true,
skipSettingLocaleOnNavigate: true,
// skipSettingLocaleOnNavigate: true,
detectBrowserLanguage: false,
// detectBrowserLanguage: {
// useCookie: true,
// alwaysRedirect: false
// // cookieKey: 'i18n_redirected',
// // cookieKey: 'my_custom_cookie_name',
// // redirectOn: 'root'
// },
/*
detectBrowserLanguage: {
useCookie: true,
// alwaysRedirect: true,
cookieKey: 'i18n_redirected',
// cookieKey: 'my_custom_cookie_name',
redirectOn: 'root'
},
//*/
onBeforeLanguageSwitch: (oldLocale: string, newLocale: string, initial: boolean, nuxt: NuxtApp) => {
console.log('onBeforeLanguageSwitch', oldLocale, newLocale, initial)
},
Expand Down
3 changes: 3 additions & 0 deletions playground/pages/category/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ definePageMeta({
<span v-for="locale in availableLocales" :key="locale.code">
<NuxtLink :to="switchLocalePath(locale.code) || ''">{{ locale.name }}</NuxtLink> |
</span>
<i18n-t keypath="hello">
<template #name>nuxtjs/i18n</template>
</i18n-t>
</nav>
</div>
</template>
90 changes: 68 additions & 22 deletions src/runtime/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,66 +251,112 @@ export function setLocaleCookie(
}
}

export type DetectBrowserLanguageNotDetectReason =
| 'unknown'
| 'not_found_match'
| 'not_redirect_on_root'
| 'not_redirect_on_no_prefix'
export type DetectBrowserLanguageFrom = 'unknown' | 'cookie' | 'navigator_or_header' | 'fallback'
export type DetectBrowserLanguageFromResult = {
locale: string
stat: boolean
reason?: DetectBrowserLanguageNotDetectReason
from?: DetectBrowserLanguageFrom
}

export function detectBrowserLanguage<Context extends NuxtApp = NuxtApp>(
route: string | Route | RouteLocationNormalized | RouteLocationNormalizedLoaded,
context: any,
nuxtI18nOptions: DeepRequired<NuxtI18nOptions<Context>>,
nuxtI18nInternalOptions: DeepRequired<NuxtI18nInternalOptions>,
localeCodes: string[] = [],
locale: Locale = ''
): string {
__DEBUG__ && console.log('detectBrowserLanguage: locale params', locale)
): DetectBrowserLanguageFromResult {
const { strategy } = nuxtI18nOptions
const { redirectOn, alwaysRedirect, useCookie, fallbackLocale } =
nuxtI18nOptions.detectBrowserLanguage as DetectBrowserLanguageOptions

const path = isString(route) ? route : route.path
__DEBUG__ && console.log('detectBrowserLanguage check route, strategy and redirectOn', path, strategy, redirectOn)
__DEBUG__ &&
console.log(
'detectBrowserLanguage: (path, strategy, alwaysRedirect, redirectOn, locale) -',
path,
strategy,
alwaysRedirect,
redirectOn,
locale
)
if (strategy !== 'no_prefix') {
if (redirectOn === 'root') {
if (path !== '/') {
__DEBUG__ && console.log('detectBrowserLanguage: not root')
return ''
return { locale: '', stat: false, reason: 'not_redirect_on_root' }
}
} else if (redirectOn === 'no prefix') {
if (!alwaysRedirect && path.match(getLocalesRegex(localeCodes as string[]))) {
__DEBUG__ && console.log('detectBrowserLanguage: no prefix')
return ''
return { locale: '', stat: false, reason: 'not_redirect_on_no_prefix' }
}
}
}

const cookieLocale = getLocaleCookie(context, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
__DEBUG__ && console.log('detectBrowserLanguage cookieLocale', cookieLocale)
__DEBUG__ && console.log('detectBrowserLanguage browserLocale', getBrowserLocale(nuxtI18nInternalOptions, context))
let localeFrom: DetectBrowserLanguageFrom = 'unknown'
let cookieLocale: string | undefined
let matchedLocale: string | undefined

let matchedLocale
if (useCookie && (matchedLocale = cookieLocale)) {
// get preferred language from cookie if present and enabled
} else {
// try to get locale from either navigator or header detection
// get preferred language from cookie if present and enabled
if (useCookie) {
matchedLocale = cookieLocale = getLocaleCookie(context, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
localeFrom = 'cookie'
__DEBUG__ && console.log('detectBrowserLanguage: cookieLocale', cookieLocale)
}
// try to get locale from either navigator or header detection
if (!matchedLocale) {
matchedLocale = getBrowserLocale(nuxtI18nInternalOptions, context)
localeFrom = 'navigator_or_header'
__DEBUG__ && console.log('detectBrowserLanguage: browserLocale', matchedLocale)
}
__DEBUG__ && console.log('detectBrowserLanguage matchedLocale', matchedLocale)

__DEBUG__ &&
console.log(
'detectBrowserLanguage: (matchedLocale, cookieLocale, localeFrom) -',
matchedLocale,
cookieLocale,
localeFrom
)

// set fallback locale if that is not matched locale
const finalLocale = matchedLocale || fallbackLocale
if (!matchedLocale && fallbackLocale) {
localeFrom = 'fallback'
}
__DEBUG__ &&
console.log(
'detectBrowserLanguage: first finaleLocale (finaleLocale, lcoaleForm) -',
finalLocale,
cookieLocale,
localeFrom
)

const vueI18nLocale = locale || (nuxtI18nOptions.vueI18n as I18nOptions).locale
__DEBUG__ && console.log('detectBrowserLanguage first finaleLocale', finalLocale)
__DEBUG__ && console.log('detectBrowserLanguage vueI18nLocale', vueI18nLocale)
__DEBUG__ && console.log('detectBrowserLanguage: vueI18nLocale', vueI18nLocale)

// handle cookie option to prevent multiple redirections
if (finalLocale && (!useCookie || alwaysRedirect || !cookieLocale)) {
if (strategy === 'no_prefix') {
return finalLocale
return { locale: finalLocale, stat: true, from: localeFrom }
} else {
if (finalLocale !== vueI18nLocale && path !== '/') {
__DEBUG__ && console.log('detectBrowserLanguage finalLocale !== vueI18nLocale', finalLocale)
return finalLocale
if (finalLocale !== vueI18nLocale /* && path !== '/'*/) {
__DEBUG__ && console.log('detectBrowserLanguage: finalLocale !== vueI18nLocale', finalLocale)
return { locale: finalLocale, stat: true, from: localeFrom }
} else {
if (alwaysRedirect && path === '/') {
return { locale: finalLocale, stat: true, from: localeFrom }
}
}
}
}

return ''
return { locale: '', stat: false, reason: 'not_found_match' }
}

export function getHost() {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default defineNuxtPlugin(async nuxt => {
normalizedLocales,
localeCodes
)
__DEBUG__ && console.log('first detect locale', initialLocale)
__DEBUG__ && console.log('first detect initial locale', initialLocale)

// load initial vue-i18n locale messages
vueI18nOptions.messages = await loadInitialMessages(nuxtContext, vueI18nOptions.messages, {
Expand Down
29 changes: 20 additions & 9 deletions src/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import type {
import type { NuxtApp } from '#imports'
import type { I18n, Locale, FallbackLocale, LocaleMessages, DefineLocaleMessage } from 'vue-i18n'
import type { NuxtI18nOptions, DetectBrowserLanguageOptions, RootRedirectOptions } from '#build/i18n.options.mjs'
import type { DetectBrowserLanguageFromResult } from '#build/i18n.internal.mjs'
import type { DeepRequired } from 'ts-essentials'

export function setCookieLocale(i18n: I18n, locale: Locale) {
Expand Down Expand Up @@ -217,14 +218,23 @@ export function detectLocale<Context extends NuxtApp = NuxtApp>(
const { strategy, defaultLocale, differentDomains } = nuxtI18nOptions

const initialLocale = isFunction(initialLocaleLoader) ? initialLocaleLoader() : initialLocaleLoader
__DEBUG__ && console.log('detectLocale: initialLocale -> ', initialLocale)
const browserLocale = nuxtI18nOptions.detectBrowserLanguage
__DEBUG__ && console.log('detectLocale: initialLocale -', initialLocale)

// prettier-ignore
const { locale: browserLocale, stat, reason, from } = nuxtI18nOptions.detectBrowserLanguage
? detectBrowserLanguage(route, context, nuxtI18nOptions, nuxtI18nInternalOptions, localeCodes, initialLocale)
: ''
__DEBUG__ && console.log('detectLocale: browserLocale -> ', browserLocale)
: { locale: '', stat: false, reason: 'unknown', from: 'unknown' } as DetectBrowserLanguageFromResult
__DEBUG__ &&
console.log(
'detectLocale: detectBrowserLanguage (browserLocale, stat, reason, from) -',
browserLocale,
stat,
reason,
from
)

let finalLocale: string | undefined = browserLocale
__DEBUG__ && console.log('detectLocale: first check finaleLocale on stragety', strategy, finalLocale)
__DEBUG__ && console.log('detectLocale: finaleLocale first (finaleLocale, strategy) -', finalLocale, strategy)
if (!finalLocale) {
if (differentDomains) {
finalLocale = getLocaleDomain(normalizedLocales)
Expand All @@ -235,19 +245,20 @@ export function detectLocale<Context extends NuxtApp = NuxtApp>(

__DEBUG__ &&
console.log(
'detectLocale: finaleLocale on detectBrowserLanguage',
nuxtI18nOptions.detectBrowserLanguage,
finalLocale
'detectLocale: finaleLocale second (finaleLocale, detectBrowserLanguage) -',
finalLocale,
nuxtI18nOptions.detectBrowserLanguage
)
if (!finalLocale && nuxtI18nOptions.detectBrowserLanguage && nuxtI18nOptions.detectBrowserLanguage.useCookie) {
finalLocale = getLocaleCookie(context, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
}

__DEBUG__ && console.log('detectLocale: finaleLocale on defailtLocale', defaultLocale, finalLocale)
__DEBUG__ && console.log('detectLocale: finalLocale last (finalLocale, defaultLocale) -', finalLocale, defaultLocale)
if (!finalLocale) {
finalLocale = defaultLocale || ''
}

__DEBUG__ && console.log('detectLocale: finalLocale -', finalLocale)
return finalLocale
}

Expand Down