The Node.js® Website
at main 2.0 kB view raw
1import { useTranslations } from 'next-intl'; 2import type { RichTranslationValues } from 'next-intl'; 3 4import { siteNavigation } from '@/next.json.mjs'; 5import type { 6 FormattedMessage, 7 NavigationEntry, 8 NavigationKeys, 9} from '@/types'; 10 11type Context = Record<string, RichTranslationValues>; 12type Navigation = Record<string, NavigationEntry>; 13 14interface MappedNavigationEntry { 15 items: Array<[string, MappedNavigationEntry]>; 16 label: FormattedMessage; 17 link: string; 18} 19 20// Provides Context replacement for variables within the Link. This is also something that is not going 21// to happen in the future with `nodejs/nodejs.dev` codebase 22const replaceLinkWithContext = ( 23 link: string, 24 context?: RichTranslationValues 25) => 26 Object.entries(context || {}).reduce( 27 (finalLink, [find, replace]) => 28 finalLink.replace( 29 `{${find}}`, 30 typeof replace === 'string' ? replace : '' 31 ), 32 link 33 ); 34 35const useSiteNavigation = () => { 36 const t = useTranslations(); 37 38 const mapNavigationEntries = (entries: Navigation, context: Context = {}) => { 39 const getFormattedMessage = (label: string, key: string) => 40 t.rich(label, context[key] || {}); 41 42 return Object.entries(entries).map( 43 ([key, { label, link, items }]): [string, MappedNavigationEntry] => [ 44 key, 45 { 46 label: label ? getFormattedMessage(label, key) : '', 47 link: link ? replaceLinkWithContext(link, context[key]) : '', 48 items: items ? mapNavigationEntries(items, context) : [], 49 }, 50 ] 51 ); 52 }; 53 54 const getSideNavigation = ( 55 keys: Array<NavigationKeys>, 56 context: Context = {} 57 ) => { 58 const navigationEntries: Navigation = keys.reduce( 59 (acc, key) => ({ ...acc, [key]: siteNavigation.sideNavigation[key] }), 60 {} 61 ); 62 63 return mapNavigationEntries(navigationEntries, context); 64 }; 65 66 const navigationItems = mapNavigationEntries(siteNavigation.topNavigation); 67 68 return { getSideNavigation, navigationItems }; 69}; 70 71export default useSiteNavigation;