55import * as React from 'react' ;
66import Head from 'next/head' ;
77import { withRouter , Router } from 'next/router' ;
8+ import { siteConfig } from '../siteConfig' ;
89
910export interface SeoProps {
1011 title : string ;
@@ -16,6 +17,16 @@ export interface SeoProps {
1617 searchOrder ?: number ;
1718}
1819
20+ const deployedTranslations = [
21+ 'en' ,
22+ // We'll add more languages when they have enough content.
23+ ] ;
24+
25+ function getDomain ( languageCode : string ) : string {
26+ const subdomain = languageCode === 'en' ? '' : languageCode + '.' ;
27+ return subdomain + 'react.dev' ;
28+ }
29+
1930export const Seo = withRouter (
2031 ( {
2132 title,
@@ -26,29 +37,37 @@ export const Seo = withRouter(
2637 isHomePage,
2738 searchOrder,
2839 } : SeoProps & { router : Router } ) => {
40+ const siteDomain = getDomain ( siteConfig . languageCode ) ;
41+ const canonicalUrl = `https://${ siteDomain } ${
42+ router . asPath . split ( / [ \? \# ] / ) [ 0 ]
43+ } `;
2944 const pageTitle = isHomePage ? 'React' : title + ' – React' ;
3045 // Twitter's meta parser is not very good.
3146 const twitterTitle = pageTitle . replace ( / [ < > ] / g, '' ) ;
3247 return (
3348 < Head >
34- { /* DEFAULT */ }
35-
3649 < meta name = "viewport" content = "width=device-width, initial-scale=1" />
37-
3850 { title != null && < title key = "title" > { pageTitle } </ title > }
3951 { description != null && (
4052 < meta name = "description" key = "description" content = { description } />
4153 ) }
42- { /* <link rel="icon" type="image/x-icon" href={favicon} />
43- <link rel="apple-touch-icon" href={favicon} /> @todo favicon */ }
54+ < link rel = "canonical" href = { canonicalUrl } />
55+ < link
56+ rel = "alternate"
57+ href = { canonicalUrl . replace ( siteDomain , getDomain ( 'en' ) ) }
58+ hrefLang = "x-default"
59+ />
60+ { deployedTranslations . map ( ( languageCode ) => (
61+ < link
62+ key = { 'alt-' + languageCode }
63+ rel = "alternate"
64+ hrefLang = { languageCode }
65+ href = { canonicalUrl . replace ( siteDomain , getDomain ( languageCode ) ) }
66+ />
67+ ) ) }
4468 < meta property = "fb:app_id" content = "623268441017527" />
45- { /* OPEN GRAPH */ }
4669 < meta property = "og:type" key = "og:type" content = "website" />
47- < meta
48- property = "og:url"
49- key = "og:url"
50- content = { `https://react.dev${ router . asPath . split ( / [ \? \# ] / ) [ 0 ] } ` }
51- />
70+ < meta property = "og:url" key = "og:url" content = { canonicalUrl } />
5271 { title != null && (
5372 < meta property = "og:title" content = { pageTitle } key = "og:title" />
5473 ) }
@@ -59,14 +78,11 @@ export const Seo = withRouter(
5978 content = { description }
6079 />
6180 ) }
62-
6381 < meta
6482 property = "og:image"
6583 key = "og:image"
66- content = { `https://react.dev ${ image } ` }
84+ content = { `https://${ siteDomain } ${ image } ` }
6785 />
68-
69- { /* TWITTER */ }
7086 < meta
7187 name = "twitter:card"
7288 key = "twitter:card"
@@ -88,11 +104,10 @@ export const Seo = withRouter(
88104 content = { description }
89105 />
90106 ) }
91-
92107 < meta
93108 name = "twitter:image"
94109 key = "twitter:image"
95- content = { `https://react.dev ${ image } ` }
110+ content = { `https://${ siteDomain } ${ image } ` }
96111 />
97112 < meta
98113 name = "google-site-verification"
0 commit comments