Skip to content

Commit

Permalink
refactor: extract duplicate detection logic into function
Browse files Browse the repository at this point in the history
  • Loading branch information
BobbieGoede committed Dec 13, 2024
1 parent e5cfda7 commit a7d298f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 69 deletions.
2 changes: 1 addition & 1 deletion src/runtime/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function loadVueI18nOptions(
for (const configFile of vueI18nConfigs) {
const { default: resolver } = await configFile()

const resolved = isFunction(resolver) ? await nuxt.runWithContext(async () => await resolver()) : resolver
const resolved = isFunction(resolver) ? await nuxt.runWithContext(() => resolver()) : resolver

deepCopy(resolved, vueI18nOptions)
}
Expand Down
116 changes: 48 additions & 68 deletions src/runtime/plugins/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { computed, ref, watch } from 'vue'
import { createI18n } from 'vue-i18n'
import { defineNuxtPlugin, useRoute, addRouteMiddleware, defineNuxtRouteMiddleware, useNuxtApp } from '#imports'
import { defineNuxtPlugin, addRouteMiddleware, defineNuxtRouteMiddleware, useNuxtApp } from '#imports'
import {
localeCodes,
vueI18nConfigs,
Expand Down Expand Up @@ -32,6 +32,7 @@ import type { Locale, I18nOptions } from 'vue-i18n'
import type { NuxtApp } from '#app'
import type { LocaleObject } from '#internal-i18n-types'
import type { I18nPublicRuntimeConfig } from '#internal-i18n-types'
import type { CompatRoute } from '../types'

// from https://github.com/nuxt/nuxt/blob/2466af53b0331cdb8b17c2c3b08675c5985deaf3/packages/nuxt/src/core/templates.ts#L152
type Decorate<T extends Record<string, unknown>> = { [K in keyof T as K extends string ? `$${K}` : never]: T[K] }
Expand All @@ -47,14 +48,14 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
parallel: parallelPlugin,
async setup(nuxt) {
const logger = /*#__PURE__*/ createLogger('plugin:i18n')
const nuxtContext = nuxt as unknown as NuxtApp
const nuxtApp = nuxt as unknown as NuxtApp

const defaultLocaleDomain = getDefaultLocaleForDomain(nuxtContext)
setupMultiDomainLocales(nuxtContext, defaultLocaleDomain)
const defaultLocaleDomain = getDefaultLocaleForDomain(nuxtApp)
setupMultiDomainLocales(nuxtApp, defaultLocaleDomain)

// Fresh copy per request to prevent reusing mutated options
const runtimeI18n = {
...(nuxtContext.$config.public.i18n as I18nPublicRuntimeConfig),
...(nuxtApp.$config.public.i18n as I18nPublicRuntimeConfig),
defaultLocale: defaultLocaleDomain
}
// @ts-expect-error type incompatible
Expand All @@ -76,12 +77,11 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
// create i18n instance
const i18n = createI18n({ ...vueI18nOptions, locale: 'en' })

let firstAccessHandled = false
let firstAccess = true

// extend i18n instance
extendI18n(i18n, {
extendComposer(composer) {
const route = useRoute()
const _locales = ref<Locale[] | LocaleObject[]>(runtimeI18n.locales)
const _localeCodes = ref<Locale[]>(localeCodes)
const _baseUrl = ref<string>('')
Expand All @@ -95,20 +95,20 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
watch(
composer.locale,
() => {
_baseUrl.value = resolveBaseUrl(runtimeI18n.baseUrl!, nuxtContext)
_baseUrl.value = resolveBaseUrl(runtimeI18n.baseUrl!, nuxtApp)
},
{ immediate: true }
)
} else {
_baseUrl.value = resolveBaseUrl(runtimeI18n.baseUrl!, nuxtContext)
_baseUrl.value = resolveBaseUrl(runtimeI18n.baseUrl!, nuxtApp)
}

composer.strategy = runtimeI18n.strategy
composer.localeProperties = computed(
() => normalizedLocales.find(l => l.code === composer.locale.value) || { code: composer.locale.value }
)
composer.setLocale = async (locale: string) => {
await loadAndSetLocale(locale, i18n, runtimeI18n, !firstAccessHandled)
await loadAndSetLocale(locale, i18n, runtimeI18n, firstAccess)

if (!hasPages) {
return
Expand All @@ -120,9 +120,10 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
return
}

const redirectPath = await nuxtContext.runWithContext(() =>
const route = nuxtApp.$router.currentRoute.value
const redirectPath = await nuxtApp.runWithContext(() =>
detectRedirect({
route: { to: nuxtContext.$router.currentRoute.value },
route: { to: route },
locale,
routeLocale: getLocaleFromRoute(route),
strategy: runtimeI18n.strategy
Expand All @@ -131,18 +132,8 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({

__DEBUG__ && logger.log('redirectPath on setLocale', redirectPath)

await nuxtContext.runWithContext(
async () =>
await navigate(
{
nuxtApp: nuxtContext,
i18n,
redirectPath,
locale: locale,
route: nuxtContext.$router.currentRoute.value
},
{ enableNavigate: true }
)
await nuxtApp.runWithContext(() =>
navigate({ nuxtApp, i18n, redirectPath, locale: locale, route }, { enableNavigate: true })
)
}
composer.loadLocaleMessages = async (locale: string) => {
Expand Down Expand Up @@ -248,27 +239,40 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
nuxt.vueApp.use(i18n) // TODO: should implement `{ inject: false } via `nuxtjs/i18n` configuration

// inject for nuxt helpers
injectNuxtHelpers(nuxtContext, i18n)

// router is enabled and project has pages
if (!hasPages) {
const currentRoute = nuxtContext.$router.currentRoute
const detected = detectLocale(
currentRoute.value,
getLocaleFromRoute(currentRoute.value),
undefined,
injectNuxtHelpers(nuxtApp, i18n)

async function handleRouteDetect(to: CompatRoute) {
const routeLocale = getLocaleFromRoute(to)
let detected = detectLocale(
to,
routeLocale,
getLocale(i18n),
{
ssg: 'normal',
callType: 'setup',
firstAccess: true,
ssg: isSSG && firstAccess && runtimeI18n.strategy === 'no_prefix' ? 'ssg_ignore' : 'normal',
callType: !hasPages ? 'setup' : 'routing',
firstAccess,
localeCookie: getLocaleCookie(localeCookie, _detectBrowserLanguage, runtimeI18n.defaultLocale)
},
runtimeI18n
)
__DEBUG__ && logger.log('detect locale', detected)

if (firstAccess) {
setLocaleProperty(i18n, detected)
await getI18nTarget(i18n).loadLocaleMessages(detected)
}

await loadAndSetLocale(detected, i18n, runtimeI18n, true)
await getI18nTarget(i18n).loadLocaleMessages(detected)
const mod = await nuxtApp.runWithContext(() => loadAndSetLocale(detected, i18n, runtimeI18n, firstAccess))
if (mod) {
detected = getLocale(i18n)
}

return detected
}

// router is enabled and project has pages
if (!hasPages) {
await handleRouteDetect(nuxtApp.$router.currentRoute.value)
return
}

Expand All @@ -278,42 +282,18 @@ export default defineNuxtPlugin<NuxtI18nPluginInjections>({
defineNuxtRouteMiddleware(async (to, from) => {
__DEBUG__ && logger.log('locale-changing middleware', to, from)

const routeLocale = getLocaleFromRoute(to)
let locale = detectLocale(
to,
routeLocale,
getLocale(i18n),
{
ssg: isSSG && !firstAccessHandled && runtimeI18n.strategy === 'no_prefix' ? 'ssg_ignore' : 'normal',
callType: 'routing',
firstAccess: !firstAccessHandled,
localeCookie: getLocaleCookie(localeCookie, _detectBrowserLanguage, runtimeI18n.defaultLocale)
},
runtimeI18n
)
__DEBUG__ && logger.log('detect locale', locale)

if (!firstAccessHandled) {
setLocaleProperty(i18n, locale)
await getI18nTarget(i18n).loadLocaleMessages(locale)
}
const locale = await nuxtApp.runWithContext(() => handleRouteDetect(to))

const _modified = await loadAndSetLocale(locale, i18n, runtimeI18n, !firstAccessHandled)
if (_modified) {
locale = getLocale(i18n)
}

const redirectPath = await nuxtContext.runWithContext(() =>
detectRedirect({ route: { to, from }, locale: locale, routeLocale, strategy: runtimeI18n.strategy }, true)
const routeLocale = getLocaleFromRoute(to)
const redirectPath = await nuxtApp.runWithContext(() =>
detectRedirect({ route: { to, from }, locale, routeLocale, strategy: runtimeI18n.strategy }, true)
)

firstAccessHandled ||= true
firstAccess = false

__DEBUG__ && logger.log('redirectPath on locale-changing middleware', redirectPath)

return await nuxtContext.runWithContext(
async () => await navigate({ nuxtApp: nuxtContext, i18n, redirectPath, locale: locale, route: to })
)
return await nuxtApp.runWithContext(() => navigate({ nuxtApp, i18n, redirectPath, locale, route: to }))
}),
{ global: true }
)
Expand Down

0 comments on commit a7d298f

Please sign in to comment.