diff --git a/.eslintrc.js b/.eslintrc.js index 5ee9a56f..8be37321 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,6 +21,7 @@ module.exports = { plugins: [ 'react', '@typescript-eslint', + 'i18next' ], rules: { 'react/react-in-jsx-scope': 'off', @@ -36,7 +37,8 @@ module.exports = { '@typescript-eslint/no-empty-function': 'off', 'no-empty-pattern': 'off', 'react/display-name': 'off', - 'react/no-find-dom-node': 'off' + 'react/no-find-dom-node': 'off', + 'i18next/no-literal-string': 'off' }, globals: { React: 'writable', diff --git a/package-lock.json b/package-lock.json index 3e509f44..2bb47398 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2539,6 +2539,15 @@ } } }, + "eslint-plugin-i18next": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-i18next/-/eslint-plugin-i18next-5.1.1.tgz", + "integrity": "sha512-qhJoeuOrRMVve5SA2/mVbYLL2nJJ4MTi8Y6nefRcOimrs86P/GZr1XXjKHSCEwcV5JL905//H6EO1AXTyUzzrg==", + "dev": true, + "requires": { + "requireindex": "~1.1.0" + } + }, "eslint-plugin-import": { "version": "2.22.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", @@ -5809,6 +5818,12 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=", + "dev": true + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", diff --git a/package.json b/package.json index f24be614..f6f66f49 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "eslint": "^7.23.0", "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^8.1.0", + "eslint-plugin-i18next": "^5.1.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-prettier": "^3.3.1", diff --git a/public/assets/icons/donation/CreditCard.tsx b/public/assets/icons/donation/CreditCard.tsx index a13d3448..3dab2722 100644 --- a/public/assets/icons/donation/CreditCard.tsx +++ b/public/assets/icons/donation/CreditCard.tsx @@ -4,40 +4,16 @@ function CreditCard() { return ( - - - - - + ); } diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 9509449f..d25d2ef1 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -70,5 +70,23 @@ "verifyEmailHeader": "Please confirm your email", "verifyEmailText": "To secure your account, we need to verify your email. Please check your inbox or spam/junk folder for a confirmation email and then continue to login.", "verifyEmailInfo": "If you didn’t receive an email please try logging in again and we’ll send you another email.", - "skipLogout":"Continue as guest" + "skipLogout":"Continue as guest", + "donationProcessedBy":"This donation is processed by Plant-for-the-Planet", + "cancelReturn":"Cancel and return to the organisation", + "aboutUs":"About Us", + "imprint":"Imprint", + "privacyTerms":"Privacy & Terms", + "contact":"Contact", + "faqs":"FAQS", + "selectLanguage":"Select Language", + "trees":"trees", + "logout":"Logout", + "directGiftRecipient": "This donation supports {{name}}", + "saveGiftDetails": "Save Gift Details", + "giftSomeone":"My donation is a gift to someone", + "payPalCard":"Use PayPal or Card", + "donateNow":"Donate Now", + "or":"OR", + "donateWith":"Donate with", + "donating":"Donating" } diff --git a/src/Donations/Components/DonationsForm.tsx b/src/Donations/Components/DonationsForm.tsx index 3f912007..066cc163 100644 --- a/src/Donations/Components/DonationsForm.tsx +++ b/src/Donations/Components/DonationsForm.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement } from "react"; +import React from "react"; import CustomIcon from "../../../public/assets/icons/CustomIcon"; import { QueryParamContext } from "../../Layout/QueryParamContext"; import GiftForm from "../Micros/GiftForm"; @@ -22,8 +22,6 @@ import TreeCostLoader from "../../Common/ContentLoaders/TreeCostLoader"; import Authentication from "./../Micros/Authentication"; import { useAuth0 } from "@auth0/auth0-react"; -interface Props {} - function DonationsForm() { const { isGift, @@ -176,7 +174,9 @@ function DonationsForm() { {option.iconFile}

{option.treeCount}

