@@ -6,14 +6,13 @@ import { ContentTreeArray, previewImageDimensions } from "@/utils/data";
66import LinkIcon from "/public/svgs/link-icon.svg" ;
77import WorldIcon from "/public/svgs/world-icon.svg" ;
88import allSources from "@/public/sources-data.json" ;
9- import allSourcesCount from "@/public/source-count-data.json" ;
109import {
1110 constructSlugPaths ,
11+ convertSlugToLanguageSlug ,
1212 deriveAlternateLanguages ,
1313 deriveSourcesList ,
1414 fetchTranscriptDetails ,
1515 loopArrOrObject ,
16- unsluggify ,
1716} from "@/utils" ;
1817import { ArrowLinkRight } from "@bitcoin-dev-project/bdp-ui/icons" ;
1918import {
@@ -28,6 +27,8 @@ import { LanguageCode, LanguageCodes, OtherSupportedLanguages } from "@/config";
2827import { SourceTree } from "@/types" ;
2928import { arrayWithoutElementAtIndex , traverseSourceTree } from "@/utils/sources" ;
3029import { parseLanguageString } from "@/utils/locale" ;
30+ import useTranslations from "@/hooks/useTranslations" ;
31+ import { buildMetadata } from "@/utils/metadata" ;
3132
3233// forces 404 for paths not generated from `generateStaticParams` function.
3334export const dynamicParams = false ;
@@ -54,18 +55,22 @@ export function generateStaticParams() {
5455 return combineSlugs ;
5556}
5657
57- const checkIfSourcesLanguageRoute = ( slug : string [ ] ) => slug . length === 2 && OtherSupportedLanguages . includes ( slug [ 0 ] as LanguageCode ) && slug [ 1 ] === "sources" ;
58+ export const generateMetadata = async ( { params} : { params : { slug : string [ ] } } ) : Promise < Metadata > => {
59+
60+ const slug = params . slug ?? [ ] ;
5861
62+ const slugUrl = slug . join ( "/" ) ;
5963
60- export const generateMetadata = async ( { params} : { params : { slug : string [ ] } } ) : Promise < Metadata > => {
64+ // convert the slug to language slug, ensuring that the language code is included as the first element of the array
65+ const languagePath = convertSlugToLanguageSlug ( slug ) ;
6166
62- const isSourcesLanguageRoute = checkIfSourcesLanguageRoute ( params . slug ) ;
67+ const language = languagePath [ 0 ] ;
6368
64- const id = params . slug [ 0 ]
65- const foundSource = allSourcesCount . find ( ( source ) => source . slug === id ) ;
69+ // is it base source path, e.g [ 'sources' ] (which is converted to [ 'en', 'sources' ]) or [ '{language}', 'sources' ] (which is not converted)
70+ const isSourcesLanguageRoute = languagePath . length === 2 && languagePath [ 1 ] === "sources" ;
6671
6772 if ( isSourcesLanguageRoute ) {
68- const languageCode = params . slug [ 0 ] as LanguageCode ;
73+ const languageCode = languagePath [ 0 ] as LanguageCode ;
6974 const { alternateLanguages, metadataLanguages } = deriveAlternateLanguages ( {
7075 languageCode,
7176 languages : LanguageCodes ,
@@ -78,33 +83,16 @@ export const generateMetadata = async ({params}: { params: { slug: string[] } })
7883 canonical : "/sources" ,
7984 languages : metadataLanguages // Add custom metadata for languages
8085 } ,
81- openGraph :{
82- images :[ {
83- url :`/api/og-image/${ foundSource ?. slug } ` ,
84- width : previewImageDimensions . width ,
85- height : previewImageDimensions . height ,
86- alt : `${ foundSource ?. name } OG Image`
87- } ]
88- } ,
89- twitter :{
90- images :[ {
91- url :`/api/og-image/${ foundSource ?. slug } ` ,
92- width : previewImageDimensions . width ,
93- height : previewImageDimensions . height ,
94- alt : `${ foundSource ?. name } OG Image`
95- } ]
96- } ,
9786 other : {
9887 alternateLanguages,
9988 language : languageCode
10089 }
10190 } ;
10291 }
10392
104-
105- const slug = params . slug ?? [ ] ;
10693 const contentTree = allSources as SourceTree ;
10794 const { slugPaths } = constructSlugPaths ( slug ) ;
95+
10896 let current : any = contentTree ;
10997
11098 for ( const part of slugPaths ) {
@@ -115,8 +103,7 @@ export const generateMetadata = async ({params}: { params: { slug: string[] } })
115103 }
116104 }
117105
118- const language = slugPaths [ 1 ] ;
119-
106+ // for e.g [ 'advancing-bitcoin', 'en' ], [ 'advancing-bitcoin', 'es' ] etc
120107 if ( slugPaths . length === 2 ) {
121108 // returns all language keys for the current source
122109 const languages = Object . keys ( contentTree [ slugPaths [ 0 ] ] ) ;
@@ -127,19 +114,21 @@ export const generateMetadata = async ({params}: { params: { slug: string[] } })
127114 return acc ;
128115 } , { } as Record < string , string > ) ;
129116
130- return {
117+ return buildMetadata ( {
131118 title : current . metadata . title ,
132- alternates : {
133- canonical : "/" ,
134- languages : metadataLanguages // Add custom metadata for languages
119+ alternateLanguages : otherLanguages ,
120+ metadataLanguages,
121+ language,
122+ canonical : "/" ,
123+ generateOpenGraphImage : {
124+ url : `/api/opengraph-image/${ slugUrl } ` ,
125+ alt : `${ current . metadata . title } OG Image` ,
135126 } ,
136- other : {
137- alternateLanguages : otherLanguages ,
138- language
139- }
140- } ;
127+ } ) ;
141128 }
142129
130+ // catch every other source (nested sources)
131+
143132 const alternateLanguages = LanguageCodes . filter ( lang => lang !== language ) . map ( language => {
144133 const slugPathTocheckForData = slugPaths . filter ( path => path !== "data" ) ;
145134 slugPathTocheckForData [ 1 ] = language ;
@@ -157,17 +146,17 @@ export const generateMetadata = async ({params}: { params: { slug: string[] } })
157146 return acc ;
158147 } , { } as Record < string , string > ) ;
159148
160- return {
149+ return buildMetadata ( {
161150 title : current . metadata . title ,
162- alternates : {
163- canonical : "/" ,
164- languages : metadataLanguages // Add custom metadata for languages
151+ alternateLanguages,
152+ metadataLanguages,
153+ language,
154+ canonical : "/" ,
155+ generateOpenGraphImage : {
156+ url : `/api/opengraph-image/${ slugUrl } ` ,
157+ alt : `${ current . metadata . title } OG Image` ,
165158 } ,
166- other : {
167- alternateLanguages,
168- language
169- }
170- }
159+ } ) ;
171160} ;
172161
173162const page = ( { params } : { params : { slug : string [ ] } } ) => {
@@ -181,8 +170,6 @@ const page = ({ params }: { params: { slug: string[] } }) => {
181170 // catch language code followed by sources e.g ["es", "sources"]. English is omitted
182171 const isRouteForLanguage = slug . length === 2 && OtherSupportedLanguages . includes ( slug [ 0 ] as LanguageCode ) && slug [ 1 ] === "sources" ;
183172
184- // console.log({isRouteForLanguage})
185-
186173 if ( isRouteForLanguage ) {
187174 const language = slug [ 0 ] ;
188175 const sourcesAndLanguage = Object . keys ( allSources ) ;
@@ -200,9 +187,8 @@ const page = ({ params }: { params: { slug: string[] } }) => {
200187 return (
201188 < div className = "flex flex-col text-black" >
202189 < TranscriptContentPage
203- header = "Sources"
190+ header = 'sources'
204191 data = { languageTreeArray }
205- description = 'Sources help you find transcripts within a specific talk, meetup, conference, and the likes.'
206192 type = 'alphabet'
207193 linkName = 'sources'
208194 languageCode = { language as LanguageCode }
@@ -222,19 +208,22 @@ const page = ({ params }: { params: { slug: string[] } }) => {
222208 }
223209 }
224210
211+ const slugPathsCopy = [ ...slugPaths ] . filter ( item => item !== "data" )
212+ const language = slugPathsCopy . splice ( 1 , 1 ) [ 0 ] as LanguageCode
213+
225214 const metadata = current . metadata ;
226215 const data = loopArrOrObject ( current ?. data ) ;
227216 const isRoot = Array . isArray ( current . data ) ;
228217 const { transcripts } = fetchTranscriptDetails ( allTranscripts , data , isRoot ) ;
229218
230219 const constructBackLink = ( ) => {
231- const slugPathsCopy = [ ...slugPaths ] . filter ( item => item !== "data" )
232- const language = slugPathsCopy . splice ( 1 , 1 ) [ 0 ]
233220 const indexPath = language === "en" ? "" : `/${ language } `
234221 const backRoute = slugPathsCopy . slice ( 0 , - 1 ) . length ? slugPathsCopy . slice ( 0 , - 1 ) . join ( "/" ) : ""
235222 return backRoute ? `${ indexPath } /${ backRoute } ` : `${ indexPath } /sources`
236223 }
237224
225+ const t = useTranslations ( language ) ;
226+
238227 return (
239228 < div className = "flex items-start lg:gap-[50px]" >
240229 < div className = "flex flex-col w-full gap-6 md:gap-8 2xl:gap-10 no-scrollbar" >
@@ -249,9 +238,9 @@ const page = ({ params }: { params: { slug: string[] } }) => {
249238 < SourcesBreadCrumbs slugPaths = { slugPaths } current = { contentTree } />
250239 </ >
251240 < div className = 'flex flex-col' >
252- < Link href = { constructBackLink ( ) } className = 'flex gap-1 items-center' >
241+ < Link href = { constructBackLink ( ) } className = 'flex gap-1 items-center max-w-fit ' >
253242 < ArrowLinkRight className = 'rotate-180 w-5 md:w-6' />
254- < p > Back </ p >
243+ < p > { t ( "explore.back" ) } </ p >
255244 </ Link >
256245
257246 < h3 className = "text-xl 2xl:text-2xl font-medium pt-6 md:pt-3" >
0 commit comments