UNPKG

@nuxtjs/i18n

Version:

Internationalization for Nuxt

179 lines (178 loc) 7.94 kB
import { computed, isRef, ref, watch } from "vue"; import { createI18n } from "vue-i18n"; import { defineNuxtPlugin, useNuxtApp } from "#imports"; import { localeCodes, vueI18nConfigs, hasPages, localeLoaders, parallelPlugin, normalizedLocales } from "#build/i18n.options.mjs"; import { loadVueI18nOptions, loadLocale } from "../messages.js"; import { loadAndSetLocale, detectRedirect, navigate, extendBaseUrl, createNuxtI18nDev } from "../utils.js"; import { getLocaleCookie, createI18nCookie, runtimeDetectBrowserLanguage, wrapComposable, getBrowserLocale } from "../internal.js"; import { createLocaleFromRouteGetter } from "../routing/utils.js"; import { extendI18n } from "../routing/i18n.js"; import { createLogger } from "#nuxt-i18n/logger"; import { getI18nTarget } from "../compatibility.js"; import { resolveRoute } from "../routing/routing.js"; import { localeHead } from "../routing/head.js"; import { useLocalePath, useLocaleRoute, useRouteBaseName, useSwitchLocalePath, useLocaleLocation } from "../composables/index.js"; import { getDefaultLocaleForDomain, setupMultiDomainLocales } from "../domain.js"; export default defineNuxtPlugin({ name: "i18n:plugin", parallel: parallelPlugin, async setup(_nuxt) { Object.defineProperty(_nuxt.versions, "nuxtI18n", { get: () => __NUXT_I18N_VERSION__ }); const logger = /* @__PURE__ */ createLogger("plugin:i18n"); const nuxt = useNuxtApp(); const _runtimeI18n = nuxt.$config.public.i18n; const defaultLocaleDomain = getDefaultLocaleForDomain(_runtimeI18n); setupMultiDomainLocales(_runtimeI18n, defaultLocaleDomain); nuxt.$config.public.i18n.defaultLocale = defaultLocaleDomain; const runtimeI18n = { ..._runtimeI18n, defaultLocale: defaultLocaleDomain, baseUrl: extendBaseUrl(nuxt) }; __DEBUG__ && logger.log("defaultLocale on setup", runtimeI18n.defaultLocale); const vueI18nOptions = await loadVueI18nOptions(vueI18nConfigs, useNuxtApp()); vueI18nOptions.messages ||= {}; vueI18nOptions.fallbackLocale ??= false; if (defaultLocaleDomain) { vueI18nOptions.locale = defaultLocaleDomain; } for (const l of localeCodes) { vueI18nOptions.messages[l] ??= {}; } const i18n = createI18n(vueI18nOptions); nuxt._vueI18n = i18n; i18n.__localeFromRoute = createLocaleFromRouteGetter(); i18n.__firstAccess = true; i18n.__setLocale = (locale) => { const i = getI18nTarget(i18n); if (isRef(i.locale)) { i.locale.value = locale; } else { i.locale = locale; } }; if (import.meta.dev) { nuxt._nuxtI18nDev = createNuxtI18nDev(); } const localeCookie = createI18nCookie(); const detectBrowserOptions = runtimeDetectBrowserLanguage(); extendI18n(i18n, { extendComposer(composer) { const _locales = ref(runtimeI18n.locales); composer.locales = computed(() => _locales.value); const _localeCodes = ref(localeCodes); composer.localeCodes = computed(() => _localeCodes.value); const _baseUrl = ref(runtimeI18n.baseUrl()); composer.baseUrl = computed(() => _baseUrl.value); if (import.meta.client) { watch(composer.locale, () => _baseUrl.value = runtimeI18n.baseUrl()); } composer.strategy = runtimeI18n.strategy; composer.localeProperties = computed( () => normalizedLocales.find((l) => l.code === composer.locale.value) || { code: composer.locale.value } ); composer.setLocale = async (locale) => { await loadAndSetLocale(locale, i18n.__firstAccess); if (composer.strategy === "no_prefix" || !hasPages) { await composer.loadLocaleMessages(locale); i18n.__setLocale(locale); return; } const route = nuxt.$router.currentRoute.value; const redirectPath = await nuxt.runWithContext( () => detectRedirect({ to: route, locale, routeLocale: i18n.__localeFromRoute(route) }) ); __DEBUG__ && logger.log("redirectPath on setLocale", redirectPath); await nuxt.runWithContext(() => navigate({ nuxt, redirectPath, locale, route }, true)); }; composer.loadLocaleMessages = async (locale) => await loadLocale(locale, localeLoaders, composer.mergeLocaleMessage.bind(composer), nuxt); composer.differentDomains = runtimeI18n.differentDomains; composer.defaultLocale = runtimeI18n.defaultLocale; composer.getBrowserLocale = () => getBrowserLocale(); composer.getLocaleCookie = () => getLocaleCookie(localeCookie, detectBrowserOptions, composer.defaultLocale); composer.setLocaleCookie = (locale) => { if (!detectBrowserOptions || !detectBrowserOptions.useCookie) return; localeCookie.value = locale; }; composer.onBeforeLanguageSwitch = (oldLocale, newLocale, initialSetup, context) => nuxt.callHook("i18n:beforeLocaleSwitch", { oldLocale, newLocale, initialSetup, context }); composer.onLanguageSwitched = (oldLocale, newLocale) => nuxt.callHook("i18n:localeSwitched", { oldLocale, newLocale }); composer.finalizePendingLocaleChange = async () => { if (!i18n.__pendingLocale) return; i18n.__setLocale(i18n.__pendingLocale); i18n.__resolvePendingLocalePromise?.(); i18n.__pendingLocale = void 0; }; composer.waitForPendingLocaleChange = async () => { if (i18n.__pendingLocale && i18n.__pendingLocalePromise) { await i18n.__pendingLocalePromise; } }; }, extendComposerInstance(instance, c) { const props = [ ["locales", () => c.locales], ["localeCodes", () => c.localeCodes], ["baseUrl", () => c.baseUrl], ["strategy", () => c.strategy], ["localeProperties", () => c.localeProperties], ["setLocale", () => async (locale) => Reflect.apply(c.setLocale, c, [locale])], ["loadLocaleMessages", () => async (locale) => Reflect.apply(c.loadLocaleMessages, c, [locale])], ["differentDomains", () => c.differentDomains], ["defaultLocale", () => c.defaultLocale], ["getBrowserLocale", () => () => Reflect.apply(c.getBrowserLocale, c, [])], ["getLocaleCookie", () => () => Reflect.apply(c.getLocaleCookie, c, [])], ["setLocaleCookie", () => (locale) => Reflect.apply(c.setLocaleCookie, c, [locale])], [ "onBeforeLanguageSwitch", () => (oldLocale, newLocale, initialSetup, context) => Reflect.apply(c.onBeforeLanguageSwitch, c, [oldLocale, newLocale, initialSetup, context]) ], [ "onLanguageSwitched", () => (oldLocale, newLocale) => Reflect.apply(c.onLanguageSwitched, c, [oldLocale, newLocale]) ], ["finalizePendingLocaleChange", () => () => Reflect.apply(c.finalizePendingLocaleChange, c, [])], ["waitForPendingLocaleChange", () => () => Reflect.apply(c.waitForPendingLocaleChange, c, [])] ]; for (const [key, get] of props) { Object.defineProperty(instance, key, { get }); } } }); nuxt.vueApp.use(i18n); Object.defineProperty(nuxt, "$i18n", { get: () => getI18nTarget(i18n) }); return { provide: { /** * TODO: remove type assertions while type narrowing based on generated types */ localeHead: wrapComposable(localeHead), localePath: useLocalePath(), localeRoute: useLocaleRoute(), getRouteBaseName: useRouteBaseName(), switchLocalePath: useSwitchLocalePath(), // TODO: remove in v10 resolveRoute: wrapComposable(resolveRoute), // TODO: remove in v10 localeLocation: useLocaleLocation() } }; } });