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.

117 lines (116 loc) 4.38 kB
import { joinURL, parseURL, withQuery } from "ufo"; import { isPrefixExceptDefaultStrategy, isNoPrefixStrategy } from "nuxt-i18n-micro-core"; import { unref, useRoute, useRuntimeConfig, watch, onUnmounted, ref, useNuxtApp } from "#imports"; import { findAllowedLocalesForRoute } from "../utils/route-utils.js"; export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "id", addSeoAttributes = true, baseUrl = "/" } = {}) => { const metaObject = ref({ htmlAttrs: {}, link: [], meta: [] }); function filterQuery(fullPath, whitelist) { const { pathname, search } = parseURL(fullPath); const params = new URLSearchParams(search); const filtered = {}; for (const key of whitelist) { if (params.has(key)) { filtered[key] = params.get(key); } } return withQuery(pathname, filtered); } function updateMeta() { const { defaultLocale, strategy, canonicalQueryWhitelist, routeLocales } = useRuntimeConfig().public.i18nConfig; const { $getLocales, $getLocale } = useNuxtApp(); if (!$getLocale || !$getLocales) return; const route = useRoute(); const locale = unref($getLocale()); const allLocales = unref($getLocales()); const routeName = (route.name ?? "").toString(); const currentLocale = unref($getLocales().find((loc) => loc.code === locale)); if (!currentLocale) return; const currentRouteLocales = findAllowedLocalesForRoute(route, routeLocales); const locales = currentRouteLocales ? allLocales.filter((loc) => currentRouteLocales.includes(loc.code)) : allLocales; const currentIso = currentLocale.iso || locale; const currentDir = currentLocale.dir || "auto"; let fullPath = unref(route.fullPath); if (!fullPath.startsWith("/")) { fullPath = `/${fullPath}`; } const matchedLocale = locales.find((locale2) => fullPath.startsWith(`/${locale2.code}`)); let localizedPath = fullPath; let ogUrl; let canonicalPath; if (routeName.startsWith("localized-") && matchedLocale) { localizedPath = fullPath.slice(matchedLocale.code.length + 1); canonicalPath = filterQuery(localizedPath, canonicalQueryWhitelist ?? []); ogUrl = joinURL(unref(baseUrl), locale, canonicalPath); } else { canonicalPath = filterQuery(fullPath, canonicalQueryWhitelist ?? []); ogUrl = joinURL(unref(baseUrl), canonicalPath); } metaObject.value = { htmlAttrs: { lang: currentIso, ...addDirAttribute ? { dir: currentDir } : {} }, link: [], meta: [] }; if (!addSeoAttributes) return; const alternateLocales = locales; const ogLocaleMeta = { [identifierAttribute]: "i18n-og", property: "og:locale", content: currentIso }; const ogUrlMeta = { [identifierAttribute]: "i18n-og-url", property: "og:url", content: ogUrl }; const alternateOgLocalesMeta = alternateLocales.map((loc) => ({ [identifierAttribute]: `i18n-og-alt-${loc.iso || loc.code}`, property: "og:locale:alternate", content: unref(loc.iso || loc.code) })); const canonicalLink = { [identifierAttribute]: "i18n-can", rel: "canonical", href: ogUrl }; const alternateLinks = isNoPrefixStrategy(strategy) ? [] : alternateLocales.flatMap((loc) => { const localizedPath2 = defaultLocale === loc.code && isPrefixExceptDefaultStrategy(strategy) ? canonicalPath : joinURL(loc.code, canonicalPath); const href = joinURL(unref(baseUrl), localizedPath2); const links = [{ [identifierAttribute]: `i18n-alternate-${loc.code}`, rel: "alternate", href, hreflang: unref(loc.code) }]; if (loc.iso && loc.iso !== loc.code) { links.push({ [identifierAttribute]: `i18n-alternate-${loc.iso}`, rel: "alternate", href, hreflang: unref(loc.iso) }); } return links; }); metaObject.value.meta = [ogLocaleMeta, ogUrlMeta, ...alternateOgLocalesMeta]; metaObject.value.link = [canonicalLink, ...alternateLinks]; } if (import.meta.client) { const route = useRoute(); const stop = watch( () => route.fullPath, () => updateMeta(), { immediate: true } ); onUnmounted(() => stop()); } else { updateMeta(); } return metaObject; };