diff options
| author | Armand Philippot <git@armandphilippot.com> | 2021-12-13 12:35:10 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2021-12-13 12:35:10 +0100 |
| commit | 8c836de71b47744ec3e99cb8b3c853528fa66b52 (patch) | |
| tree | b4d1d0cf88b02457cfc4be7afd7586cc83b4ccfb | |
| parent | 4cae14b9f86609b8c1f74d97a033e7091af49cb4 (diff) | |
chore: load i18n translations using lingui provider
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | src/components/Branding/Branding.tsx | 9 | ||||
| -rw-r--r-- | src/i18n/fr/messages.po | 23 | ||||
| -rw-r--r-- | src/pages/_app.tsx | 30 | ||||
| -rw-r--r-- | src/pages/index.tsx | 15 | ||||
| -rw-r--r-- | src/utils/helpers/i18n.ts | 35 | ||||
| -rw-r--r-- | yarn.lock | 25 |
7 files changed, 136 insertions, 2 deletions
diff --git a/package.json b/package.json index 804b671..573521e 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@commitlint/cli": "^15.0.0", "@commitlint/config-conventional": "^15.0.0", "@lingui/cli": "^3.13.0", + "@lingui/loader": "^3.13.0", "@lingui/macro": "^3.13.0", "@svgr/webpack": "^6.1.2", "@testing-library/react": "^12.1.2", diff --git a/src/components/Branding/Branding.tsx b/src/components/Branding/Branding.tsx index e5565a4..a8adf9b 100644 --- a/src/components/Branding/Branding.tsx +++ b/src/components/Branding/Branding.tsx @@ -12,7 +12,14 @@ const Branding: BrandingReturn = ({ isHome = false }) => { return ( <div className={styles.wrapper}> <div className={styles.logo}> - <Image src={photo} alt={t`${config.name} picture`} layout="intrinsic" /> + <Image + src={photo} + alt={t({ + message: `${config.name} picture`, + comment: 'Branding logo.', + })} + layout="intrinsic" + /> </div> {isHome ? ( <h1 className={styles.name}> diff --git a/src/i18n/fr/messages.po b/src/i18n/fr/messages.po new file mode 100644 index 0000000..a05ea8e --- /dev/null +++ b/src/i18n/fr/messages.po @@ -0,0 +1,23 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2021-12-13 12:10+0100\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: fr\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#: src/config/website.ts:5 +msgid "Front-end developer" +msgstr "" + +#. Branding logo. +#: src/components/Branding/Branding.tsx:17 +msgid "{0} picture" +msgstr "" diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 8194b10..fde93eb 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,9 +1,37 @@ +import { useEffect, useRef } from 'react'; +import { useRouter } from 'next/router'; +import { i18n } from '@lingui/core'; +import { I18nProvider } from '@lingui/react'; import { AppPropsWithLayout } from '@ts/types/app'; +import { initTranslation } from '@utils/helpers/i18n'; import '../styles/globals.scss'; +initTranslation(i18n); + function MyApp({ Component, pageProps }: AppPropsWithLayout) { + const router = useRouter(); + const locale: string = router.locale || router.defaultLocale!; + const firstRender = useRef(true); + + if (pageProps.translation && firstRender.current) { + i18n.load(locale, pageProps.translation); + i18n.activate(locale); + firstRender.current = false; + } + + useEffect(() => { + if (pageProps.translation) { + i18n.load(locale, pageProps.translation); + i18n.activate(locale); + } + }, [locale, pageProps.translation]); + const getLayout = Component.getLayout ?? ((page) => page); - return getLayout(<Component {...pageProps} />); + return ( + <I18nProvider i18n={i18n}> + {getLayout(<Component {...pageProps} />)} + </I18nProvider> + ); } export default MyApp; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 6022497..615fe0a 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,5 +1,7 @@ import Layout from '@components/Layouts/Layout'; import { NextPageWithLayout } from '@ts/types/app'; +import { loadTranslation } from '@utils/helpers/i18n'; +import { GetStaticProps } from 'next'; import Head from 'next/head'; import Image from 'next/image'; import type { ReactElement } from 'react'; @@ -75,4 +77,17 @@ Home.getLayout = function getLayout(page: ReactElement) { return <Layout>{page}</Layout>; }; +export const getStaticProps: GetStaticProps = async (ctx) => { + const translation = await loadTranslation( + ctx.locale!, + process.env.NODE_ENV === 'production' + ); + + return { + props: { + translation, + }, + }; +}; + export default Home; diff --git a/src/utils/helpers/i18n.ts b/src/utils/helpers/i18n.ts new file mode 100644 index 0000000..38616a2 --- /dev/null +++ b/src/utils/helpers/i18n.ts @@ -0,0 +1,35 @@ +import type { I18n } from '@lingui/core'; +import { en, fr } from 'make-plural/plurals'; + +export interface LocaleData { + messages: object; + default: object; +} + +export const locales = { + en: 'English', + fr: 'Français', +}; + +export const defaultLocale = 'fr'; + +export function initTranslation(i18n: I18n): void { + i18n.loadLocaleData({ + en: { plurals: en }, + fr: { plurals: fr }, + }); +} + +export async function loadTranslation( + locale: string, + isProduction: boolean = true +) { + let data: LocaleData; + if (isProduction) { + data = await import(`src/i18n/${locale}/messages`); + } else { + data = await import(`@lingui/loader!src/i18n/${locale}/messages.po`); + } + + return data.messages; +} @@ -1484,6 +1484,17 @@ make-plural "^6.2.2" messageformat-parser "^4.1.3" +"@lingui/loader@^3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lingui/loader/-/loader-3.13.0.tgz#9d41cce476bbb782d0d4bde72c2133c28a47808b" + integrity sha512-MuLwM6vVMYH/ilCGunNGIPTvZU9gtjaohU54/bDCRbDJ5teN46UKqFTYqP6TwVWa+AF6hRMcgUprBcQJi7Iw8Q== + dependencies: + "@babel/runtime" "^7.11.2" + "@lingui/cli" "^3.13.0" + "@lingui/conf" "^3.13.0" + loader-utils "^2.0.0" + ramda "^0.27.1" + "@lingui/macro@^3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lingui/macro/-/macro-3.13.0.tgz#accb4a97ff7109d76647a1114f6527037cab5fef" @@ -3458,6 +3469,11 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + encoding@0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -5478,6 +5494,15 @@ loader-utils@1.2.3: emojis-list "^2.0.0" json5 "^1.0.1" +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" |
