@nuxtjs/i18n
Version:
Internationalization for Nuxt
128 lines (127 loc) • 5.02 kB
JavaScript
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];
}