feat(seo): add localized route metadata
This commit is contained in:
+127
@@ -0,0 +1,127 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
|
||||
export const SITE_URL = (
|
||||
process.env.NEXT_PUBLIC_SITE_URL || "https://poyrazavsever.com"
|
||||
).replace(/\/$/, "");
|
||||
|
||||
export type SiteLocale = "tr" | "en";
|
||||
|
||||
type LocalePaths = Partial<Record<SiteLocale, string>>;
|
||||
|
||||
type StaticSeoPage =
|
||||
| "home"
|
||||
| "about"
|
||||
| "references"
|
||||
| "volunteerCommunity"
|
||||
| "blog"
|
||||
| "projects"
|
||||
| "content"
|
||||
| "gallery"
|
||||
| "links"
|
||||
| "contact";
|
||||
|
||||
function normalizePath(path: string) {
|
||||
if (!path || path === "/") return "/";
|
||||
return `/${path.replace(/^\/+|\/+$/g, "")}`;
|
||||
}
|
||||
|
||||
export function getLocalizedPath(locale: SiteLocale, path: string) {
|
||||
const normalizedPath = normalizePath(path);
|
||||
|
||||
if (locale === "tr") return normalizedPath;
|
||||
return normalizedPath === "/" ? "/en" : `/en${normalizedPath}`;
|
||||
}
|
||||
|
||||
export function getAbsoluteUrl(path: string) {
|
||||
return new URL(path, `${SITE_URL}/`).toString();
|
||||
}
|
||||
|
||||
export function getLocalizedUrl(locale: SiteLocale, path: string) {
|
||||
return getAbsoluteUrl(getLocalizedPath(locale, path));
|
||||
}
|
||||
|
||||
export function createAlternates(
|
||||
locale: SiteLocale,
|
||||
paths: LocalePaths,
|
||||
): Metadata["alternates"] {
|
||||
const currentPath = paths[locale];
|
||||
if (!currentPath) return undefined;
|
||||
|
||||
const languages: Record<string, string> = {};
|
||||
|
||||
if (paths.tr) {
|
||||
languages["tr-TR"] = getLocalizedUrl("tr", paths.tr);
|
||||
}
|
||||
if (paths.en) {
|
||||
languages["en-US"] = getLocalizedUrl("en", paths.en);
|
||||
}
|
||||
|
||||
languages["x-default"] = paths.tr
|
||||
? getLocalizedUrl("tr", paths.tr)
|
||||
: getLocalizedUrl(locale, currentPath);
|
||||
|
||||
return {
|
||||
canonical: getLocalizedUrl(locale, currentPath),
|
||||
languages,
|
||||
};
|
||||
}
|
||||
|
||||
export function createPageMetadata({
|
||||
locale,
|
||||
title,
|
||||
description,
|
||||
path,
|
||||
absoluteTitle = false,
|
||||
}: {
|
||||
locale: SiteLocale;
|
||||
title: string;
|
||||
description: string;
|
||||
path: string;
|
||||
absoluteTitle?: boolean;
|
||||
}): Metadata {
|
||||
const url = getLocalizedUrl(locale, path);
|
||||
|
||||
return {
|
||||
title: absoluteTitle ? { absolute: title } : title,
|
||||
description,
|
||||
alternates: createAlternates(locale, { tr: path, en: path }),
|
||||
openGraph: {
|
||||
type: "website",
|
||||
locale: locale === "tr" ? "tr_TR" : "en_US",
|
||||
alternateLocale: locale === "tr" ? ["en_US"] : ["tr_TR"],
|
||||
url,
|
||||
title,
|
||||
description,
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
creator: "@poyrazavsever",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function getStaticPageMetadata({
|
||||
locale,
|
||||
page,
|
||||
path,
|
||||
absoluteTitle = false,
|
||||
}: {
|
||||
locale: string;
|
||||
page: StaticSeoPage;
|
||||
path: string;
|
||||
absoluteTitle?: boolean;
|
||||
}) {
|
||||
const siteLocale = locale === "en" ? "en" : "tr";
|
||||
const t = await getTranslations({ locale: siteLocale, namespace: "Seo" });
|
||||
|
||||
return createPageMetadata({
|
||||
locale: siteLocale,
|
||||
title: t(`${page}.title`),
|
||||
description: t(`${page}.description`),
|
||||
path,
|
||||
absoluteTitle,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user