nuxt-i18n-micro
Version:
Nuxt I18n Micro is a lightweight, high-performance internationalization module for Nuxt, designed to handle multi-language support with minimal overhead, fast build times, and efficient runtime performance.
149 lines (148 loc) • 5.43 kB
JavaScript
import { isNoPrefixStrategy } from "@i18n-micro/core";
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
import { useState } from "#app";
import { plural } from "#build/i18n.plural.mjs";
import { createI18nStrategy, getI18nConfig } from "#build/i18n.strategy.mjs";
import { createError, defineNuxtPlugin, navigateTo, useRouter, useRuntimeConfig } from "#imports";
import { useI18nHead } from "../composables/useI18nHead.js";
import { useI18nLocale } from "../composables/useI18nLocale.js";
import { createNuxtI18nPluginApi, NuxtI18n, NuxtTranslationLoader } from "../utils/nuxt-i18n.js";
import { translationStorage } from "../utils/storage.js";
const isDev = process.env.NODE_ENV !== "production";
export default defineNuxtPlugin(async (nuxtApp) => {
const router = useRouter();
const i18nStrategy = createI18nStrategy(router);
const runtimeConfig = useRuntimeConfig();
const i18nConfig = resolveI18nConfigWithRuntimeOverrides(
getI18nConfig(),
runtimeConfig.public
);
translationStorage.configure({
maxSize: i18nConfig.cacheMaxSize ?? 0,
ttl: i18nConfig.cacheTtl ?? 0
});
const { locale: localeState, setLocale, getLocale, getEffectiveLocale, resolveInitialLocale, isValidLocale } = useI18nLocale();
const i18nRouteParams = useState("i18n-route-params", () => ({}));
const { resetPageHead } = useI18nHead();
const customMissingHandler = useState("i18n-missing-handler", () => null);
const ssrChunks = useState("i18n-ssr-chunks", () => ({}));
const i18n = new NuxtI18n({
plural,
missingWarn: i18nConfig.missingWarn ?? true,
getCustomMissingHandler: () => customMissingHandler.value
});
const getCurrentLocale = (route) => {
const r = route ?? router.currentRoute.value;
return i18nStrategy.getCurrentLocale(r, getLocale() ?? null);
};
const getPluginRouteName = (route, locale) => {
return i18nStrategy.getPluginRouteName(route, locale);
};
i18n.setRouteContextResolver((route) => {
const resolvedRoute = route ?? router.currentRoute.value;
const locale = getCurrentLocale(resolvedRoute);
return {
locale,
routeName: getPluginRouteName(resolvedRoute, locale)
};
});
nuxtApp.hook("page:transition:finish", () => {
i18n.finishTransition();
});
const loadOptions = {
apiBaseUrl: i18nConfig.apiBaseUrl ?? "_locales",
baseURL: runtimeConfig.app.baseURL,
apiBaseClientHost: i18nConfig.apiBaseClientHost,
dateBuild: i18nConfig.dateBuild,
routesLocaleLinks: i18nConfig.routesLocaleLinks
};
if (import.meta.client && Object.keys(ssrChunks.value).length > 0) {
translationStorage.seedFromSsrChunks(ssrChunks.value);
}
const loader = new NuxtTranslationLoader({
i18n,
loadOptions,
getSsrChunks: () => ssrChunks.value,
setSsrChunk: (cacheKey, data) => {
ssrChunks.value = { ...ssrChunks.value, [cacheKey]: data };
},
isDev
});
const serverLocale = import.meta.server ? nuxtApp.ssrContext?.event?.context?.i18n?.locale : void 0;
const initialLocale = resolveInitialLocale({
route: router.currentRoute.value,
serverLocale,
getLocaleFromRoute: (r) => getCurrentLocale(r)
});
const initialRouteName = getPluginRouteName(router.currentRoute.value, initialLocale);
try {
await loader.switchContext(initialLocale, initialRouteName);
} catch (e) {
if (isDev) console.error("[i18n] Initial load error:", e);
throw createError({ statusCode: 404, statusMessage: "Page Not Found" });
}
const getRouteName = (route, locale) => {
const selectedRoute = route ?? router.currentRoute.value;
const selectedLocale = locale ?? getCurrentLocale(selectedRoute);
return i18nStrategy.getRouteBaseName(selectedRoute, selectedLocale) ?? "";
};
const {
helper,
switchContext,
provide: provideApi
} = createNuxtI18nPluginApi({
i18n,
loader,
i18nStrategy,
i18nConfig,
router,
getCurrentLocale,
getEffectiveLocale,
getPluginRouteName,
getRouteName,
i18nRouteParams,
setLocale,
isValidLocale,
navigateTo,
setMissingHandler: (handler) => {
customMissingHandler.value = handler;
}
});
router.beforeEach(async (to, from) => {
if (to.name !== from.name) {
i18nRouteParams.value = {};
resetPageHead();
}
const shouldSwitchContext = to.path !== from.path || isNoPrefixStrategy(i18nConfig.strategy);
if (!shouldSwitchContext) {
return;
}
try {
const targetLocale = getEffectiveLocale(to, (r) => getCurrentLocale(r));
const targetRouteName = getPluginRouteName(to, targetLocale);
if (targetLocale !== i18n.getCurrentLocale() || targetRouteName !== i18n.getCurrentRouteName()) {
await switchContext(targetLocale, targetRouteName);
}
if (targetLocale && isValidLocale(targetLocale) && localeState.value !== targetLocale) {
setLocale(targetLocale);
}
} catch (e) {
if (isDev) console.error("[i18n] Navigation error:", e);
}
return;
});
const provideData = {
...provideApi,
helper,
i18n: void 0,
__micro: true
};
const $provideData = Object.fromEntries(Object.entries(provideData).map(([key, value]) => [`$${key}`, value]));
provideData.i18n = { ...provideData, ...$provideData };
return {
provide: {
...provideData,
getI18nConfig: () => i18nConfig
}
};
});