282 أسطر
7.7 KiB
TypeScript
282 أسطر
7.7 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { englishPortfolioContent, getPortfolioContent, sharedProfile, type Language } from "@/data/portfolio";
|
|
import { absoluteUrl, siteName } from "@/data/site-config";
|
|
|
|
const primaryEnglishName = sharedProfile.founderNameEn;
|
|
const fullEnglishName = sharedProfile.fullNameEn;
|
|
const englishAlternateNames = sharedProfile.alternateNamesEn;
|
|
const arabicName = sharedProfile.founderNameAr;
|
|
|
|
const sharedKeywords = [
|
|
"Grace Salmoun",
|
|
"Grace Butrus Salmoun",
|
|
"Grace Salamoun",
|
|
"architecture portfolio",
|
|
"architectural engineer",
|
|
"architectural design",
|
|
"urban rehabilitation",
|
|
"landscape design",
|
|
"shop drawings",
|
|
"architectural visualization",
|
|
"Damascus architect",
|
|
];
|
|
|
|
const localizedKeywords: Record<Language, string[]> = {
|
|
en: ["portfolio architect", "presentation boards", "mixed-use towers", "hospitality design"],
|
|
ar: ["بورتفوليو معماري", "مهندسة معمارية", "تصميم معماري", "إعادة تأهيل عمراني"],
|
|
};
|
|
|
|
function getLocale(language: Language) {
|
|
return language === "ar" ? "ar_SY" : "en_US";
|
|
}
|
|
|
|
function getAlternateLocales(language: Language) {
|
|
return language === "ar" ? ["en_US"] : ["ar_SY"];
|
|
}
|
|
|
|
function getHomePath(language: Language) {
|
|
return language === "ar" ? "/ar" : "/";
|
|
}
|
|
|
|
function getResumePath(language: Language) {
|
|
return language === "ar" ? "/ar/resume" : "/resume";
|
|
}
|
|
|
|
function getOgImage(language: Language) {
|
|
return {
|
|
url: absoluteUrl(sharedProfile.heroImage),
|
|
alt:
|
|
language === "ar"
|
|
? "معاينة بورتفوليو غريس بطرس سلمون"
|
|
: "Portfolio preview for Grace Salmoun",
|
|
};
|
|
}
|
|
|
|
function buildMetadata({
|
|
language,
|
|
title,
|
|
description,
|
|
canonicalPath,
|
|
pageType,
|
|
}: {
|
|
language: Language;
|
|
title: string;
|
|
description: string;
|
|
canonicalPath: string;
|
|
pageType: "website" | "profile";
|
|
}): Metadata {
|
|
const ogImage = getOgImage(language);
|
|
|
|
return {
|
|
title,
|
|
description,
|
|
keywords: [...sharedKeywords, ...localizedKeywords[language]],
|
|
authors: [{ name: primaryEnglishName }],
|
|
creator: primaryEnglishName,
|
|
publisher: primaryEnglishName,
|
|
category: "architecture portfolio",
|
|
alternates: {
|
|
canonical: canonicalPath,
|
|
languages: {
|
|
en: canonicalPath.includes("/resume") ? "/resume" : "/",
|
|
ar: canonicalPath.includes("/resume") ? "/ar/resume" : "/ar",
|
|
"x-default": "/",
|
|
},
|
|
},
|
|
robots: {
|
|
index: true,
|
|
follow: true,
|
|
googleBot: {
|
|
index: true,
|
|
follow: true,
|
|
"max-image-preview": "large",
|
|
"max-snippet": -1,
|
|
"max-video-preview": -1,
|
|
},
|
|
},
|
|
openGraph: {
|
|
title,
|
|
description,
|
|
url: absoluteUrl(canonicalPath),
|
|
siteName,
|
|
locale: getLocale(language),
|
|
alternateLocale: getAlternateLocales(language),
|
|
type: pageType,
|
|
images: [ogImage],
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title,
|
|
description,
|
|
images: [ogImage.url],
|
|
},
|
|
};
|
|
}
|
|
|
|
export function getDefaultSeoMetadata(): Metadata {
|
|
const title = englishPortfolioContent.meta.title;
|
|
const description = englishPortfolioContent.meta.description;
|
|
const ogImage = getOgImage("en");
|
|
|
|
return {
|
|
title,
|
|
description,
|
|
applicationName: siteName,
|
|
authors: [{ name: primaryEnglishName }],
|
|
creator: primaryEnglishName,
|
|
publisher: primaryEnglishName,
|
|
keywords: [...sharedKeywords, ...localizedKeywords.en],
|
|
category: "architecture portfolio",
|
|
referrer: "origin-when-cross-origin",
|
|
robots: {
|
|
index: true,
|
|
follow: true,
|
|
googleBot: {
|
|
index: true,
|
|
follow: true,
|
|
"max-image-preview": "large",
|
|
"max-snippet": -1,
|
|
"max-video-preview": -1,
|
|
},
|
|
},
|
|
openGraph: {
|
|
title,
|
|
description,
|
|
url: absoluteUrl("/"),
|
|
siteName,
|
|
locale: "en_US",
|
|
alternateLocale: ["ar_SY"],
|
|
type: "website",
|
|
images: [ogImage],
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title,
|
|
description,
|
|
images: [ogImage.url],
|
|
},
|
|
};
|
|
}
|
|
|
|
export function getHomeMetadata(language: Language): Metadata {
|
|
const t = getPortfolioContent(language);
|
|
|
|
return buildMetadata({
|
|
language,
|
|
title: t.meta.title,
|
|
description: t.meta.description,
|
|
canonicalPath: getHomePath(language),
|
|
pageType: "website",
|
|
});
|
|
}
|
|
|
|
export function getResumeMetadata(language: Language): Metadata {
|
|
const t = getPortfolioContent(language);
|
|
const title = language === "ar" ? `السيرة الذاتية | ${t.meta.title}` : `Resume | ${t.meta.title}`;
|
|
|
|
return buildMetadata({
|
|
language,
|
|
title,
|
|
description: t.resume.description,
|
|
canonicalPath: getResumePath(language),
|
|
pageType: "profile",
|
|
});
|
|
}
|
|
|
|
export function getHomeStructuredData(language: Language) {
|
|
const t = getPortfolioContent(language);
|
|
const name = language === "ar" ? sharedProfile.founderNameAr : sharedProfile.founderNameEn;
|
|
const address = language === "ar" ? sharedProfile.addressAr : sharedProfile.address;
|
|
|
|
return [
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
name: siteName,
|
|
alternateName: [`${fullEnglishName} Portfolio`, "Grace Salamoun Portfolio"],
|
|
url: absoluteUrl("/"),
|
|
inLanguage: ["en", "ar"],
|
|
},
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "Person",
|
|
name,
|
|
givenName: "Grace",
|
|
additionalName: "Butrus",
|
|
familyName: "Salmoun",
|
|
alternateName: language === "ar" ? [primaryEnglishName, fullEnglishName, ...englishAlternateNames] : [fullEnglishName, arabicName, ...englishAlternateNames],
|
|
url: absoluteUrl(getHomePath(language)),
|
|
image: absoluteUrl(sharedProfile.heroImage),
|
|
jobTitle: t.ui.architectureEngineer,
|
|
description: t.meta.description,
|
|
email: sharedProfile.email,
|
|
telephone: sharedProfile.phone,
|
|
address: {
|
|
"@type": "PostalAddress",
|
|
addressLocality: address,
|
|
addressCountry: "SY",
|
|
},
|
|
sameAs: [sharedProfile.facebookHref],
|
|
knowsAbout: [...t.craft.skills.slice(0, 4), ...t.sectors.categories.slice(0, 4)],
|
|
},
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "CollectionPage",
|
|
name: t.meta.title,
|
|
description: t.meta.description,
|
|
url: absoluteUrl(getHomePath(language)),
|
|
inLanguage: language,
|
|
isPartOf: {
|
|
"@type": "WebSite",
|
|
name: siteName,
|
|
url: absoluteUrl("/"),
|
|
},
|
|
about: {
|
|
"@type": "Person",
|
|
name,
|
|
},
|
|
},
|
|
];
|
|
}
|
|
|
|
export function getResumeStructuredData(language: Language) {
|
|
const t = getPortfolioContent(language);
|
|
const name = language === "ar" ? sharedProfile.founderNameAr : sharedProfile.founderNameEn;
|
|
const title = language === "ar" ? `السيرة الذاتية | ${name}` : `Resume | ${name}`;
|
|
|
|
return [
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "Person",
|
|
name,
|
|
givenName: "Grace",
|
|
additionalName: "Butrus",
|
|
familyName: "Salmoun",
|
|
alternateName: language === "ar" ? [primaryEnglishName, fullEnglishName, ...englishAlternateNames] : [fullEnglishName, arabicName, ...englishAlternateNames],
|
|
url: absoluteUrl(getHomePath(language)),
|
|
email: sharedProfile.email,
|
|
telephone: sharedProfile.phone,
|
|
image: absoluteUrl(sharedProfile.heroImage),
|
|
jobTitle: t.ui.architectureEngineer,
|
|
sameAs: [sharedProfile.facebookHref],
|
|
},
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "ProfilePage",
|
|
name: title,
|
|
description: t.resume.description,
|
|
url: absoluteUrl(getResumePath(language)),
|
|
inLanguage: language,
|
|
isPartOf: {
|
|
"@type": "WebSite",
|
|
name: siteName,
|
|
url: absoluteUrl("/"),
|
|
},
|
|
about: {
|
|
"@type": "Person",
|
|
name,
|
|
},
|
|
},
|
|
];
|
|
}
|