Skip to content

Commit 61107f1

Browse files
committed
add withLegal with full translation support
1 parent 9e972ed commit 61107f1

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

apps/site/components/withLegal.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { useTranslations } from 'next-intl';
2+
3+
import Link from '#site/components/Link';
4+
5+
import type { FC } from 'react';
6+
7+
type LegalProps = {
8+
footerLinks: Array<{
9+
text: string;
10+
link: string;
11+
}>;
12+
};
13+
14+
/**
15+
* These keys match the following locations, and are kept in sync to lessen duplication:
16+
* - translation keys within [locale].json components.containers.footer.links
17+
* - keys within the large [locale].json components.containers.footer.legal paragraph
18+
* - used directly to find the passed links from navigation.footerLinks
19+
*/
20+
const RICH_TRANSLATION_KEYS = [
21+
'openjsf',
22+
'trademarkPolicy',
23+
'trademarkList',
24+
'termsOfUse',
25+
'privacyPolicy',
26+
'bylaws',
27+
'codeOfConduct',
28+
'cookiePolicy',
29+
];
30+
31+
const WithLegal: FC<LegalProps> = ({ footerLinks }) => {
32+
const t = useTranslations();
33+
34+
/**
35+
* Takes the footerLinks from navigation constants and returns the link based on the final part of the translation key.
36+
*
37+
* Example: {
38+
"link": "https://openjsf.org/",
39+
"text": "components.containers.footer.links.openjsf"
40+
},
41+
*
42+
*
43+
* @param key the final part of a translation string
44+
* @returns the link URL matching the translation key
45+
*/
46+
const getLinkFromTranslationKey = (key: string) => {
47+
return footerLinks.find(link => link.text.split('.').pop() === key)?.link;
48+
};
49+
50+
const richComponents = RICH_TRANSLATION_KEYS.reduce(
51+
(acc, key) => {
52+
acc[key] = (chunks: React.ReactNode) => (
53+
<Link href={getLinkFromTranslationKey(key)}>{chunks}</Link>
54+
);
55+
return acc;
56+
},
57+
{} as Record<string, (text: React.ReactNode) => JSX.Element>
58+
);
59+
60+
return (
61+
<>
62+
<p>{t.rich('components.containers.footer.legal', richComponents)}</p>
63+
64+
<p>
65+
{footerLinks.map((link, index) => (
66+
<span key={link.link}>
67+
<Link href={link.link}>{link.text}</Link>
68+
{index < footerLinks.length - 1 && ' | '}
69+
</span>
70+
))}
71+
</p>
72+
</>
73+
);
74+
};
75+
76+
export default WithLegal;

0 commit comments

Comments
 (0)