Commit multilingual editorial frontend work
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
---
|
||||
import "../styles/global.css";
|
||||
import CookieBanner from "../components/CookieBanner.astro";
|
||||
import LocaleCopy from "../components/LocaleCopy.astro";
|
||||
import LocaleSwitcher from "../components/LocaleSwitcher.astro";
|
||||
import SectionMark from "../components/SectionMark.astro";
|
||||
import { getSectionHref, launchSections } from "../data/site";
|
||||
import { footerCallouts, getChromeCopy, localizedSections, policyLinkCopy } from "../data/locales";
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
@@ -15,47 +19,42 @@ const {
|
||||
lang = "en",
|
||||
} = Astro.props;
|
||||
|
||||
const issueDate = new Intl.DateTimeFormat("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}).format(new Date());
|
||||
const now = new Date();
|
||||
const issueDate = {
|
||||
en: new Intl.DateTimeFormat("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}).format(now),
|
||||
fr: new Intl.DateTimeFormat("fr-FR", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}).format(now),
|
||||
nb: new Intl.DateTimeFormat("nb-NO", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}).format(now),
|
||||
};
|
||||
|
||||
const pathname = Astro.url.pathname.replace(/\/+$/, "") || "/";
|
||||
const activeSlug = pathname === "/" ? "home" : pathname.split("/").filter(Boolean)[0];
|
||||
const primarySlugs = ["business", "education", "writing", "jazz-music", "ai-lab", "norway"];
|
||||
const primaryNav = launchSections.filter((section) => primarySlugs.includes(section.slug));
|
||||
const footerNav = launchSections.filter((section) => !primarySlugs.includes(section.slug));
|
||||
const currentSection = launchSections.find((section) => section.slug === activeSlug);
|
||||
const articleMeta = pathname.startsWith("/articles/norway")
|
||||
? {
|
||||
label: "Article / Norway desk",
|
||||
note: "Field report / family life / fathers / immigrants",
|
||||
}
|
||||
const articleKey = pathname.startsWith("/articles/norway")
|
||||
? "norway"
|
||||
: pathname.startsWith("/articles/kongsberg-jazz-2026")
|
||||
? {
|
||||
label: "Article / Jazz and Music",
|
||||
note: "Field report / Kongsberg x Paris",
|
||||
}
|
||||
? "jazz"
|
||||
: pathname.startsWith("/articles/trivia-and-tunes-april-2026")
|
||||
? {
|
||||
label: "Article / Projects desk",
|
||||
note: "Field report / music trivia / Blue Note Rhino / April build",
|
||||
}
|
||||
: null;
|
||||
const issueLabel = currentSection
|
||||
? `Section ${currentSection.label} / ${currentSection.title}`
|
||||
: articleMeta
|
||||
? articleMeta.label
|
||||
: "Founding issue / Personal edition";
|
||||
const ribbonNote = currentSection?.tone
|
||||
?? (articleMeta
|
||||
? articleMeta.note
|
||||
: "Ringwood / Villanova / Brussels / Paris / Krakow / Oslo / Kongsberg");
|
||||
? "projects"
|
||||
: null;
|
||||
const chromeCopy = getChromeCopy({ activeSlug, issueDate, articleKey });
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={lang}>
|
||||
<html lang={lang} data-ui-lang="en" data-cookie-analytics="false" data-cookie-embeds="false">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
@@ -74,28 +73,31 @@ const ribbonNote = currentSection?.tone
|
||||
<body>
|
||||
<header class="site-ribbon">
|
||||
<div class="container site-ribbon__row">
|
||||
<span>Founding issue / {issueDate}</span>
|
||||
<span>{ribbonNote}</span>
|
||||
<LocaleCopy copy={chromeCopy.ribbonIssue} />
|
||||
<LocaleCopy copy={chromeCopy.ribbonNote} />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="site-masthead">
|
||||
<div class="container masthead">
|
||||
<div class="masthead__row">
|
||||
<span>{issueLabel}</span>
|
||||
<span>Jazz desk / machine room / family archive / pataphysical bulletin</span>
|
||||
<LocaleCopy copy={chromeCopy.issueLabel} />
|
||||
<LocaleCopy copy={chromeCopy.mastheadLine} />
|
||||
</div>
|
||||
|
||||
<a href="/" class="masthead__brand masthead__brand--site">
|
||||
<p class="masthead__domain">davegilligan.com</p>
|
||||
<strong>Dave Gilligan</strong>
|
||||
<p class="masthead__prompt">Hybrid IT. Private AI. Jazz rooms. Literary weather.</p>
|
||||
<p class="masthead__prompt">
|
||||
<LocaleCopy copy={chromeCopy.domainPrompt} />
|
||||
</p>
|
||||
<span>
|
||||
A personal site edited like a bright retro paper: systems, music, languages, Norway,
|
||||
civic weather, and useful mischief under one masthead.
|
||||
<LocaleCopy copy={chromeCopy.domainLede} />
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<LocaleSwitcher />
|
||||
|
||||
<nav class="site-nav" aria-label="Primary sections">
|
||||
{primaryNav.map((section) => (
|
||||
<a
|
||||
@@ -103,7 +105,15 @@ const ribbonNote = currentSection?.tone
|
||||
class={`site-nav__link ${activeSlug === section.slug ? "site-nav__link--active" : ""}`}
|
||||
>
|
||||
<SectionMark slug={section.slug} className="section-mark--nav" />
|
||||
<span>{section.title}</span>
|
||||
<span>
|
||||
<LocaleCopy
|
||||
copy={{
|
||||
en: localizedSections[section.slug]?.en.title ?? section.title,
|
||||
fr: localizedSections[section.slug]?.fr.title ?? section.title,
|
||||
nb: localizedSections[section.slug]?.nb.title ?? section.title,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
@@ -116,27 +126,63 @@ const ribbonNote = currentSection?.tone
|
||||
<div class="container site-footer__top">
|
||||
<div class="site-footer__brand">
|
||||
<p>davegilligan.com</p>
|
||||
<strong>Jazz desk, machine room, and civic archive.</strong>
|
||||
<span>
|
||||
Built in Astro with React islands, backed by PHP and SQL, and art-directed like a
|
||||
magazine instead of a brochure.
|
||||
</span>
|
||||
<strong><LocaleCopy copy={chromeCopy.footerHeadline} /></strong>
|
||||
<span><LocaleCopy copy={chromeCopy.footerBody} /></span>
|
||||
</div>
|
||||
|
||||
<div class="footer-links">
|
||||
{footerNav.map((section) => (
|
||||
<a href={getSectionHref(section)}>
|
||||
<SectionMark slug={section.slug} className="section-mark--footer" />
|
||||
<span>{section.title}</span>
|
||||
<span>
|
||||
<LocaleCopy
|
||||
copy={{
|
||||
en: localizedSections[section.slug]?.en.title ?? section.title,
|
||||
fr: localizedSections[section.slug]?.fr.title ?? section.title,
|
||||
nb: localizedSections[section.slug]?.nb.title ?? section.title,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container site-footer__callouts">
|
||||
<a class="footer-callout" href={footerCallouts.blueNoteLogic.href} target="_blank" rel="noreferrer">
|
||||
<p class="footer-callout__label">
|
||||
<LocaleCopy copy={footerCallouts.blueNoteLogic.label} />
|
||||
</p>
|
||||
<strong><LocaleCopy copy={footerCallouts.blueNoteLogic.title} /></strong>
|
||||
<span><LocaleCopy copy={footerCallouts.blueNoteLogic.body} /></span>
|
||||
</a>
|
||||
|
||||
<a class="footer-callout" href={footerCallouts.gilliganTech.href} target="_blank" rel="noreferrer">
|
||||
<p class="footer-callout__label">
|
||||
<LocaleCopy copy={footerCallouts.gilliganTech.label} />
|
||||
</p>
|
||||
<strong><LocaleCopy copy={footerCallouts.gilliganTech.title} /></strong>
|
||||
<span><LocaleCopy copy={footerCallouts.gilliganTech.body} /></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="container site-footer__policies">
|
||||
<a class="policy-link" href={policyLinkCopy.privacy.href}>
|
||||
<strong><LocaleCopy copy={policyLinkCopy.privacy.title} /></strong>
|
||||
<span><LocaleCopy copy={policyLinkCopy.privacy.body} /></span>
|
||||
</a>
|
||||
<a class="policy-link" href={policyLinkCopy.cookies.href}>
|
||||
<strong><LocaleCopy copy={policyLinkCopy.cookies.title} /></strong>
|
||||
<span><LocaleCopy copy={policyLinkCopy.cookies.body} /></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="container footer-note">
|
||||
<span>Astro + React islands + PHP + SQL</span>
|
||||
<span>Blue Note Logic / Gilligan TECH / Kongsberg / multilingual edition</span>
|
||||
<span><LocaleCopy copy={chromeCopy.footerNoteLeft} /></span>
|
||||
<span><LocaleCopy copy={chromeCopy.footerNoteRight} /></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<CookieBanner />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user