aboutsummaryrefslogtreecommitdiffstats
path: root/src/pages
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-01-29 18:21:37 +0100
committerArmand Philippot <git@armandphilippot.com>2022-01-29 19:02:57 +0100
commite4d5b8151802517b2943756fc0d09ffa95e2c4e2 (patch)
tree9e99137a7b64ea7993a8311a7162336a551be8b2 /src/pages
parent47b854de26dea24e7838fd0804df103dee99635f (diff)
chore: replace lingui functions with react-intl
Diffstat (limited to 'src/pages')
-rw-r--r--src/pages/404.tsx62
-rw-r--r--src/pages/article/[slug].tsx6
-rw-r--r--src/pages/blog/index.tsx78
-rw-r--r--src/pages/contact.tsx95
-rw-r--r--src/pages/cv.tsx55
-rw-r--r--src/pages/index.tsx69
-rw-r--r--src/pages/mentions-legales.tsx35
-rw-r--r--src/pages/projets.tsx30
-rw-r--r--src/pages/recherche/index.tsx68
-rw-r--r--src/pages/sujet/[slug].tsx20
-rw-r--r--src/pages/thematique/[slug].tsx20
11 files changed, 424 insertions, 114 deletions
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
index 64c74ba..079dead 100644
--- a/src/pages/404.tsx
+++ b/src/pages/404.tsx
@@ -1,44 +1,70 @@
import { getLayout } from '@components/Layouts/Layout';
import PostHeader from '@components/PostHeader/PostHeader';
-import { seo } from '@config/seo';
-import { t, Trans } from '@lingui/macro';
+import { config } from '@config/website';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
-import { loadTranslation } from '@utils/helpers/i18n';
+import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import Link from 'next/link';
+import { FormattedMessage, useIntl } from 'react-intl';
+
+const Error404: NextPageWithLayout = () => {
+ const intl = useIntl();
+
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'Error 404: Page not found - {websiteName}',
+ description: '404Page: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage({
+ defaultMessage: 'Page not found.',
+ description: '404Page: SEO - Meta description',
+ });
-const error404: NextPageWithLayout = () => {
return (
<>
<Head>
- <title>{seo.error404.title}</title>
- <meta name="description" content={seo.error404.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
</Head>
<div className={`${styles.article} ${styles['article--no-comments']}`}>
- <PostHeader title={t`Page not found`} />
+ <PostHeader
+ title={intl.formatMessage({
+ defaultMessage: 'Page not found',
+ description: '404Page: page title',
+ })}
+ />
<div className={styles.body}>
- <Trans>
- Sorry, it seems that the page you are looking for does not exist.
- </Trans>{' '}
- <Trans>
- If you think this path should work, feel free to{' '}
- <Link href="/contact/">contact me</Link> with the necessary
- information so that I can fix the problem.
- </Trans>
+ <FormattedMessage
+ defaultMessage="Sorry, it seems that the page your are looking for does not exist. If you think this path should work, feel free to <link>contact me</link> with the necessary information so that I can fix the problem."
+ description="404Page: page body"
+ values={{
+ link: (chunks: string) => (
+ <Link href="/contact/">
+ <a>{chunks}</a>
+ </Link>
+ ),
+ }}
+ />
</div>
</div>
</>
);
};
-error404.getLayout = getLayout;
+Error404.getLayout = getLayout;
export const getStaticProps: GetStaticProps = async (
context: GetStaticPropsContext
) => {
- const breadcrumbTitle = t`Error`;
+ const intl = await getIntlInstance();
+ const breadcrumbTitle = intl.formatMessage({
+ defaultMessage: 'Error 404',
+ description: '404Page: breadcrumb item',
+ });
const { locale } = context;
const translation = await loadTranslation(locale);
@@ -51,4 +77,4 @@ export const getStaticProps: GetStaticProps = async (
};
};
-export default error404;
+export default Error404;
diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
index ce9c22b..8668a66 100644
--- a/src/pages/article/[slug].tsx
+++ b/src/pages/article/[slug].tsx
@@ -18,6 +18,7 @@ import { useRouter } from 'next/router';
import Prism from 'prismjs';
import { ParsedUrlQuery } from 'querystring';
import { useEffect } from 'react';
+import { useIntl } from 'react-intl';
import { Blog, BlogPosting, Graph, WebPage } from 'schema-dts';
const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
@@ -45,6 +46,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
wordsCount: info.wordsCount,
};
+ const intl = useIntl();
const router = useRouter();
const locale = router.locale ? router.locale : config.locales.defaultLocale;
const articleUrl = `${config.url}${router.asPath}`;
@@ -55,8 +57,8 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
});
useEffect(() => {
- translateCopyButton(locale);
- }, [locale]);
+ translateCopyButton(locale, intl);
+ }, [intl, locale]);
const webpageSchema: WebPage = {
'@id': `${articleUrl}`,
diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx
index 8e42e02..9a86d9f 100644
--- a/src/pages/blog/index.tsx
+++ b/src/pages/blog/index.tsx
@@ -6,22 +6,22 @@ import PostsList from '@components/PostsList/PostsList';
import Sidebar from '@components/Sidebar/Sidebar';
import Spinner from '@components/Spinner/Spinner';
import { ThematicsList, TopicsList } from '@components/Widgets';
-import { seo } from '@config/seo';
import { config } from '@config/website';
-import { t } from '@lingui/macro';
import { getPublishedPosts } from '@services/graphql/queries';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
import { BlogPageProps, PostsList as PostsListData } from '@ts/types/blog';
-import { loadTranslation } from '@utils/helpers/i18n';
+import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useEffect, useRef, useState } from 'react';
+import { useIntl } from 'react-intl';
import { Blog as BlogSchema, Graph, WebPage } from 'schema-dts';
import useSWRInfinite from 'swr/infinite';
const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => {
+ const intl = useIntl();
const lastPostRef = useRef<HTMLSpanElement>(null);
const router = useRouter();
@@ -76,21 +76,39 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => {
};
const getPostsList = () => {
- if (error) return t`Failed to load.`;
+ if (error)
+ return intl.formatMessage({
+ defaultMessage: 'Failed to load.',
+ description: 'BlogPage: failed to load text',
+ });
if (!data) return <Spinner />;
return <PostsList ref={lastPostRef} data={data} showYears={true} />;
};
- const title = t`Blog`;
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'Blog: development, open source - {websiteName}',
+ description: 'BlogPage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage:
+ "Discover {websiteName}'s writings. He talks about web development, Linux and open source mostly.",
+ description: 'BlogPage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
const pageUrl = `${config.url}${router.asPath}`;
const webpageSchema: WebPage = {
'@id': `${pageUrl}`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.blog.title,
- description: seo.blog.description,
+ name: pageTitle,
+ description: pageDescription,
inLanguage: config.locales.defaultLocale,
reviewedBy: { '@id': `${config.url}/#branding` },
url: `${config.url}`,
@@ -115,15 +133,20 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => {
'@graph': [webpageSchema, blogSchema],
};
+ const title = intl.formatMessage({
+ defaultMessage: 'Blog',
+ description: 'BlogPage: page title',
+ });
+
return (
<>
<Head>
- <title>{seo.blog.title}</title>
- <meta name="description" content={seo.blog.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:url" content={`${pageUrl}`} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
- <meta property="og:description" content={seo.blog.description} />
+ <meta property="og:description" content={pageDescription} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
@@ -146,13 +169,34 @@ const Blog: NextPageWithLayout<BlogPageProps> = ({ fallback }) => {
isDisabled={isLoadingMore}
clickHandler={loadMorePosts}
position="center"
- >{t`Load more?`}</Button>
+ >
+ {intl.formatMessage({
+ defaultMessage: 'Load more?',
+ description: 'BlogPage: load more text',
+ })}
+ </Button>
</>
)}
</div>
- <Sidebar position="right" title={t`Filter by`}>
- <ThematicsList title={t`Thematics`} />
- <TopicsList title={t`Topics`} />
+ <Sidebar
+ position="right"
+ title={intl.formatMessage({
+ defaultMessage: 'Filter by:',
+ description: 'BlogPage: sidebar title',
+ })}
+ >
+ <ThematicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Thematics',
+ description: 'BlogPage: thematics list widget title',
+ })}
+ />
+ <TopicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Topics',
+ description: 'BlogPage: topics list widget title',
+ })}
+ />
</Sidebar>
</article>
</>
@@ -164,7 +208,11 @@ Blog.getLayout = getLayout;
export const getStaticProps: GetStaticProps = async (
context: GetStaticPropsContext
) => {
- const breadcrumbTitle = t`Blog`;
+ const intl = await getIntlInstance();
+ const breadcrumbTitle = intl.formatMessage({
+ defaultMessage: 'Blog',
+ description: 'BlogPage: breadcrumb item',
+ });
const data = await getPublishedPosts({ first: config.postsPerPage });
const { locale } = context;
const translation = await loadTranslation(locale);
diff --git a/src/pages/contact.tsx b/src/pages/contact.tsx
index 464854d..489135d 100644
--- a/src/pages/contact.tsx
+++ b/src/pages/contact.tsx
@@ -4,20 +4,20 @@ import { getLayout } from '@components/Layouts/Layout';
import PostHeader from '@components/PostHeader/PostHeader';
import Sidebar from '@components/Sidebar/Sidebar';
import { SocialMedia } from '@components/Widgets';
-import { seo } from '@config/seo';
import { config } from '@config/website';
-import { t } from '@lingui/macro';
import { sendMail } from '@services/graphql/mutations';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
-import { loadTranslation } from '@utils/helpers/i18n';
+import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { FormEvent, useState } from 'react';
+import { useIntl } from 'react-intl';
import { ContactPage as ContactPageSchema, Graph, WebPage } from 'schema-dts';
const ContactPage: NextPageWithLayout = () => {
+ const intl = useIntl();
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [subject, setSubject] = useState('');
@@ -46,26 +46,54 @@ const ContactPage: NextPageWithLayout = () => {
if (mail.sent) {
setStatus(
- t`Thanks. Your message was successfully sent. I will answer it as soon as possible.`
+ intl.formatMessage({
+ defaultMessage:
+ 'Thanks. Your message was successfully sent. I will answer it as soon as possible.',
+ description: 'ContactPage: success message',
+ })
);
resetForm();
} else {
- const errorPrefix = t`An error occurred:`;
+ const errorPrefix = intl.formatMessage({
+ defaultMessage: 'An error occurred:',
+ description: 'ContactPage: error message',
+ });
const error = `${errorPrefix} ${mail.message}`;
setStatus(error);
}
};
- const title = t`Contact`;
- const intro = t`Please fill the form to contact me.`;
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'Contact form - {websiteName}',
+ description: 'ContactPage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage:
+ "Contact {websiteName} through its website. All you need to do it's to fill the contact form.",
+ description: 'ContactPage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
const pageUrl = `${config.url}${router.asPath}`;
+ const title = intl.formatMessage({
+ defaultMessage: 'Contact',
+ description: 'ContactPage: page title',
+ });
+ const intro = intl.formatMessage({
+ defaultMessage: 'Please fill the form to contact me.',
+ description: 'ContactPage: page introduction',
+ });
const webpageSchema: WebPage = {
'@id': `${pageUrl}`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.contact.title,
- description: seo.contact.description,
+ name: pageTitle,
+ description: pageDescription,
reviewedBy: { '@id': `${config.url}/#branding` },
url: `${pageUrl}`,
isPartOf: {
@@ -94,8 +122,8 @@ const ContactPage: NextPageWithLayout = () => {
return (
<>
<Head>
- <title>{seo.contact.title}</title>
- <meta name="description" content={seo.contact.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:url" content={`${pageUrl}`} />
<meta property="og:type" content="article" />
<meta property="og:title" content={title} />
@@ -111,7 +139,12 @@ const ContactPage: NextPageWithLayout = () => {
>
<PostHeader title={title} intro={intro} />
<div className={styles.body}>
- <p>{t`All fields marked with * are required.`}</p>
+ <p>
+ {intl.formatMessage({
+ defaultMessage: 'All fields marked with * are required.',
+ description: 'ContactPage: required fields text',
+ })}
+ </p>
{status && <p>{status}</p>}
<Form submitHandler={submitHandler}>
<FormItem>
@@ -120,7 +153,10 @@ const ContactPage: NextPageWithLayout = () => {
name="name"
value={name}
setValue={setName}
- label={t`Name`}
+ label={intl.formatMessage({
+ defaultMessage: 'Name',
+ description: 'ContactPage: name field label',
+ })}
required={true}
/>
</FormItem>
@@ -130,7 +166,10 @@ const ContactPage: NextPageWithLayout = () => {
name="email"
value={email}
setValue={setEmail}
- label={t`Email`}
+ label={intl.formatMessage({
+ defaultMessage: 'Email',
+ description: 'ContactPage: email field label',
+ })}
required={true}
/>
</FormItem>
@@ -140,7 +179,10 @@ const ContactPage: NextPageWithLayout = () => {
name="subject"
value={subject}
setValue={setSubject}
- label={t`Subject`}
+ label={intl.formatMessage({
+ defaultMessage: 'Subject',
+ description: 'ContactPage: subject field label',
+ })}
/>
</FormItem>
<FormItem>
@@ -149,18 +191,29 @@ const ContactPage: NextPageWithLayout = () => {
name="message"
value={message}
setValue={setMessage}
- label={t`Message`}
+ label={intl.formatMessage({
+ defaultMessage: 'Message',
+ description: 'ContactPage: message field label',
+ })}
required={true}
/>
</FormItem>
<FormItem>
- <ButtonSubmit>{t`Send`}</ButtonSubmit>
+ <ButtonSubmit>
+ {intl.formatMessage({
+ defaultMessage: 'Send',
+ description: 'ContactPage: send button text',
+ })}
+ </ButtonSubmit>
</FormItem>
</Form>
</div>
<Sidebar position="right">
<SocialMedia
- title={t`Find me elsewhere`}
+ title={intl.formatMessage({
+ defaultMessage: 'Find me elsewhere',
+ description: 'ContactPage: social media widget title',
+ })}
github={true}
gitlab={true}
linkedin={true}
@@ -176,7 +229,11 @@ ContactPage.getLayout = getLayout;
export const getStaticProps: GetStaticProps = async (
context: GetStaticPropsContext
) => {
- const breadcrumbTitle = t`Contact`;
+ const intl = await getIntlInstance();
+ const breadcrumbTitle = intl.formatMessage({
+ defaultMessage: 'Contact',
+ description: 'ContactPage: breadcrumb item',
+ });
const { locale } = context;
const translation = await loadTranslation(locale);
diff --git a/src/pages/cv.tsx b/src/pages/cv.tsx
index a851c38..c3686de 100644
--- a/src/pages/cv.tsx
+++ b/src/pages/cv.tsx
@@ -2,10 +2,8 @@ import { getLayout } from '@components/Layouts/Layout';
import PostHeader from '@components/PostHeader/PostHeader';
import Sidebar from '@components/Sidebar/Sidebar';
import { CVPreview, SocialMedia, ToC } from '@components/Widgets';
-import { seo } from '@config/seo';
import { config } from '@config/website';
import CVContent, { intro, meta, pdf, image } from '@content/pages/cv.mdx';
-import { t } from '@lingui/macro';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
import { ArticleMeta } from '@ts/types/articles';
@@ -13,9 +11,11 @@ import { loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
+import { useIntl } from 'react-intl';
import { AboutPage, Graph, WebPage } from 'schema-dts';
const CV: NextPageWithLayout = () => {
+ const intl = useIntl();
const router = useRouter();
const dates = {
publication: meta.publishedOn,
@@ -26,13 +26,28 @@ const CV: NextPageWithLayout = () => {
dates,
};
const pageUrl = `${config.url}${router.asPath}`;
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'CV Front-end developer - {websiteName}',
+ description: 'CVPage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage:
+ 'Discover the curriculum of {websiteName}, front-end developer located in France: skills, experiences and training.',
+ description: 'CVPage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
const webpageSchema: WebPage = {
'@id': `${pageUrl}`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.cv.title,
- description: seo.cv.description,
+ name: pageTitle,
+ description: pageDescription,
reviewedBy: { '@id': `${config.url}/#branding` },
url: `${pageUrl}`,
isPartOf: {
@@ -46,7 +61,7 @@ const CV: NextPageWithLayout = () => {
const cvSchema: AboutPage = {
'@id': `${config.url}/#cv`,
'@type': 'AboutPage',
- name: `${config.name} CV`,
+ name: pageTitle,
description: intro,
author: { '@id': `${config.url}/#branding` },
creator: { '@id': `${config.url}/#branding` },
@@ -66,17 +81,25 @@ const CV: NextPageWithLayout = () => {
'@graph': [webpageSchema, cvSchema],
};
+ const title = intl.formatMessage(
+ {
+ defaultMessage: "{name}'s CV",
+ description: 'CVPage: page title',
+ },
+ { name: config.name }
+ );
+
return (
<>
<Head>
- <title>{seo.cv.title}</title>
- <meta name="description" content={seo.cv.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:url" content={`${pageUrl}`} />
<meta property="og:type" content="article" />
- <meta property="og:title" content={`${config.name} CV`} />
+ <meta property="og:title" content={title} />
<meta property="og:description" content={intro} />
<meta property="og:image" content={image} />
- <meta property="og:image:alt" content={`${config.name} CV`} />
+ <meta property="og:image:alt" content={title} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
@@ -94,9 +117,19 @@ const CV: NextPageWithLayout = () => {
<CVContent />
</div>
<Sidebar position="right">
- <CVPreview title={t`Other formats`} imgSrc={image} pdf={pdf} />
+ <CVPreview
+ title={intl.formatMessage({
+ defaultMessage: 'Others formats',
+ description: 'CVPage: cv preview widget title',
+ })}
+ imgSrc={image}
+ pdf={pdf}
+ />
<SocialMedia
- title={t`Open-source projects`}
+ title={intl.formatMessage({
+ defaultMessage: 'Open-source projects',
+ description: 'CVPage: social media widget title',
+ })}
github={true}
gitlab={true}
/>
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 264c45a..41a4603 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -2,29 +2,38 @@ import FeedIcon from '@assets/images/icon-feed.svg';
import { ButtonLink } from '@components/Buttons';
import { ContactIcon } from '@components/Icons';
import Layout from '@components/Layouts/Layout';
-import { seo } from '@config/seo';
import { config } from '@config/website';
import HomePageContent from '@content/pages/homepage.mdx';
-import { t } from '@lingui/macro';
import styles from '@styles/pages/Home.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
import { loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import type { ReactElement } from 'react';
+import { useIntl } from 'react-intl';
import { Graph, WebPage } from 'schema-dts';
const Home: NextPageWithLayout = () => {
+ const intl = useIntl();
+
const CodingLinks = () => {
return (
<ul className={styles['links-list']}>
<li>
<ButtonLink target="/thematique/developpement-web">
- {t`Web development`}
+ {intl.formatMessage({
+ defaultMessage: 'Web development',
+ description: 'HomePage: link to web development thematic',
+ })}
</ButtonLink>
</li>
<li>
- <ButtonLink target="/projets">{t`Projects`}</ButtonLink>
+ <ButtonLink target="/projets">
+ {intl.formatMessage({
+ defaultMessage: 'Projects',
+ description: 'HomePage: link to projects',
+ })}
+ </ButtonLink>
</li>
</ul>
);
@@ -57,10 +66,20 @@ const Home: NextPageWithLayout = () => {
return (
<ul className={styles['links-list']}>
<li>
- <ButtonLink target="/thematique/libre">{t`Free`}</ButtonLink>
+ <ButtonLink target="/thematique/libre">
+ {intl.formatMessage({
+ defaultMessage: 'Free',
+ description: 'HomePage: link to free thematic',
+ })}
+ </ButtonLink>
</li>
<li>
- <ButtonLink target="/thematique/linux">{t`Linux`}</ButtonLink>
+ <ButtonLink target="/thematique/linux">
+ {intl.formatMessage({
+ defaultMessage: 'Linux',
+ description: 'HomePage: link to Linux thematic',
+ })}
+ </ButtonLink>
</li>
</ul>
);
@@ -72,13 +91,19 @@ const Home: NextPageWithLayout = () => {
<li>
<ButtonLink target="/contact">
<ContactIcon />
- {t`Contact me`}
+ {intl.formatMessage({
+ defaultMessage: 'Contact me',
+ description: 'HomePage: contact button text',
+ })}
</ButtonLink>
</li>
<li>
<ButtonLink target="/feed">
<FeedIcon className={styles['icon--feed']} />
- {t`Subscribe`}
+ {intl.formatMessage({
+ defaultMessage: 'Subscribe',
+ description: 'HomePage: RSS feed subscription text',
+ })}
</ButtonLink>
</li>
</ul>
@@ -92,12 +117,28 @@ const Home: NextPageWithLayout = () => {
MoreLinks: MoreLinks,
};
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: '{websiteName} | Front-end developer: WordPress/React',
+ description: 'HomePage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage:
+ '{websiteName} is a front-end developer located in France. He codes and he writes mostly about web development and open-source.',
+ description: 'HomePage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
+
const webpageSchema: WebPage = {
'@id': `${config.url}/#home`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.legalNotice.title,
- description: seo.legalNotice.description,
+ name: pageTitle,
+ description: pageDescription,
author: { '@id': `${config.url}/#branding` },
creator: { '@id': `${config.url}/#branding` },
editor: { '@id': `${config.url}/#branding` },
@@ -115,12 +156,12 @@ const Home: NextPageWithLayout = () => {
return (
<>
<Head>
- <title>{seo.homepage.title}</title>
- <meta name="description" content={seo.homepage.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:type" content="website" />
<meta property="og:url" content={`${config.url}`} />
- <meta property="og:title" content={seo.homepage.title} />
- <meta property="og:description" content={seo.homepage.description} />
+ <meta property="og:title" content={pageTitle} />
+ <meta property="og:description" content={pageDescription} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
diff --git a/src/pages/mentions-legales.tsx b/src/pages/mentions-legales.tsx
index e13a7e2..0ec92a2 100644
--- a/src/pages/mentions-legales.tsx
+++ b/src/pages/mentions-legales.tsx
@@ -2,13 +2,11 @@ import { getLayout } from '@components/Layouts/Layout';
import PostHeader from '@components/PostHeader/PostHeader';
import Sidebar from '@components/Sidebar/Sidebar';
import { ToC } from '@components/Widgets';
-import { seo } from '@config/seo';
import { config } from '@config/website';
import LegalNoticeContent, {
intro,
meta,
} from '@content/pages/legal-notice.mdx';
-import { t } from '@lingui/macro';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
import { ArticleMeta } from '@ts/types/articles';
@@ -16,9 +14,11 @@ import { loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
+import { useIntl } from 'react-intl';
import { Article, Graph, WebPage } from 'schema-dts';
const LegalNotice: NextPageWithLayout = () => {
+ const intl = useIntl();
const router = useRouter();
const dates = {
publication: meta.publishedOn,
@@ -28,8 +28,25 @@ const LegalNotice: NextPageWithLayout = () => {
const pageMeta: ArticleMeta = {
dates,
};
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'Legal notice - {websiteName}',
+ description: 'LegalNoticePage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage: "Discover the legal notice of {websiteName}'s website.",
+ description: 'LegalNoticePage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
const pageUrl = `${config.url}${router.asPath}`;
-
+ const title = intl.formatMessage({
+ defaultMessage: 'Legal notice',
+ description: 'LegalNoticePage: page title',
+ });
const publicationDate = new Date(dates.publication);
const updateDate = new Date(dates.update);
@@ -37,8 +54,8 @@ const LegalNotice: NextPageWithLayout = () => {
'@id': `${pageUrl}`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.legalNotice.title,
- description: seo.legalNotice.description,
+ name: pageTitle,
+ description: pageDescription,
inLanguage: config.locales.defaultLocale,
license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
reviewedBy: { '@id': `${config.url}/#branding` },
@@ -51,7 +68,7 @@ const LegalNotice: NextPageWithLayout = () => {
const articleSchema: Article = {
'@id': `${config.url}/#legal-notice`,
'@type': 'Article',
- name: t`Legal notice`,
+ name: title,
description: intro,
author: { '@id': `${config.url}/#branding` },
copyrightYear: publicationDate.getFullYear(),
@@ -73,11 +90,11 @@ const LegalNotice: NextPageWithLayout = () => {
return (
<>
<Head>
- <title>{seo.legalNotice.title}</title>
- <meta name="description" content={seo.legalNotice.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:url" content={`${pageUrl}`} />
<meta property="og:type" content="article" />
- <meta property="og:title" content={t`Legal notice`} />
+ <meta property="og:title" content={pageTitle} />
<meta property="og:description" content={intro} />
<script
type="application/ld+json"
diff --git a/src/pages/projets.tsx b/src/pages/projets.tsx
index 263973d..da4523c 100644
--- a/src/pages/projets.tsx
+++ b/src/pages/projets.tsx
@@ -1,7 +1,6 @@
import { getLayout } from '@components/Layouts/Layout';
import PostHeader from '@components/PostHeader/PostHeader';
import ProjectsList from '@components/ProjectsList/ProjectsList';
-import { seo } from '@config/seo';
import { config } from '@config/website';
import PageContent, { meta } from '@content/pages/projects.mdx';
import styles from '@styles/pages/Projects.module.scss';
@@ -11,9 +10,11 @@ import { getSortedProjects } from '@utils/helpers/projects';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
+import { useIntl } from 'react-intl';
import { Article, Graph, WebPage } from 'schema-dts';
const Projects = ({ projects }: { projects: Project[] }) => {
+ const intl = useIntl();
const dates = {
publication: meta.publishedOn,
update: meta.updatedOn,
@@ -22,13 +23,28 @@ const Projects = ({ projects }: { projects: Project[] }) => {
const updateDate = new Date(dates.update);
const router = useRouter();
const pageUrl = `${config.url}${router.asPath}`;
+ const pageTitle = intl.formatMessage(
+ {
+ defaultMessage: 'Projects: open-source makings - {websiteName}',
+ description: 'ProjectsPage: SEO - Page title',
+ },
+ { websiteName: config.name }
+ );
+ const pageDescription = intl.formatMessage(
+ {
+ defaultMessage:
+ 'Discover {websiteName} projects. Mostly related to web development and open source.',
+ description: 'ProjectsPage: SEO - Meta description',
+ },
+ { websiteName: config.name }
+ );
const webpageSchema: WebPage = {
'@id': `${pageUrl}`,
'@type': 'WebPage',
breadcrumb: { '@id': `${config.url}/#breadcrumb` },
- name: seo.legalNotice.title,
- description: seo.legalNotice.description,
+ name: pageTitle,
+ description: pageDescription,
inLanguage: config.locales.defaultLocale,
license: 'https://creativecommons.org/licenses/by-sa/4.0/deed.fr',
reviewedBy: { '@id': `${config.url}/#branding` },
@@ -42,7 +58,7 @@ const Projects = ({ projects }: { projects: Project[] }) => {
'@id': `${config.url}/#projects`,
'@type': 'Article',
name: meta.title,
- description: seo.projects.description,
+ description: pageDescription,
author: { '@id': `${config.url}/#branding` },
copyrightYear: publicationDate.getFullYear(),
creator: { '@id': `${config.url}/#branding` },
@@ -63,12 +79,12 @@ const Projects = ({ projects }: { projects: Project[] }) => {
return (
<>
<Head>
- <title>{seo.projects.title}</title>
- <meta name="description" content={seo.projects.description} />
+ <title>{pageTitle}</title>
+ <meta name="description" content={pageDescription} />
<meta property="og:url" content={`${pageUrl}`} />
<meta property="og:type" content="article" />
<meta property="og:title" content={meta.title} />
- <meta property="og:description" content={seo.projects.description} />
+ <meta property="og:description" content={pageDescription} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schemaJsonLd) }}
diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx
index c3c71f3..857b114 100644
--- a/src/pages/recherche/index.tsx
+++ b/src/pages/recherche/index.tsx
@@ -7,19 +7,20 @@ import Sidebar from '@components/Sidebar/Sidebar';
import Spinner from '@components/Spinner/Spinner';
import { ThematicsList, TopicsList } from '@components/Widgets';
import { config } from '@config/website';
-import { t } from '@lingui/macro';
import { getPublishedPosts } from '@services/graphql/queries';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
import { PostsList as PostsListData } from '@ts/types/blog';
-import { loadTranslation } from '@utils/helpers/i18n';
+import { getIntlInstance, loadTranslation } from '@utils/helpers/i18n';
import { GetStaticProps, GetStaticPropsContext } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { useEffect, useRef, useState } from 'react';
+import { useIntl } from 'react-intl';
import useSWRInfinite from 'swr/infinite';
const Search: NextPageWithLayout = () => {
+ const intl = useIntl();
const [query, setQuery] = useState('');
const router = useRouter();
const lastPostRef = useRef<HTMLSpanElement>(null);
@@ -76,15 +77,33 @@ const Search: NextPageWithLayout = () => {
const hasNextPage = data && data[data.length - 1].pageInfo.hasNextPage;
const title = query
- ? t`Search results for: ${query}`
- : t({
- comment: 'Search page title',
- message: 'Search',
+ ? intl.formatMessage(
+ {
+ defaultMessage: 'Search results for {query}',
+ description: 'SearchPage: search results text',
+ },
+ { query }
+ )
+ : intl.formatMessage({
+ defaultMessage: 'Search',
+ description: 'SearchPage: page title',
});
const description = query
- ? t`Discover search results for: ${query}`
- : t`Search for a post on ${config.name}.`;
+ ? intl.formatMessage(
+ {
+ defaultMessage: 'Discover search results for {query}',
+ description: 'SearchPage: meta description with query',
+ },
+ { query }
+ )
+ : intl.formatMessage(
+ {
+ defaultMessage: 'Search for a post on {websiteName}',
+ description: 'SearchPage: meta description without query',
+ },
+ { websiteName: config.name }
+ );
const head = {
title: `${title} | ${config.name}`,
@@ -99,7 +118,11 @@ const Search: NextPageWithLayout = () => {
};
const getPostsList = () => {
- if (error) return t`Failed to load.`;
+ if (error)
+ return intl.formatMessage({
+ defaultMessage: 'Failed to load.',
+ description: 'SearchPage: failed to load text',
+ });
if (!data) return <Spinner />;
return <PostsList ref={lastPostRef} data={data} showYears={false} />;
@@ -127,13 +150,28 @@ const Search: NextPageWithLayout = () => {
isDisabled={isLoadingMore}
clickHandler={loadMorePosts}
position="center"
- >{t`Load more?`}</Button>
+ >
+ {intl.formatMessage({
+ defaultMessage: 'Load more?',
+ description: 'SearchPage: load more text',
+ })}
+ </Button>
</>
)}
</div>
<Sidebar position="right">
- <ThematicsList title={t`Thematics`} />
- <TopicsList title={t`Topics`} />
+ <ThematicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Thematics',
+ description: 'SearchPage: thematics list widget title',
+ })}
+ />
+ <TopicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Topics',
+ description: 'SearchPage: topics list widget title',
+ })}
+ />
</Sidebar>
</article>
</>
@@ -145,7 +183,11 @@ Search.getLayout = getLayout;
export const getStaticProps: GetStaticProps = async (
context: GetStaticPropsContext
) => {
- const breadcrumbTitle = t`Search`;
+ const intl = await getIntlInstance();
+ const breadcrumbTitle = intl.formatMessage({
+ defaultMessage: 'Search',
+ description: 'SearchPage: breadcrumb item',
+ });
const { locale } = context;
const translation = await loadTranslation(locale);
diff --git a/src/pages/sujet/[slug].tsx b/src/pages/sujet/[slug].tsx
index 65ea2fd..87a86a2 100644
--- a/src/pages/sujet/[slug].tsx
+++ b/src/pages/sujet/[slug].tsx
@@ -4,7 +4,6 @@ import PostPreview from '@components/PostPreview/PostPreview';
import Sidebar from '@components/Sidebar/Sidebar';
import { RelatedThematics, ToC, TopicsList } from '@components/Widgets';
import { config } from '@config/website';
-import { t } from '@lingui/macro';
import { getAllTopicsSlug, getTopicBySlug } from '@services/graphql/queries';
import styles from '@styles/pages/Page.module.scss';
import { NextPageWithLayout } from '@ts/types/app';
@@ -16,9 +15,11 @@ import Head from 'next/head';
import { useRouter } from 'next/router';
import { ParsedUrlQuery } from 'querystring';
import { useRef } from 'react';
+import { useIntl } from 'react-intl';
import { Article as Article, Graph, WebPage } from 'schema-dts';
const Topic: NextPageWithLayout<TopicProps> = ({ topic }) => {
+ const intl = useIntl();
const relatedThematics = useRef<ThematicPreview[]>([]);
const router = useRouter();
@@ -128,14 +129,27 @@ const Topic: NextPageWithLayout<TopicProps> = ({ topic }) => {
<div dangerouslySetInnerHTML={{ __html: topic.content }}></div>
{topic.posts.length > 0 && (
<section className={styles.section}>
- <h2>{t`All posts in ${topic.title}`}</h2>
+ <h2>
+ {intl.formatMessage(
+ {
+ defaultMessage: 'All posts in {name}',
+ description: 'TopicPage: posts list title',
+ },
+ { name: topic.title }
+ )}
+ </h2>
<ol className={styles.list}>{getPostsList()}</ol>
</section>
)}
</div>
<Sidebar position="right">
<RelatedThematics thematics={relatedThematics.current} />
- <TopicsList title={t`Other topics`} />
+ <TopicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Others topics',
+ description: 'TopicPage: topics list widget title',
+ })}
+ />
</Sidebar>
</article>
</>
diff --git a/src/pages/thematique/[slug].tsx b/src/pages/thematique/[slug].tsx
index d263ee9..61019fd 100644
--- a/src/pages/thematique/[slug].tsx
+++ b/src/pages/thematique/[slug].tsx
@@ -4,7 +4,6 @@ import PostPreview from '@components/PostPreview/PostPreview';
import Sidebar from '@components/Sidebar/Sidebar';
import { RelatedTopics, ThematicsList, ToC } from '@components/Widgets';
import { config } from '@config/website';
-import { t } from '@lingui/macro';
import {
getAllThematicsSlug,
getThematicBySlug,
@@ -19,9 +18,11 @@ import Head from 'next/head';
import { useRouter } from 'next/router';
import { ParsedUrlQuery } from 'querystring';
import { useRef } from 'react';
+import { useIntl } from 'react-intl';
import { Article, Graph, WebPage } from 'schema-dts';
const Thematic: NextPageWithLayout<ThematicProps> = ({ thematic }) => {
+ const intl = useIntl();
const relatedTopics = useRef<TopicPreview[]>([]);
const router = useRouter();
@@ -118,14 +119,27 @@ const Thematic: NextPageWithLayout<ThematicProps> = ({ thematic }) => {
<div dangerouslySetInnerHTML={{ __html: thematic.content }}></div>
{thematic.posts.length > 0 && (
<section className={styles.section}>
- <h2>{t`All posts in ${thematic.title}`}</h2>
+ <h2>
+ {intl.formatMessage(
+ {
+ defaultMessage: 'All posts in {name}',
+ description: 'ThematicPage: posts list title',
+ },
+ { name: thematic.title }
+ )}
+ </h2>
<ol className={styles.list}>{getPostsList()}</ol>
</section>
)}
</div>
<Sidebar position="right">
<RelatedTopics topics={relatedTopics.current} />
- <ThematicsList title={t`Other thematics`} />
+ <ThematicsList
+ title={intl.formatMessage({
+ defaultMessage: 'Others thematics',
+ description: 'ThematicPage: thematics list widget title',
+ })}
+ />
</Sidebar>
</article>
</>