- trees + + {t('trees')} +
); @@ -213,7 +213,7 @@ function DonationsForm() { }} ref={customInputRef} /> - trees + {t('trees')} diff --git a/src/Donations/Components/ThankYouComponent.tsx b/src/Donations/Components/ThankYouComponent.tsx index dcf4869e..133f108f 100644 --- a/src/Donations/Components/ThankYouComponent.tsx +++ b/src/Donations/Components/ThankYouComponent.tsx @@ -1,7 +1,6 @@ import Snackbar from "@material-ui/core/Snackbar"; import MuiAlert, { AlertProps } from "@material-ui/lab/Alert"; import React from "react"; -// import tenantConfig from '../../../../tenant.config'; import { useTranslation } from "react-i18next"; import { getPaymentType } from "../PaymentMethods/PaymentFunctions"; import PaymentFailedIllustration from "../../../public/assets/icons/donation/PaymentFailed"; diff --git a/src/Donations/Micros/Authentication.tsx b/src/Donations/Micros/Authentication.tsx index 6b4c4410..52d39923 100644 --- a/src/Donations/Micros/Authentication.tsx +++ b/src/Donations/Micros/Authentication.tsx @@ -72,6 +72,7 @@ function Authentication({}: Props): ReactElement { } }, [isAuthenticated, isLoading]); + const { t, ready } = useTranslation("common"); return (
{!isLoading && !isAuthenticated && ( @@ -84,7 +85,7 @@ function Authentication({}: Props): ReactElement { }) } > - Login & Continue + {t('loginContinue')} )} @@ -93,7 +94,7 @@ function Authentication({}: Props): ReactElement { className="login-continue" onClick={() => logout({ returnTo: `${process.env.NEXTAUTH_URL}/` })} > - Logout + {t('logout')} )} {t("verifyEmailText")}

{t("verifyEmailInfo")}

