Fix runttime

This commit is contained in:
diyaa 2026-03-13 03:56:40 +01:00
parent d1ed5c641b
commit c9e9ae6b90
8 changed files with 75 additions and 35 deletions

View File

@ -1,7 +1,7 @@
import Link from "next/link"; import Link from "next/link";
import type { CommonContent, HomeContent, HomeVariantContent } from "@/content/types"; import type { CommonContent, HomeContent, HomeVariantContent } from "@/content/types";
import type { Locale } from "@/lib/i18n"; import type { Locale } from "@/lib/i18n";
import { getEmailHref, isComingSoonMode } from "@/lib/site"; import { getEmailHref, getModeValue, isComingSoonMode } from "@/lib/site";
type HeroSectionProps = { type HeroSectionProps = {
locale: Locale; locale: Locale;
@ -10,7 +10,7 @@ type HeroSectionProps = {
}; };
export default function HeroSection({ locale, home, common }: HeroSectionProps) { export default function HeroSection({ locale, home, common }: HeroSectionProps) {
const activeHome: HomeVariantContent = isComingSoonMode() ? home.comingSoon : home.full; const activeHome: HomeVariantContent = getModeValue(home);
const emailHref = getEmailHref(); const emailHref = getEmailHref();
return ( return (

View File

@ -1,5 +1,6 @@
import type { Locale } from "@/lib/i18n"; import type { Locale } from "@/lib/i18n";
import type { CommonContent } from "@/content/types"; import type { CommonContent } from "@/content/types";
import { getModeValue } from "@/lib/site";
type SiteFooterProps = { type SiteFooterProps = {
locale: Locale; locale: Locale;
@ -8,13 +9,14 @@ type SiteFooterProps = {
export default function SiteFooter({ locale, common }: SiteFooterProps) { export default function SiteFooter({ locale, common }: SiteFooterProps) {
const year = new Date().getFullYear(); const year = new Date().getFullYear();
const commonVariant = getModeValue(common.variants);
return ( return (
<footer className="site-footer"> <footer className="site-footer">
<div className="container footer-content"> <div className="container footer-content">
<div className="footer-copy"> <div className="footer-copy">
<p>{common.footerRights.replace("{year}", String(year))}</p> <p>{common.footerRights.replace("{year}", String(year))}</p>
<p>{common.footerBuiltWith}</p> <p>{commonVariant.footerBuiltWith}</p>
</div> </div>
<p className="locale-badge">{locale.toUpperCase()}</p> <p className="locale-badge">{locale.toUpperCase()}</p>
</div> </div>

View File

@ -3,7 +3,7 @@ import LanguageSwitcher from "@/components/LanguageSwitcher";
import ThemeToggle from "@/components/ThemeToggle"; import ThemeToggle from "@/components/ThemeToggle";
import type { Locale } from "@/lib/i18n"; import type { Locale } from "@/lib/i18n";
import type { CommonContent } from "@/content/types"; import type { CommonContent } from "@/content/types";
import { isComingSoonMode } from "@/lib/site"; import { getModeValue, isComingSoonMode } from "@/lib/site";
type SiteHeaderProps = { type SiteHeaderProps = {
locale: Locale; locale: Locale;
@ -12,6 +12,7 @@ type SiteHeaderProps = {
export default function SiteHeader({ locale, common }: SiteHeaderProps) { export default function SiteHeader({ locale, common }: SiteHeaderProps) {
const isComingSoon = isComingSoonMode(); const isComingSoon = isComingSoonMode();
const commonVariant = getModeValue(common.variants);
return ( return (
<header className="site-header"> <header className="site-header">
@ -20,7 +21,7 @@ export default function SiteHeader({ locale, common }: SiteHeaderProps) {
<Link href={`/${locale}`} className="brand"> <Link href={`/${locale}`} className="brand">
{common.siteTitle} {common.siteTitle}
</Link> </Link>
<span className="brand-tagline">{common.siteTagline}</span> <span className="brand-tagline">{commonVariant.siteTagline}</span>
</div> </div>
{!isComingSoon ? ( {!isComingSoon ? (

View File

@ -3,7 +3,6 @@ import type { Dictionary } from "@/content/types";
const ar: Dictionary = { const ar: Dictionary = {
common: { common: {
siteTitle: "ضياء", siteTitle: "ضياء",
siteTagline: "موقع شخصي جديد قيد الإطلاق",
navLabel: "التنقل الرئيسي", navLabel: "التنقل الرئيسي",
languageSwitcherLabel: "تبديل اللغة", languageSwitcherLabel: "تبديل اللغة",
themeToggleLabel: "نمط الواجهة", themeToggleLabel: "نمط الواجهة",
@ -15,8 +14,16 @@ const ar: Dictionary = {
contact: "تواصل", contact: "تواصل",
}, },
footerRights: "{year} جميع الحقوق محفوظة", footerRights: "{year} جميع الحقوق محفوظة",
variants: {
comingSoon: {
siteTagline: "موقع شخصي جديد قيد الإطلاق",
footerBuiltWith: "صفحة مؤقتة للإعلان عن قرب إطلاق الموقع الكامل على الخادم الخاص.",
},
full: {
siteTagline: "مطور ويب يبني تجارب سريعة وقابلة للتوسع",
footerBuiltWith: "موقع ثنائي اللغة مهيأ للعرض المهني والنشر على خادم خاص.", footerBuiltWith: "موقع ثنائي اللغة مهيأ للعرض المهني والنشر على خادم خاص.",
availabilityBadge: "متاح لمشاريع الويب والتطوير المخصص", },
},
}, },
home: { home: {
comingSoon: { comingSoon: {
@ -92,10 +99,16 @@ const ar: Dictionary = {
], ],
}, },
metadata: { metadata: {
homeTitle: "قريبًا", home: {
homeDescription: "صفحة ترحيبية مؤقتة للإعلان عن قرب إطلاق الموقع الشخصي الجديد.", comingSoon: {
fullHomeTitle: "الصفحة الرئيسية", title: "قريبًا",
fullHomeDescription: "موقع شخصي احترافي ثنائي اللغة يعرض الهوية المهنية والخبرة التقنية والاستعداد للنشر.", description: "صفحة ترحيبية مؤقتة للإعلان عن قرب إطلاق الموقع الشخصي الجديد.",
},
full: {
title: "الصفحة الرئيسية",
description: "موقع شخصي احترافي ثنائي اللغة يعرض الهوية المهنية والخبرة التقنية والاستعداد للنشر.",
},
},
aboutTitle: "من أنا", aboutTitle: "من أنا",
aboutDescription: "تعرف على الخبرات، المهارات، ومنهج العمل في بناء مواقع وأنظمة ويب حديثة.", aboutDescription: "تعرف على الخبرات، المهارات، ومنهج العمل في بناء مواقع وأنظمة ويب حديثة.",
contactTitle: "تواصل", contactTitle: "تواصل",

View File

@ -3,7 +3,6 @@ import type { Dictionary } from "@/content/types";
const en: Dictionary = { const en: Dictionary = {
common: { common: {
siteTitle: "Diyaa", siteTitle: "Diyaa",
siteTagline: "A new personal site is on the way",
navLabel: "Main navigation", navLabel: "Main navigation",
languageSwitcherLabel: "Switch language", languageSwitcherLabel: "Switch language",
themeToggleLabel: "Interface theme", themeToggleLabel: "Interface theme",
@ -15,8 +14,16 @@ const en: Dictionary = {
contact: "Contact", contact: "Contact",
}, },
footerRights: "{year} All rights reserved", footerRights: "{year} All rights reserved",
variants: {
comingSoon: {
siteTagline: "A new personal site is on the way",
footerBuiltWith: "A temporary landing page announcing the upcoming launch on the private server.",
},
full: {
siteTagline: "Web developer building fast, scalable digital experiences",
footerBuiltWith: "A bilingual professional site prepared for deployment on a private server.", footerBuiltWith: "A bilingual professional site prepared for deployment on a private server.",
availabilityBadge: "Available for web builds and custom development", },
},
}, },
home: { home: {
comingSoon: { comingSoon: {
@ -92,10 +99,16 @@ const en: Dictionary = {
], ],
}, },
metadata: { metadata: {
homeTitle: "Coming Soon", home: {
homeDescription: "A temporary landing page announcing the upcoming launch of the new personal website.", comingSoon: {
fullHomeTitle: "Home", title: "Coming Soon",
fullHomeDescription: "A bilingual professional site presenting technical expertise, project readiness, and server-friendly deployment.", description: "A temporary landing page announcing the upcoming launch of the new personal website.",
},
full: {
title: "Home",
description: "A bilingual professional site presenting technical expertise, project readiness, and server-friendly deployment.",
},
},
aboutTitle: "About", aboutTitle: "About",
aboutDescription: "Learn about experience, skills, and the working approach behind modern web builds.", aboutDescription: "Learn about experience, skills, and the working approach behind modern web builds.",
contactTitle: "Contact", contactTitle: "Contact",

View File

@ -1,6 +1,15 @@
export type ModeVariants<T> = {
comingSoon: T;
full: T;
};
export type CommonVariantContent = {
siteTagline: string;
footerBuiltWith: string;
};
export type CommonContent = { export type CommonContent = {
siteTitle: string; siteTitle: string;
siteTagline: string;
navLabel: string; navLabel: string;
languageSwitcherLabel: string; languageSwitcherLabel: string;
themeToggleLabel: string; themeToggleLabel: string;
@ -12,8 +21,7 @@ export type CommonContent = {
contact: string; contact: string;
}; };
footerRights: string; footerRights: string;
footerBuiltWith: string; variants: ModeVariants<CommonVariantContent>;
availabilityBadge: string;
}; };
export type HomeVariantContent = { export type HomeVariantContent = {
@ -29,10 +37,7 @@ export type HomeVariantContent = {
}>; }>;
}; };
export type HomeContent = { export type HomeContent = ModeVariants<HomeVariantContent>;
comingSoon: HomeVariantContent;
full: HomeVariantContent;
};
export type AboutContent = { export type AboutContent = {
kicker: string; kicker: string;
@ -64,11 +69,13 @@ export type ContactContent = {
channels: ContactChannelContent[]; channels: ContactChannelContent[];
}; };
export type MetadataVariantContent = {
title: string;
description: string;
};
export type MetadataContent = { export type MetadataContent = {
homeTitle: string; home: ModeVariants<MetadataVariantContent>;
homeDescription: string;
fullHomeTitle: string;
fullHomeDescription: string;
aboutTitle: string; aboutTitle: string;
aboutDescription: string; aboutDescription: string;
contactTitle: string; contactTitle: string;

View File

@ -1,6 +1,6 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { getDictionary, type Locale } from "@/lib/i18n"; import { getDictionary, type Locale } from "@/lib/i18n";
import { getLocalizedPath, getLocalizedUrl, isComingSoonMode } from "@/lib/site"; import { getLocalizedPath, getLocalizedUrl, getModeValue } from "@/lib/site";
type PageKey = "home" | "about" | "contact"; type PageKey = "home" | "about" | "contact";
@ -13,11 +13,11 @@ const pagePathMap: Record<PageKey, string> = {
export function buildPageMetadata(locale: Locale, page: PageKey): Metadata { export function buildPageMetadata(locale: Locale, page: PageKey): Metadata {
const dictionary = getDictionary(locale); const dictionary = getDictionary(locale);
const pathname = pagePathMap[page]; const pathname = pagePathMap[page];
const isComingSoon = isComingSoonMode(); const homeMetadata = getModeValue(dictionary.metadata.home);
const metadataByPage = { const metadataByPage = {
home: { home: {
title: isComingSoon ? dictionary.metadata.homeTitle : dictionary.metadata.fullHomeTitle, title: homeMetadata.title,
description: isComingSoon ? dictionary.metadata.homeDescription : dictionary.metadata.fullHomeDescription, description: homeMetadata.description,
}, },
about: { about: {
title: dictionary.metadata.aboutTitle, title: dictionary.metadata.aboutTitle,

View File

@ -1,4 +1,4 @@
import type { ContactContent } from "@/content/types"; import type { ContactContent, ModeVariants } from "@/content/types";
const FALLBACK_SITE_URL = "https://example.com"; const FALLBACK_SITE_URL = "https://example.com";
const SITE_MODES = ["coming-soon", "full"] as const; const SITE_MODES = ["coming-soon", "full"] as const;
@ -60,6 +60,10 @@ export function isComingSoonMode(): boolean {
return getSiteMode() === "coming-soon"; return getSiteMode() === "coming-soon";
} }
export function getModeValue<T>(variants: ModeVariants<T>): T {
return variants[getSiteMode()];
}
export function getLocalizedPath(pathname: string, locale: "ar" | "en"): string { export function getLocalizedPath(pathname: string, locale: "ar" | "en"): string {
const normalizedPath = pathname === "/" ? "" : pathname; const normalizedPath = pathname === "/" ? "" : pathname;
return `/${locale}${normalizedPath}`; return `/${locale}${normalizedPath}`;