返回 CodeWhale
footer.tsx
根目录 / web / components / footer.tsx
1 import Link from "next/link";
2 import { GITEE_ENABLED, type Locale } from "@/lib/i18n/config";
3 import { getChrome } from "@/lib/i18n/dictionaries";
4 import {
5 footerLegalLinks,
6 footerProductLinks,
7 footerProjectLinks,
8 REPO_RELEASES_URL,
9 REPO_URL,
10 } from "@/lib/i18n/links";
11 import { SITE_CONTACT_EMAIL, SITE_SECURITY_EMAIL } from "@/lib/page-meta";
12 import { USAGE_COUNTING_COPY } from "@/lib/content/usage-counting";
13 import { pickText } from "@/lib/i18n/dictionaries";
14 import { getStorefrontCopy } from "@/lib/content/merch-storefront";
15 import { WhalePose } from "./whale-pose";
16
17 /**
18 * Site footer: the sea below one horizon line, in both appearances.
19 * One dictionary path for every routed locale; the Product column carries
20 * the full link set everywhere.
21 */
22 export function Footer({ locale = "en" }: { locale?: Locale }) {
23 const chrome = getChrome(locale);
24 const homeHref = `/${locale}`;
25 const product = footerProductLinks(locale, chrome);
26 const project = footerProjectLinks(locale, chrome);
27 const legal = footerLegalLinks(locale, chrome);
28
29 return (
30 <footer className="site-footer">
31 <div className="site-footer-sea">
32 <div className="horizon" aria-hidden="true" />
33 <div className="site-footer-main">
34 <div className="site-footer-brand">
35 <Link href={homeHref} className="site-wordmark site-wordmark-footer" aria-label="Codewhale">
36 <WhalePose pose="rest" />
37 <span className="wordmark" aria-hidden="true" />
38 </Link>
39 <p>{chrome.footerTagline}</p>
40 </div>
41
42 <div className="site-footer-links">
43 <div className="site-footer-group">
44 <span className="site-footer-label">{chrome.footerProduct}</span>
45 <div className="site-footer-list">
46 {product.map((item) => <Link key={item.href} href={item.href}>{item.label}</Link>)}
47 </div>
48 </div>
49 <div className="site-footer-group">
50 <span className="site-footer-label">{chrome.footerProject}</span>
51 <div className="site-footer-list">
52 {project.map((item) => <Link key={item.href} href={item.href}>{item.label}</Link>)}
53 <Link href={`/${locale}/merch`}>{getStorefrontCopy(locale).merch}</Link>
54 </div>
55 </div>
56 </div>
57 </div>
58
59 <div className="site-footer-meta">
60 <p>
61 {chrome.footerCanonicalSource}
62 <a href={REPO_URL}>github.com/codewhale-hq/CodeWhale</a>
63 {chrome.footerReleases}
64 <a href={REPO_RELEASES_URL}>{chrome.footerReleasesLink}</a>
65 </p>
66 <div className="site-footer-meta-links">
67 {legal.map((item) => <Link key={item.href} href={item.href}>{item.label}</Link>)}
68 {GITEE_ENABLED && <a href="https://gitee.com/codewhale-hq/CodeWhale">Gitee</a>}
69 <a href="https://cnb.cool/codewhale.net/codewhale">CNB</a>
70 <a href="https://npmmirror.com/package/codewhale">npmmirror</a>
71 <a href={`mailto:${SITE_CONTACT_EMAIL}`}>{SITE_CONTACT_EMAIL}</a>
72 <a href={`mailto:${SITE_SECURITY_EMAIL}`}>{chrome.footerSecurity}</a>
73 <Link href={`/${locale}/legal/privacy#usage-counting`}>{pickText(USAGE_COUNTING_COPY.footerLink, locale)}</Link>
74 </div>
75 <span>© {new Date().getFullYear()} Codewhale</span>
76 </div>
77 </div>
78 </footer>
79 );
80 }
81
81 lines Plain Text