UNPKG

@nuxtjs/i18n

Version:

Internationalization for Nuxt

128 lines (127 loc) 5.02 kB
import { hasProtocol, joinURL, withQuery } from "ufo"; const strictSeo = __I18N_STRICT_SEO__; export function localeHead(options, currentLanguage = options.getCurrentLanguage(), currentDirection = options.getCurrentDirection()) { const metaObject = { htmlAttrs: {}, link: [], meta: [] }; if (options.dir) { metaObject.htmlAttrs.dir = currentDirection; } if (options.lang && currentLanguage) { metaObject.htmlAttrs.lang = currentLanguage; } if (options.seo) { const alternateLinks = getHreflangLinks(options); metaObject.link = metaObject.link.concat( alternateLinks, getCanonicalLink(options) ); metaObject.meta = metaObject.meta.concat( getOgUrl(options), getCurrentOgLocale(options), getAlternateOgLocales( options, strictSeo ? alternateLinks.map((x) => x.hreflang).filter((x) => x !== "x-default") : options.locales.map((x) => x.language || x.code) ) ); } return metaObject; } function createLocaleMap(locales) { const localeMap = /* @__PURE__ */ new Map(); for (const locale of locales) { if (!locale.language) { console.warn("Locale `language` ISO code is required to generate alternate link"); continue; } const [language, region] = locale.language.split("-"); if (language && region && (locale.isCatchallLocale || !localeMap.has(language))) { localeMap.set(language, locale); } localeMap.set(locale.language, locale); } return localeMap; } function getHreflangLinks(options) { if (!options.hreflangLinks) return []; const links = []; const localeMap = createLocaleMap(options.locales); for (const [language, locale] of localeMap.entries()) { const link = getHreflangLink(language, locale, options); if (!link) continue; links.push(link); if (options.defaultLocale && options.defaultLocale === locale.code && links[0].hreflang !== "x-default") { links.unshift( strictSeo ? { rel: "alternate", href: link.href, hreflang: "x-default" } : { [options.key]: "i18n-xd", rel: "alternate", href: link.href, hreflang: "x-default" } ); } } return links; } function getHreflangLink(language, locale, options, routeWithoutQuery = options.strictCanonicals ? options.getRouteWithoutQuery() : void 0) { const localePath = options.getLocalizedRoute(locale.code, routeWithoutQuery); if (!localePath) return void 0; const href = withQuery( hasProtocol(localePath) ? localePath : joinURL(options.baseUrl, localePath), options.strictCanonicals ? getCanonicalQueryParams(options) : {} ); return strictSeo ? { rel: "alternate", href, hreflang: language } : { [options.key]: `i18n-alt-${language}`, rel: "alternate", href, hreflang: language }; } function getCanonicalUrl(options, route = options.getCurrentRoute()) { const currentRoute = options.getLocaleRoute( Object.assign({}, route, { path: void 0, name: options.getRouteBaseName(route) }) ); if (!currentRoute) return ""; return withQuery(joinURL(options.baseUrl, currentRoute.path), getCanonicalQueryParams(options)); } function getCanonicalLink(options, href = getCanonicalUrl(options)) { if (!href) return []; return [strictSeo ? { rel: "canonical", href } : { [options.key]: "i18n-can", rel: "canonical", href }]; } function getCanonicalQueryParams(options, route = options.getCurrentRoute()) { const currentRoute = options.getLocaleRoute( Object.assign({}, route, { path: void 0, name: options.getRouteBaseName(route) }) ); const currentRouteQuery = currentRoute?.query ?? {}; const params = {}; for (const param of options.canonicalQueries.filter((x) => x in currentRouteQuery)) { params[param] ??= []; for (const val of toArray(currentRouteQuery[param])) { params[param].push(val || ""); } } return params; } function getOgUrl(options, href = getCanonicalUrl(options)) { if (!href) return []; return [ strictSeo ? { property: "og:url", content: href } : { [options.key]: "i18n-og-url", property: "og:url", content: href } ]; } function getCurrentOgLocale(options, currentLanguage = options.getCurrentLanguage()) { if (!currentLanguage) return []; return [ strictSeo ? { property: "og:locale", content: formatOgLanguage(currentLanguage) } : { [options.key]: "i18n-og", property: "og:locale", content: formatOgLanguage(currentLanguage) } ]; } function getAlternateOgLocales(options, languages, currentLanguage = options.getCurrentLanguage()) { const alternateLocales = languages.filter((locale) => locale && locale !== currentLanguage); return alternateLocales.map( (locale) => strictSeo ? { property: "og:locale:alternate", content: formatOgLanguage(locale) } : { [options.key]: `i18n-og-alt-${locale}`, property: "og:locale:alternate", content: formatOgLanguage(locale) } ); } function formatOgLanguage(val = "") { return val.replace(/-/g, "_"); } function toArray(value) { return Array.isArray(value) ? value : [value]; }