This commit is contained in:
+131
-9
@@ -1,7 +1,17 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { AppLocale, getLocalizedPath, resolveLocale } from "@/lib/locale";
|
||||
import { routing } from "../i18n/routing";
|
||||
import {
|
||||
PAGE_TITLE_TOKEN,
|
||||
SITE_NAME_TOKEN,
|
||||
type SiteSettings,
|
||||
type SiteSettingsMediaBindings,
|
||||
} from "./site-settings";
|
||||
import {
|
||||
getSiteSettings,
|
||||
getSiteSettingsMediaBindings,
|
||||
} from "./app-config";
|
||||
import { AppLocale, getLocalizedPath, resolveLocale } from "./locale";
|
||||
|
||||
function getSiteUrl(): URL {
|
||||
return new URL(process.env.NEXT_PUBLIC_SITE_URL ?? "https://mohfarawati.de");
|
||||
@@ -25,32 +35,144 @@ export function buildLocaleAlternates(pathname: string) {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyTitleTemplateFn(title: string, template: string, siteName: string): string {
|
||||
const safeTemplate = template.includes(PAGE_TITLE_TOKEN)
|
||||
? template
|
||||
: `${PAGE_TITLE_TOKEN} | ${SITE_NAME_TOKEN}`;
|
||||
|
||||
return safeTemplate
|
||||
.replaceAll(SITE_NAME_TOKEN, siteName)
|
||||
.replace(PAGE_TITLE_TOKEN, title);
|
||||
}
|
||||
|
||||
function buildMetadataImages(imageUrl?: string | null) {
|
||||
if (!imageUrl) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
url: toAbsoluteUrl(imageUrl),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export async function buildAppMetadata(): Promise<Metadata> {
|
||||
const [settings, bindings] = await Promise.all([getSiteSettings(), getSiteSettingsMediaBindings()]);
|
||||
|
||||
return buildAppMetadataFromConfig(settings, bindings);
|
||||
}
|
||||
|
||||
export function buildAppMetadataFromConfig(
|
||||
settings: SiteSettings,
|
||||
bindings: SiteSettingsMediaBindings,
|
||||
): Metadata {
|
||||
const defaultLocaleSettings = settings.locales[routing.defaultLocale];
|
||||
const openGraphImages = buildMetadataImages(bindings.defaultOgImage?.url);
|
||||
|
||||
return {
|
||||
metadataBase: getSiteUrl(),
|
||||
title: defaultLocaleSettings.siteName,
|
||||
description: defaultLocaleSettings.siteDescription,
|
||||
applicationName: defaultLocaleSettings.siteName,
|
||||
icons: bindings.favicon?.url
|
||||
? {
|
||||
icon: [bindings.favicon.url],
|
||||
shortcut: [bindings.favicon.url],
|
||||
apple: [bindings.favicon.url],
|
||||
}
|
||||
: undefined,
|
||||
openGraph: {
|
||||
title: defaultLocaleSettings.siteName,
|
||||
description: defaultLocaleSettings.siteDescription,
|
||||
url: toAbsoluteUrl(getLocalizedPath(routing.defaultLocale, "/")),
|
||||
siteName: defaultLocaleSettings.siteName,
|
||||
locale: routing.defaultLocale,
|
||||
type: "website",
|
||||
images: openGraphImages,
|
||||
},
|
||||
twitter: {
|
||||
card: openGraphImages ? "summary_large_image" : "summary",
|
||||
title: defaultLocaleSettings.siteName,
|
||||
description: defaultLocaleSettings.siteDescription,
|
||||
images: openGraphImages?.map((image) => image.url),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
type LocalizedMetadataInput = {
|
||||
locale: string;
|
||||
pathname: string;
|
||||
title: string;
|
||||
description: string;
|
||||
description?: string;
|
||||
applyTitleTemplate?: boolean;
|
||||
};
|
||||
|
||||
export function buildLocalizedMetadata({
|
||||
export async function buildLocalizedMetadata({
|
||||
locale,
|
||||
pathname,
|
||||
title,
|
||||
description,
|
||||
}: LocalizedMetadataInput): Metadata {
|
||||
applyTitleTemplate,
|
||||
}: LocalizedMetadataInput): Promise<Metadata> {
|
||||
const localeKey = resolveLocale(locale);
|
||||
const [settings, bindings] = await Promise.all([getSiteSettings(), getSiteSettingsMediaBindings()]);
|
||||
|
||||
return {
|
||||
return buildLocalizedMetadataFromConfig({
|
||||
settings,
|
||||
bindings,
|
||||
locale: localeKey,
|
||||
pathname,
|
||||
title,
|
||||
description,
|
||||
applyTitleTemplate,
|
||||
});
|
||||
}
|
||||
|
||||
export function buildLocalizedMetadataFromConfig(input: {
|
||||
settings: SiteSettings;
|
||||
bindings: SiteSettingsMediaBindings;
|
||||
locale: AppLocale;
|
||||
pathname: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
applyTitleTemplate?: boolean;
|
||||
}): Metadata {
|
||||
const {
|
||||
settings,
|
||||
bindings,
|
||||
locale,
|
||||
pathname,
|
||||
title,
|
||||
description,
|
||||
applyTitleTemplate = true,
|
||||
} = input;
|
||||
const localeKey = resolveLocale(locale);
|
||||
const localeSettings = settings.locales[localeKey];
|
||||
const resolvedDescription = description?.trim() || localeSettings.siteDescription;
|
||||
const resolvedTitle = applyTitleTemplate
|
||||
? applyTitleTemplateFn(title, localeSettings.titleTemplate, localeSettings.siteName)
|
||||
: title;
|
||||
const openGraphImages = buildMetadataImages(bindings.defaultOgImage?.url);
|
||||
|
||||
return {
|
||||
title: resolvedTitle,
|
||||
description: resolvedDescription,
|
||||
alternates: buildLocaleAlternates(pathname),
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
title: resolvedTitle,
|
||||
description: resolvedDescription,
|
||||
url: toAbsoluteUrl(getLocalizedPath(localeKey, pathname)),
|
||||
siteName: "moh-sass",
|
||||
siteName: localeSettings.siteName,
|
||||
locale: localeKey,
|
||||
type: "website",
|
||||
images: openGraphImages,
|
||||
},
|
||||
twitter: {
|
||||
card: openGraphImages ? "summary_large_image" : "summary",
|
||||
title: resolvedTitle,
|
||||
description: resolvedDescription,
|
||||
images: openGraphImages?.map((image) => image.url),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user