UNPKG

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
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 } }; });