-
- +
+ - + - +
diff --git a/src/Donations/Micros/GiftForm.tsx b/src/Donations/Micros/GiftForm.tsx index 93a16ffc..4e3a1173 100644 --- a/src/Donations/Micros/GiftForm.tsx +++ b/src/Donations/Micros/GiftForm.tsx @@ -5,9 +5,7 @@ import { useTranslation } from "next-i18next"; import { QueryParamContext } from "../../Layout/QueryParamContext"; import ToggleSwitch from "../../Common/InputTypes/ToggleSwitch"; import CloseIcon from "../../../public/assets/icons/CloseIcon"; -interface Props { - -} +interface Props {} export default function GiftForm({}: Props): ReactElement { const { t } = useTranslation("common"); @@ -22,7 +20,7 @@ export default function GiftForm({}: Props): ReactElement { giftMessage: giftDetails.giftMessage, }; - const { register, errors, handleSubmit,reset } = useForm({ + const { register, errors, handleSubmit, reset } = useForm({ mode: "all", defaultValues: defaultDeails, }); @@ -39,15 +37,15 @@ export default function GiftForm({}: Props): ReactElement { setgiftDetails({ ...giftDetails, ...data }); }; - const resetGiftForm = () =>{ + const resetGiftForm = () => { const defaultDeails = { - recipientName: '', - email: '', - giftMessage: '', + recipientName: "", + email: "", + giftMessage: "", }; - setgiftDetails(defaultDeails) + setgiftDetails(defaultDeails); reset(defaultDeails); - } + }; return (
@@ -55,7 +53,7 @@ export default function GiftForm({}: Props): ReactElement {
- Save Gift Details + {t('saveGiftDetails')}
) : (
-

This donation supports {giftDetails.recipientName}

-
diff --git a/src/Donations/Micros/SelectCurrencyModal.tsx b/src/Donations/Micros/SelectCurrencyModal.tsx index aba290ed..2f5b573c 100644 --- a/src/Donations/Micros/SelectCurrencyModal.tsx +++ b/src/Donations/Micros/SelectCurrencyModal.tsx @@ -1,12 +1,10 @@ import Backdrop from "@material-ui/core/Backdrop"; import Fade from "@material-ui/core/Fade"; import FormControl from "@material-ui/core/FormControl"; -import FormControlLabel from "@material-ui/core/FormControlLabel"; import Modal from "@material-ui/core/Modal"; -import RadioGroup from "@material-ui/core/RadioGroup"; import { withStyles } from "@material-ui/core/styles"; import Autocomplete from "@material-ui/lab/Autocomplete"; -import React, { useEffect, useState } from "react"; +import React from "react"; import { useTranslation } from "react-i18next"; import { ThemeContext } from "../../../styles/themeContext"; import MaterialTextField from "../../Common/InputTypes/MaterialTextField"; @@ -19,7 +17,7 @@ import { useStylesAutoComplete } from "./../../Common/InputTypes/AutoCompleteCou export default function TransitionsModal(props: any) { const { openModal, handleModalClose } = props; - const { setcountry, country, setcurrency, currency } = React.useContext( + const { setcountry, country, currency } = React.useContext( QueryParamContext ); @@ -40,7 +38,6 @@ export default function TransitionsModal(props: any) { setImportantList(impCountryList); }, [currency]); - return ready ? (
{ setcountry(value.countryCode); - handleModalClose(); + handleModalClose(); }} />
- -
diff --git a/src/Donations/Micros/ShareOptions.tsx b/src/Donations/Micros/ShareOptions.tsx index 9a36f5b9..c07dba3f 100644 --- a/src/Donations/Micros/ShareOptions.tsx +++ b/src/Donations/Micros/ShareOptions.tsx @@ -1,4 +1,4 @@ -import React, { useRef } from 'react'; +import React from 'react'; import EmailIcon from '../../../public/assets/icons/share/Email'; import EmailSolid from '../../../public/assets/icons/share/EmailSolid'; import FacebookIcon from '../../../public/assets/icons/share/Facebook'; diff --git a/src/Donations/PaymentMethods/GiroPayPayments.tsx b/src/Donations/PaymentMethods/GiroPayPayments.tsx index cda2fc63..1c19f157 100644 --- a/src/Donations/PaymentMethods/GiroPayPayments.tsx +++ b/src/Donations/PaymentMethods/GiroPayPayments.tsx @@ -6,7 +6,7 @@ interface Props { } function GiroPayPayments({ onSubmitPayment }: Props): ReactElement { - const { t, i18n, ready } = useTranslation("common"); + const { t } = useTranslation("common"); return (
OR
@@ -193,7 +192,7 @@ export const PaymentRequestCustomButton = ({ onClick={() => paymentRequest.show()} className="primary-button dark-pay w-100 mb-10" > - Donate with + {t('donateWith')}
OR
@@ -203,15 +202,18 @@ export const PaymentRequestCustomButton = ({ onClick={() => paymentRequest.show()} className="primary-button donate-now w-100 mb-10" > - Donate Now + + {t('donateNow')} -
OR
+
+ {t('or')} +
) ) : null}
diff --git a/src/Donations/index.tsx b/src/Donations/index.tsx index f1699b4e..71af8d80 100644 --- a/src/Donations/index.tsx +++ b/src/Donations/index.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, useState } from "react"; +import React, { ReactElement } from "react"; import ContactsForm from "./Components/ContactsForm"; import { QueryParamContext } from "../Layout/QueryParamContext"; @@ -51,7 +51,7 @@ function DonationInfo() { } = React.useContext(QueryParamContext); const [showContactDetails, setshowContactDetails] = React.useState(false); - + return projectDetails && paymentSetup ? (
{/*
*/}
- {projectDetails.name} -
+ + {projectDetails.name} + +
{projectDetails.tpo && ( - + {t("byOrganization", { organizationName: projectDetails.tpo.name, })} @@ -76,7 +88,7 @@ function DonationInfo() { {(donationStep === 2 || donationStep === 3) && (
- Donating {" "} + {t('donating')} {getFormatedCurrency( i18n.language, @@ -94,7 +106,11 @@ function DonationInfo() {
{giftDetails && isGift && giftDetails.recipientName && (
-

This donation supports {giftDetails.recipientName}

+

+ {t("directGiftRecipient", { + name: giftDetails.recipientName, + })} +

)}
diff --git a/src/Layout/Footer.tsx b/src/Layout/Footer.tsx index 39fb4b39..b64dab2c 100644 --- a/src/Layout/Footer.tsx +++ b/src/Layout/Footer.tsx @@ -27,40 +27,55 @@ function Footer({}: Props): ReactElement { return (
-

- This donation is processed by Plant-for-the-Planet -

+

{t("donationProcessedBy")}

- {returnTo ? ( - Cancel and return to the organisation - ) : ( -

- )} + {returnTo ? {t("cancelReturn")} :

} - ): <>; + ) : ( + <> + ); } interface ModalProps { @@ -132,6 +150,7 @@ function LanguageModal({ const { theme } = React.useContext(ThemeContext); const { language, setlanguage } = React.useContext(QueryParamContext); + const { t, ready } = useTranslation(["common"]); return (
-

Select Language

+

+ {t('selectLanguage')} +

{ // stores the session id present in AsyncStorage - let sessionId = await getsessionId(); + const sessionId = await getsessionId(); // if there's session id then adds the same into the header if (sessionId) { @@ -50,10 +50,10 @@ axiosInstance.interceptors.response.use( }, ); -const request = async (url:string, method:string = 'GET', token:any = false, data:any = undefined) => { +const request = async (url:string, method = 'GET', token:any = false, data:any = undefined) => { try { // sets the options which is passed to axios to make the request - let options = { + const options = { method, url, };