@nuxtjs/i18n
Version:
Internationalization for Nuxt
179 lines (178 loc) • 7.94 kB
JavaScript
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()
}
};
}
});