UNPKG

@nuxtjs/i18n

Version:

Internationalization for Nuxt

123 lines (122 loc) 5.29 kB
import { isRef, unref } from "vue"; import { useState, useCookie, useRequestURL } from "#imports"; import { localeLoaders } from "#build/i18n-options.mjs"; import { getLocaleMessagesMergedCached } from "./shared/messages.js"; import { createBaseUrlGetter, createComposableContext } from "./utils.js"; import { getI18nTarget } from "./compatibility.js"; import { domainFromLocale } from "./shared/domain.js"; import { isSupportedLocale } from "./shared/locales.js"; import { resolveRootRedirect, useI18nDetection, useRuntimeI18n } from "./shared/utils.js"; import { joinURL } from "ufo"; import { isString } from "@intlify/shared"; export const useLocaleConfigs = () => useState( "i18n:cached-locale-configs", () => void 0 ); export const useResolvedLocale = () => useState("i18n:resolved-locale", () => ""); function useI18nCookie({ cookieCrossOrigin, cookieDomain, cookieSecure, cookieKey }) { const date = /* @__PURE__ */ new Date(); return useCookie(cookieKey || __DEFAULT_COOKIE_KEY__, { path: "/", readonly: false, expires: new Date(date.setDate(date.getDate() + 365)), sameSite: cookieCrossOrigin ? "none" : "lax", domain: cookieDomain || void 0, secure: cookieCrossOrigin || cookieSecure }); } export function createNuxtI18nContext(nuxt, vueI18n, defaultLocale) { const i18n = getI18nTarget(vueI18n); const runtimeI18n = useRuntimeI18n(nuxt); const detectConfig = useI18nDetection(nuxt); const serverLocaleConfigs = useLocaleConfigs(); const localeCookie = useI18nCookie(detectConfig); const getLocaleConfig = (locale) => serverLocaleConfigs.value[locale]; const getDomainFromLocale = (locale) => domainFromLocale(runtimeI18n.domainLocales, useRequestURL({ xForwardedHost: true }), locale); const baseUrl = createBaseUrlGetter(nuxt, runtimeI18n.baseUrl, defaultLocale, getDomainFromLocale); const resolvedLocale = useResolvedLocale(); if (__I18N_SERVER_REDIRECT__ && import.meta.server && nuxt.ssrContext?.event?.context?.nuxtI18n?.detectLocale) { resolvedLocale.value = nuxt.ssrContext.event.context.nuxtI18n.detectLocale; } const loadMessagesFromClient = async (locale) => { const locales = getLocaleConfig(locale)?.fallbacks ?? []; if (!locales.includes(locale)) locales.push(locale); for (const k of locales) { const msg = await nuxt.runWithContext(() => getLocaleMessagesMergedCached(k, localeLoaders[k])); i18n.mergeLocaleMessage(k, msg); } }; const loadMessagesFromServer = async (locale) => { if (locale in localeLoaders === false) return; const headers = getLocaleConfig(locale)?.cacheable ? {} : { "Cache-Control": "no-cache" }; const messages = await $fetch(`/_i18n/${__I18N_HASH__}/${locale}/messages.json`, { headers }); for (const k of Object.keys(messages)) { i18n.mergeLocaleMessage(k, messages[k]); } }; const ctx = { vueI18n, initial: true, preloaded: false, config: runtimeI18n, rootRedirect: resolveRootRedirect(runtimeI18n.rootRedirect), redirectStatusCode: runtimeI18n.redirectStatusCode ?? 302, dynamicResourcesSSG: !__IS_SSR__ || !__I18N_FULL_STATIC__ && (import.meta.prerender || __IS_SSG__), getDefaultLocale: () => defaultLocale, getLocale: () => unref(i18n.locale), setLocale: async (locale) => { const oldLocale = ctx.getLocale(); if (locale === oldLocale || !isSupportedLocale(locale)) return; if (isRef(i18n.locale)) { i18n.locale.value = locale; } else { i18n.locale = locale; } await nuxt.callHook("i18n:localeSwitched", { newLocale: locale, oldLocale }); resolvedLocale.value = locale; }, setLocaleSuspend: async (locale) => { if (!isSupportedLocale(locale)) return; ctx.vueI18n.__pendingLocale = locale; ctx.vueI18n.__pendingLocalePromise = new Promise((resolve) => { ctx.vueI18n.__resolvePendingLocalePromise = async () => { ctx.setCookieLocale(locale); await ctx.setLocale(locale); ctx.vueI18n.__pendingLocale = void 0; resolve(); }; }); if (import.meta.server || nuxt.isHydrating || !ctx.config.skipSettingLocaleOnNavigate) { await ctx.vueI18n.__resolvePendingLocalePromise?.(); } }, getLocales: () => unref(i18n.locales).map((x) => isString(x) ? { code: x } : x), setCookieLocale: (locale) => { if (detectConfig.useCookie && isSupportedLocale(locale)) { localeCookie.value = locale; } }, getBaseUrl: (locale) => { if (locale) { return joinURL(getDomainFromLocale(locale) || baseUrl(), nuxt.$config.app.baseURL); } return joinURL(baseUrl(), nuxt.$config.app.baseURL); }, loadMessages: async (locale) => { try { return ctx.dynamicResourcesSSG || import.meta.dev ? await loadMessagesFromClient(locale) : await loadMessagesFromServer(locale); } catch (e) { console.warn(`Failed to load messages for locale "${locale}"`, e); } }, composableCtx: void 0 }; ctx.composableCtx = createComposableContext(ctx, nuxt); return ctx; } export function useNuxtI18nContext(nuxt) { if (nuxt._nuxtI18n == null) { throw new Error("Nuxt I18n context has not been set up yet."); } return nuxt._nuxtI18n; }