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,18 @@ export interface SeoProps {
1617 searchOrder ?: number ;
1718}
1819
20+ const deployedTranslations = [
21+ 'en' ,
22+ 'zh-hans' ,
23+ 'es' ,
24+ // We'll add more languages when they have enough content.
25+ ] ;
26+
27+ function getDomain ( languageCode : string ) : string {
28+ const subdomain = languageCode === 'en' ? '' : languageCode + '.' ;
29+ return subdomain + 'react.dev' ;
30+ }
31+
1932export const Seo = withRouter (
2033 ( {
2134 title,
@@ -26,29 +39,37 @@ export const Seo = withRouter(
2639 isHomePage,
2740 searchOrder,
2841 } : SeoProps & { router : Router } ) => {
42+ const siteDomain = getDomain ( siteConfig . languageCode ) ;
43+ const canonicalUrl = `https://${ siteDomain } ${
44+ router . asPath . split ( / [ \? \# ] / ) [ 0 ]
45+ } `;
2946 const pageTitle = isHomePage ? 'React' : title + ' – React' ;
3047 // Twitter's meta parser is not very good.
3148 const twitterTitle = pageTitle . replace ( / [ < > ] / g, '' ) ;
3249 return (
3350 < Head >
34- { /* DEFAULT */ }
35-
3651 < meta name = "viewport" content = "width=device-width, initial-scale=1" />
37-
3852 { title != null && < title key = "title" > { pageTitle } </ title > }
3953 { description != null && (
4054 < meta name = "description" key = "description" content = { description } />
4155 ) }
42- { /* <link rel="icon" type="image/x-icon" href={favicon} />
43- <link rel="apple-touch-icon" href={favicon} /> @todo favicon */ }
56+ < link rel = "canonical" href = { canonicalUrl } />
57+ < link
58+ rel = "alternate"
59+ href = { canonicalUrl . replace ( siteDomain , getDomain ( 'en' ) ) }
60+ hrefLang = "x-default"
61+ />
62+ { deployedTranslations . map ( ( languageCode ) => (
63+ < link
64+ key = { 'alt-' + languageCode }
65+ rel = "alternate"
66+ hrefLang = { languageCode }
67+ href = { canonicalUrl . replace ( siteDomain , getDomain ( languageCode ) ) }
68+ />
69+ ) ) }
4470 < meta property = "fb:app_id" content = "623268441017527" />
45- { /* OPEN GRAPH */ }
4671 < 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- />
72+ < meta property = "og:url" key = "og:url" content = { canonicalUrl } />
5273 { title != null && (
5374 < meta property = "og:title" content = { pageTitle } key = "og:title" />
5475 ) }
@@ -59,14 +80,11 @@ export const Seo = withRouter(
5980 content = { description }
6081 />
6182 ) }
62-
6383 < meta
6484 property = "og:image"
6585 key = "og:image"
66- content = { `https://react.dev ${ image } ` }
86+ content = { `https://${ siteDomain } ${ image } ` }
6787 />
68-
69- { /* TWITTER */ }
7088 < meta
7189 name = "twitter:card"
7290 key = "twitter:card"
@@ -88,11 +106,10 @@ export const Seo = withRouter(
88106 content = { description }
89107 />
90108 ) }
91-
92109 < meta
93110 name = "twitter:image"
94111 key = "twitter:image"
95- content = { `https://react.dev ${ image } ` }
112+ content = { `https://${ siteDomain } ${ image } ` }
96113 />
97114 < meta
98115 name = "google-site-verification"
0 commit comments