From 02a6cc14d2a2303e76fb502c28b978c0d2ea6582 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Fri, 31 Mar 2023 14:35:30 +0200 Subject: [PATCH 01/25] Re-do commit 583ef70 on current master --- README.md | 8 ++ packages/react-app/package.json | 1 + packages/react-app/src/components/Account.jsx | 4 +- packages/react-app/src/components/Header.jsx | 1 - packages/react-app/src/index.jsx | 22 +++- packages/react-app/src/lang/en.json | 4 + packages/react-app/src/lang/es.json | 4 + packages/react-app/src/lang/format.js | 7 + packages/react-app/src/views/HomeView.jsx | 9 +- yarn.lock | 120 +++++++++++++++++- 10 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 packages/react-app/src/lang/en.json create mode 100644 packages/react-app/src/lang/es.json create mode 100644 packages/react-app/src/lang/format.js diff --git a/README.md b/README.md index a1ee0a38..2f95ca6e 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,11 @@ Then re-run: ```bash yarn backend ``` + +## Translations + +Extract (run in react-app folder): + +``` +yarn translations-extract 'src/**/*.js*' --ignore='**/*.json' --format='src/lang/format.js' --out-file src/lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' +``` diff --git a/packages/react-app/package.json b/packages/react-app/package.json index 0b41ba39..b0bb5806 100644 --- a/packages/react-app/package.json +++ b/packages/react-app/package.json @@ -53,6 +53,7 @@ "react": "^16.14.0", "react-blockies": "^1.4.1", "react-dom": "^16.14.0", + "react-intl": "^6.3.2", "react-markdown": "^7.1.0", "react-qr-reader": "^2.2.1", "react-router-dom": "^5.2.0", diff --git a/packages/react-app/src/components/Account.jsx b/packages/react-app/src/components/Account.jsx index 3fa96300..2d83fd80 100644 --- a/packages/react-app/src/components/Account.jsx +++ b/packages/react-app/src/components/Account.jsx @@ -19,6 +19,7 @@ import { LinkBox, LinkOverlay, } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import QRPunkBlockie from "./QrPunkBlockie"; import useDisplayAddress from "../hooks/useDisplayAddress"; import useCustomColorModes from "../hooks/useCustomColorModes"; @@ -63,7 +64,6 @@ import SignatureSignUp from "./SignatureSignUp"; export default function Account({ address, - connectText, ensProvider, isWalletConnected, loadWeb3Modal, @@ -92,7 +92,7 @@ export default function Account({ const connectWallet = ( ); diff --git a/packages/react-app/src/components/Header.jsx b/packages/react-app/src/components/Header.jsx index 4006d630..98db63fd 100644 --- a/packages/react-app/src/components/Header.jsx +++ b/packages/react-app/src/components/Header.jsx @@ -134,7 +134,6 @@ export default function Header({ - - - - + + + + + + , document.getElementById("root"), ); diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json new file mode 100644 index 00000000..f14c354e --- /dev/null +++ b/packages/react-app/src/lang/en.json @@ -0,0 +1,4 @@ +{ + "account.connect-wallet": "Connect Wallet", + "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas." +} diff --git a/packages/react-app/src/lang/es.json b/packages/react-app/src/lang/es.json new file mode 100644 index 00000000..a753fd93 --- /dev/null +++ b/packages/react-app/src/lang/es.json @@ -0,0 +1,4 @@ +{ + "account.connect-wallet": "Conectar Wallet", + "index.learn-ethereum": "Aprender a desarrollar en Ethereum; los super poderes y los trucos." +} diff --git a/packages/react-app/src/lang/format.js b/packages/react-app/src/lang/format.js new file mode 100644 index 00000000..5a047985 --- /dev/null +++ b/packages/react-app/src/lang/format.js @@ -0,0 +1,7 @@ +exports.format = function format(msgs) { + const results = {}; + Object.entries(msgs).forEach(([id, msg]) => { + results[id] = msg.defaultMessage; + }); + return results; +}; diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index ca151b10..ebffaf20 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -1,5 +1,6 @@ import React, { useMemo } from "react"; import { Container, Box, Text, Center, useColorModeValue } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import ChallengeExpandedCard from "../components/ChallengeExpandedCard"; import { challengeInfo } from "../data/challenges"; import useCustomColorModes from "../hooks/useCustomColorModes"; @@ -60,7 +61,13 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > - Learn how to build on Ethereum; the superpowers and the gotchas. + {chunks}, + }} + />
Date: Fri, 31 Mar 2023 14:43:41 +0200 Subject: [PATCH 02/25] Add missing script --- packages/react-app/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-app/package.json b/packages/react-app/package.json index b0bb5806..ac565cf8 100644 --- a/packages/react-app/package.json +++ b/packages/react-app/package.json @@ -102,6 +102,7 @@ "s3": "node ./scripts/s3.js", "ship": "yarn surge", "theme": "npx gulp less", - "watch": "node ./scripts/watch.js" + "watch": "node ./scripts/watch.js", + "translations-extract": "formatjs extract" } } From e1dde3616b359152712007f13051d79725ccf5f3 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 3 Apr 2023 12:10:15 +0200 Subject: [PATCH 03/25] Add extracting and compiling scripts --- README.md | 4 ++-- packages/react-app/package.json | 3 ++- packages/react-app/src/lang/en.json | 2 +- packages/react-app/src/lang/format.js | 7 ------- packages/react-app/src/views/HomeView.jsx | 2 +- yarn.lock | 5 +++++ 6 files changed, 11 insertions(+), 12 deletions(-) delete mode 100644 packages/react-app/src/lang/format.js diff --git a/README.md b/README.md index 2f95ca6e..92fb5351 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ yarn backend ## Translations -Extract (run in react-app folder): +Extract and compile strings ([docs](https://formatjs.io/docs/tooling/cli/#extraction-and-compilation-with-a-single-script)) (run in react-app folder): ``` -yarn translations-extract 'src/**/*.js*' --ignore='**/*.json' --format='src/lang/format.js' --out-file src/lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' +yarn translations-extract ``` diff --git a/packages/react-app/package.json b/packages/react-app/package.json index ac565cf8..d7072609 100644 --- a/packages/react-app/package.json +++ b/packages/react-app/package.json @@ -64,6 +64,7 @@ "web3modal": "^1.9.1" }, "devDependencies": { + "@formatjs/cli": "^6.0.4", "@testing-library/dom": "^6.12.2", "@types/react": "^16.9.19", "autoprefixer": "^10.2.4", @@ -103,6 +104,6 @@ "ship": "yarn surge", "theme": "npx gulp less", "watch": "node ./scripts/watch.js", - "translations-extract": "formatjs extract" + "translations-extract": "formatjs extract 'src/**/*.js*' --ignore='**/*.json' --out-file src/lang/extractions.json --flatten --id-interpolation-pattern '[sha512:contenthash:base64:6]' && formatjs compile 'src/lang/extractions.json' --out-file src/lang/en.json && rm src/lang/extractions.json" } } diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index f14c354e..16718101 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,4 +1,4 @@ { "account.connect-wallet": "Connect Wallet", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas." -} +} \ No newline at end of file diff --git a/packages/react-app/src/lang/format.js b/packages/react-app/src/lang/format.js deleted file mode 100644 index 5a047985..00000000 --- a/packages/react-app/src/lang/format.js +++ /dev/null @@ -1,7 +0,0 @@ -exports.format = function format(msgs) { - const results = {}; - Object.entries(msgs).forEach(([id, msg]) => { - results[id] = msg.defaultMessage; - }); - return results; -}; diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index ebffaf20..3bf99412 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -63,7 +63,7 @@ export default function HomeView({ connectedBuilder, userProvider }) { > {chunks}, }} diff --git a/yarn.lock b/yarn.lock index 80098724..5143e64d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2496,6 +2496,11 @@ resolved "https://registry.yarnpkg.com/@fontsource/space-grotesk/-/space-grotesk-4.5.10.tgz#49c62a52e08c7c713ccf25ff58d9061d31048191" integrity sha512-Ua+3NeVpUbVrF4F0I5posgZ0/SvpX0ijmwU4MI43cormzOP6r6Z09+BWwhS85+wMJsM+ravc+65fa/rqAZQ3wg== +"@formatjs/cli@^6.0.4": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-6.0.4.tgz#f772639748ecb2173df0b028bf084df25e91d3f1" + integrity sha512-ivb+uUcYmHnffBkXM7OM4NDofxyfnVvW5G52p+M9Cg3DGMz3wVBm3TwW3SXgGGTft7CMWHeGQGXjxTOwBYKeEA== + "@formatjs/ecma402-abstract@1.14.3": version "1.14.3" resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.14.3.tgz#6428f243538a11126180d121ce8d4b2f17465738" From 5e6f1fa15e64ec56c44cd313a1b7926545031b6a Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 3 Apr 2023 22:19:17 +0200 Subject: [PATCH 04/25] Add a couple of examples and extract them --- .../src/components/AnnouncementBanner.jsx | 23 ++++++++++++++----- .../src/components/SignatureSignUp.jsx | 10 +++++++- packages/react-app/src/index.jsx | 2 +- packages/react-app/src/lang/en.json | 4 +++- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/react-app/src/components/AnnouncementBanner.jsx b/packages/react-app/src/components/AnnouncementBanner.jsx index bbd47926..1eaf116a 100644 --- a/packages/react-app/src/components/AnnouncementBanner.jsx +++ b/packages/react-app/src/components/AnnouncementBanner.jsx @@ -1,17 +1,28 @@ import React from "react"; import { chakra, useColorModeValue, Link } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; export default function AnnouncementBanner() { const bannerBg = useColorModeValue("#fbf7f6", "whiteAlpha.300"); return ( - Hey builder!! The BuidlGuidl is hosting a{" "} - - πŸ— Scaffold-Eth 2 hackathon - - . We are giving 10 ETH away to the best projects. -
Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps! + πŸ— Scaffold-Eth 2 hackathon. + We are giving 10 ETH away to the best projects. + {br}Come join the fun and learn the latest scaffold-eth techniques! + Let's build a bunch of apps!`} + values={{ + Link: chunks => ( + + {chunks} + + ), + br:
, + }} + />
); } diff --git a/packages/react-app/src/components/SignatureSignUp.jsx b/packages/react-app/src/components/SignatureSignUp.jsx index 8ac486a9..75d3a228 100644 --- a/packages/react-app/src/components/SignatureSignUp.jsx +++ b/packages/react-app/src/components/SignatureSignUp.jsx @@ -1,11 +1,13 @@ import React, { useState } from "react"; import axios from "axios"; import { forwardRef, chakra, Button, useToast } from "@chakra-ui/react"; +import { useIntl } from "react-intl"; import { SERVER_URL as serverUrl } from "../constants"; import { USER_ROLES } from "../helpers/constants"; const SignatureSignUp = forwardRef(({ address, userProvider, onSuccess, setUserRole }, ref) => { const [loading, setLoading] = useState(false); + const intl = useIntl(); const toast = useToast({ position: "top", isClosable: true }); const handleLoginSigning = async () => { @@ -68,7 +70,13 @@ const SignatureSignUp = forwardRef(({ address, userProvider, onSuccess, setUserR return ( ); }); diff --git a/packages/react-app/src/index.jsx b/packages/react-app/src/index.jsx index 34b00451..084c6195 100644 --- a/packages/react-app/src/index.jsx +++ b/packages/react-app/src/index.jsx @@ -18,7 +18,7 @@ const translations = { }; // TODO: change from ui -const userLocale = "es"; +const userLocale = "en"; ReactDOM.render( diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 16718101..171a127b 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,4 +1,6 @@ { "account.connect-wallet": "Connect Wallet", - "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas." + "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", + "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", + "signatureSingUp.write-icon": "write icon" } \ No newline at end of file From a2e1b057229b0030a3028b3e95078b87d633d9d8 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Sun, 16 Apr 2023 13:56:08 +0200 Subject: [PATCH 05/25] Add i18n to HomeView --- packages/react-app/src/lang/en.json | 6 + packages/react-app/src/views/HomeView.jsx | 212 ++++++++++++++-------- 2 files changed, 140 insertions(+), 78 deletions(-) diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 171a127b..b06d65bf 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -2,5 +2,11 @@ "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", + "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", + "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:", + "index.step-2.2": "global units, primitives, mappings, structs, modifiers, events,", + "index.step-2.3": "inheritance, sending eth, and payable/fallback functions.", + "index.step-3": "Watch this getting started playlist to become a power user and eth scripter.", + "index.step-4": "When you are ready to test your knowledge, Speed Run Ethereum:", "signatureSingUp.write-icon": "write icon" } \ No newline at end of file diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index 3bf99412..16eee1f3 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -93,16 +93,22 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > - Watch this{" "} - - quick video - {" "} - as an Intro to Ethereum Development. + ( + + {chunks} + + ), + }} + /> @@ -117,19 +123,27 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > - Then use{" "} - - - πŸ— - {" "} - Scaffold-ETH - {" "} - to copy/paste each Solidity concept and tinker: + ( + + {chunks} + + ), + span: chunks => ( + + {chunks} + + ), + }} + />
- - global units - - ,{" "} - - primitives - - ,{" "} - - mappings - - ,{" "} - - structs - - ,{" "} - - modifiers - - ,{" "} - - events - - , + global units, primitives, mappings, structs, modifiers, events, + `} + values={{ + a_globalUnits: chunks => ( + + {chunks} + + ), + a_primitives: chunks => ( + + {chunks} + + ), + a_mappings: chunks => ( + + {chunks} + + ), + a_structs: chunks => ( + + {chunks} + + ), + a_modifiers: chunks => ( + + {chunks} + + ), + a_events: chunks => ( + + {chunks} + + ), + }} + />
{" "} - - inheritance - - ,{" "} - - sending eth - - , and{" "} - - payable - - / - - fallback - {" "} - functions. + inheritance, sending eth, and payable/fallback functions. + `} + values={{ + a_inheritance: chunks => ( + + {chunks} + + ), + a_sendingEth: chunks => ( + + {chunks} + + ), + a_payable: chunks => ( + + {chunks} + + ), + a_fallback: chunks => ( + + {chunks} + + ), + }} + />
@@ -201,16 +248,22 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > - Watch this{" "} - - getting started playlist - {" "} - to become a power user and eth scripter. + ( + + {chunks} + + ), + }} + /> @@ -225,7 +278,10 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > - When you are ready to test your knowledge, Speed Run Ethereum: + Date: Sun, 16 Apr 2023 14:15:37 +0200 Subject: [PATCH 06/25] Add i18n to ChallengeExpandedCard --- .../src/components/ChallengeExpandedCard.jsx | 11 ++++++----- packages/react-app/src/lang/en.json | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/react-app/src/components/ChallengeExpandedCard.jsx b/packages/react-app/src/components/ChallengeExpandedCard.jsx index 216d044b..b48fef62 100644 --- a/packages/react-app/src/components/ChallengeExpandedCard.jsx +++ b/packages/react-app/src/components/ChallengeExpandedCard.jsx @@ -15,6 +15,7 @@ import { useColorModeValue, VStack, } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import useCustomColorModes from "../hooks/useCustomColorModes"; import { CHALLENGE_SUBMISSION_STATUS } from "../helpers/constants"; @@ -137,7 +138,7 @@ const ChallengeExpandedCard = ({ fontSize={{ base: "xl", lg: "lg" }} border="2px" backgroundColor="sreDark.default" - disabled={true} + disabled borderColor="sre.default" py="1rem" px={4} @@ -145,7 +146,7 @@ const ChallengeExpandedCard = ({ - Locked + @@ -285,7 +286,7 @@ const ChallengeExpandedCard = ({ - Locked + )} @@ -316,14 +317,14 @@ const ChallengeExpandedCard = ({ - Quest + ) : ( - Locked + )} diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index b06d65bf..bb47f1c9 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -8,5 +8,7 @@ "index.step-2.3": "inheritance, sending eth, and payable/fallback functions.", "index.step-3": "Watch this getting started playlist to become a power user and eth scripter.", "index.step-4": "When you are ready to test your knowledge, Speed Run Ethereum:", + "locked": "Locked", + "quest": "Quest", "signatureSingUp.write-icon": "write icon" } \ No newline at end of file From 3f3abca6a556cf7df0d519ede56b5e033720e7c0 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 17 Apr 2023 11:40:44 +0200 Subject: [PATCH 07/25] Add key to remove warning --- packages/react-app/src/views/HomeView.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index 16eee1f3..e544ddea 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -296,6 +296,7 @@ export default function HomeView({ connectedBuilder, userProvider }) { {Object.entries(challengeInfo).map(([challengeId, challenge], index, { length }) => ( Date: Mon, 17 Apr 2023 11:41:49 +0200 Subject: [PATCH 08/25] Add i18n to JoinBG --- packages/react-app/src/components/JoinBG.jsx | 78 ++++++++++++++------ packages/react-app/src/index.jsx | 8 +- packages/react-app/src/lang/en.json | 8 ++ 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/packages/react-app/src/components/JoinBG.jsx b/packages/react-app/src/components/JoinBG.jsx index c9944f4e..c1f2594a 100644 --- a/packages/react-app/src/components/JoinBG.jsx +++ b/packages/react-app/src/components/JoinBG.jsx @@ -1,11 +1,13 @@ import React, { useState } from "react"; import axios from "axios"; import { chakra, useToast, Button, Link } from "@chakra-ui/react"; +import { FormattedMessage, useIntl } from "react-intl"; import { SERVER_URL as serverUrl } from "../constants"; const serverPath = "/bg/join"; export default function JoinBG({ text, connectedBuilder, isChallengeLocked, userProvider, onJoinCallback }) { + const intl = useIntl(); const [isJoining, setIsJoining] = useState(false); // Optimistic update. const [joined, setJoined] = useState(false); @@ -18,16 +20,25 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user if (!connectedBuilder.socialLinks || Object.keys(connectedBuilder?.socialLinks ?? {}).length === 0) { toast({ - title: "Can't join the BuidlGuidl", + title: intl.formatMessage({ + id: "joinBg.missing-socials.title", + defaultMessage: "Can't join the BuidlGuidl", + }), duration: 10000, - description: ( - <> - In order to join the BuildGuidl you need to set your socials in{" "} - - your portfolio - - . It's our way to contact you. - + description: intl.formatMessage( + { + id: "joinBg.missing-socials.description", + defaultMessage: `In order to join the BuildGuidl you need to set + your socials in your portfolio. It's our way to + contact you.`, + }, + { + Link: chunks => ( + + {chunks} + + ), + }, ), status: "error", @@ -48,7 +59,10 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user signMessage = signMessageResponse.data; } catch (error) { toast({ - description: "Can't get the message to sign. Please try again", + description: intl.formatMessage({ + id: `joinBg.get-message-failed`, + defaultMessage: "Can't get the message to sign. Please try again", + }), status: "error", }); setIsJoining(false); @@ -61,7 +75,10 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user } catch (error) { toast({ status: "error", - description: "The signature was cancelled", + description: intl.formatMessage({ + id: "joinBg.signature-cancelled", + defaultMessage: "The signature was cancelled", + }), }); console.error(error); setIsJoining(false); @@ -83,7 +100,12 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user } catch (error) { toast({ status: "error", - description: error?.response?.data ?? "Submission Error. Please try again.", + description: + error?.response?.data ?? + intl.formatMessage({ + id: "joinBg.signature-submission-error", + defaultMessage: "Submission Error. Please try again.", + }), }); console.error(error); setIsJoining(false); @@ -94,15 +116,21 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user toast({ status: "success", duration: 10000, - title: "Welcome to the BuildGuidl :)", - description: ( - <> - Visit{" "} - - BuidlGuidl - {" "} - and start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build. - + title: intl.formatMessage({ id: "joinBg.success.title", defaultMessage: "Welcome to the BuildGuidl :)" }), + description: intl.formatMessage( + { + id: "joinBg.success.description", + defaultMessage: `Visit BuidlGuidl and start crafting + your Web3 portfolio by submitting your DEX, Multisig or SVG NFT + build.`, + }, + { + Link: chunks => ( + + {chunks} + + ), + }, ), }); setIsJoining(false); @@ -125,7 +153,13 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user isFullWidth isExternal > - {builderAlreadyJoined || joined ? "Already joined" : text} + + {builderAlreadyJoined || joined ? ( + + ) : ( + text + )} + ); } diff --git a/packages/react-app/src/index.jsx b/packages/react-app/src/index.jsx index 084c6195..67ad25ce 100644 --- a/packages/react-app/src/index.jsx +++ b/packages/react-app/src/index.jsx @@ -21,13 +21,13 @@ const translations = { const userLocale = "en"; ReactDOM.render( - - + + - - , +
+ , document.getElementById("root"), ); diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index bb47f1c9..79e6fa52 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -8,6 +8,14 @@ "index.step-2.3": "inheritance, sending eth, and payable/fallback functions.", "index.step-3": "Watch this getting started playlist to become a power user and eth scripter.", "index.step-4": "When you are ready to test your knowledge, Speed Run Ethereum:", + "joinBg.button.already-joined": "Already joined", + "joinBg.get-message-failed": "Can't get the message to sign. Please try again", + "joinBg.missing-socials.description": "In order to join the BuildGuidl you need to set your socials in your portfolio. It's our way to contact you.", + "joinBg.missing-socials.title": "Can't join the BuidlGuidl", + "joinBg.signature-cancelled": "The signature was cancelled", + "joinBg.signature-submission-error": "Submission Error. Please try again.", + "joinBg.success.description": "Visit BuidlGuidl and start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", + "joinBg.success.title": "Welcome to the BuildGuidl :)", "locked": "Locked", "quest": "Quest", "signatureSingUp.write-icon": "write icon" From 351aed5aae09039a6d9f21e4a03964c5f23c3de1 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 17 Apr 2023 12:43:25 +0200 Subject: [PATCH 09/25] Add i18n to BuilderChallenges --- packages/react-app/src/lang/en.json | 1 + packages/react-app/src/views/BuilderProfileView.jsx | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 79e6fa52..074b1c02 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,6 +1,7 @@ { "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", + "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:", diff --git a/packages/react-app/src/views/BuilderProfileView.jsx b/packages/react-app/src/views/BuilderProfileView.jsx index b21f322a..89ae6dfd 100644 --- a/packages/react-app/src/views/BuilderProfileView.jsx +++ b/packages/react-app/src/views/BuilderProfileView.jsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import axios from "axios"; import { useToast, useColorModeValue, Container, SimpleGrid, GridItem, Box } from "@chakra-ui/react"; +import { useIntl } from "react-intl"; import BuilderProfileCard from "../components/builder/BuilderProfileCard"; import { challengeInfo } from "../data/challenges"; import { BG_BACKEND_URL as bgBackendUrl } from "../constants"; @@ -26,6 +27,7 @@ export default function BuilderProfileView({ const [isLoadingBuilder, setIsLoadingBuilder] = useState(false); const [isBuilderOnBg, setIsBuilderOnBg] = useState(false); const [isLoadingTimestamps, setIsLoadingTimestamps] = useState(false); + const intl = useIntl(); const toast = useToast({ position: "top", isClosable: true }); const toastVariant = useColorModeValue("subtle", "solid"); const bgColor = useColorModeValue("sre.cardBackground", "sreDark.cardBackground"); @@ -75,7 +77,10 @@ export default function BuilderProfileView({ setIsLoadingTimestamps(false); } catch (error) { toast({ - description: "Can't get challenges metadata. Please try again", + description: intl.formatMessage({ + id: "builderProfileView.error-getting-challenges", + defaultMessage: "Can't get challenges metadata. Please try again", + }), status: "error", variant: toastVariant, }); From 6e8fe9ceeb5bd2b0bc44cec35d4eaaefab752fae Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 17 Apr 2023 13:19:43 +0200 Subject: [PATCH 10/25] Add i18n to BuilderProfileCard --- .../components/builder/BuilderProfileCard.jsx | 67 +++++++++++++++---- packages/react-app/src/lang/en.json | 14 +++- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/packages/react-app/src/components/builder/BuilderProfileCard.jsx b/packages/react-app/src/components/builder/BuilderProfileCard.jsx index 9537cc82..a50e67a2 100644 --- a/packages/react-app/src/components/builder/BuilderProfileCard.jsx +++ b/packages/react-app/src/components/builder/BuilderProfileCard.jsx @@ -28,6 +28,7 @@ import { useClipboard, } from "@chakra-ui/react"; import { CopyIcon, QuestionOutlineIcon } from "@chakra-ui/icons"; +import { FormattedMessage, useIntl } from "react-intl"; import QRPunkBlockie from "../QrPunkBlockie"; import SocialLink from "../SocialLink"; import useDisplayAddress from "../../hooks/useDisplayAddress"; @@ -56,6 +57,7 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide const { isOpen, onOpen, onClose } = useDisclosure(); const { hasCopied, onCopy } = useClipboard(builder?.id); const { borderColor, secondaryFontColor } = useCustomColorModes(); + const intl = useIntl(); const shortAddress = ellipsizedAddress(builder?.id); const hasEns = ens !== shortAddress; @@ -85,9 +87,15 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide const invalidSocials = validateSocials(socialLinkCleaned); if (invalidSocials.length !== 0) { toast({ - description: `The usernames for the following socials are not correct: ${invalidSocials - .map(([social]) => social) - .join(", ")}`, + description: intl.formatMessage( + { + id: "builderProfileCard.error.invalid-socials", + defaultMessage: "The usernames for the following socials are not correct: {invalidSocials}", + }, + { + invalidSocials: invalidSocials.map(([social]) => social).join(", "), + }, + ), status: "error", variant: toastVariant, }); @@ -100,7 +108,10 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide signMessage = await getUpdateSocialsSignMessage(address); } catch (error) { toast({ - description: " Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", + description: intl.formatMessage({ + id: "error.server-overloaded", + defaultMessage: "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", + }), status: "error", variant: toastVariant, }); @@ -113,7 +124,10 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide signature = await userProvider.send("personal_sign", [signMessage, address]); } catch (error) { toast({ - description: "Couldn't get a signature from the Wallet", + description: intl.formatMessage({ + id: "error.signature-from-wallet", + defaultMessage: "Couldn't get a signature from the Wallet", + }), status: "error", variant: toastVariant, }); @@ -127,7 +141,10 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide if (error.status === 401) { toast({ status: "error", - description: "Access error", + description: intl.formatMessage({ + id: "error.access-error", + defaultMessage: "Access error", + }), variant: toastVariant, }); setIsUpdatingSocials(false); @@ -135,7 +152,10 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide } toast({ status: "error", - description: "Can't update your socials. Please try again.", + description: intl.formatMessage({ + id: "builderProfileCard.error.updating-socials", + defaultMessage: "Can't update your socials. Please try again.", + }), variant: toastVariant, }); setIsUpdatingSocials(false); @@ -143,7 +163,10 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide } toast({ - description: "Your social links have been updated", + description: intl.formatMessage({ + id: "builderProfileCard.success.updating-socials", + defaultMessage: "Your social links have been updated", + }), status: "success", variant: toastVariant, }); @@ -289,8 +312,18 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide isMyProfile && ( - You haven't set your socials{" "} - + {" "} + + } + > @@ -299,11 +332,15 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide )} {isMyProfile && ( )} - Joined {joinedDateDisplay} + @@ -312,7 +349,9 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide - Update your socials + + + {Object.entries(socials).map(([socialId, socialData]) => ( @@ -336,7 +375,7 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide ))} diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 074b1c02..13952fa5 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,7 +1,18 @@ { "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", + "builderProfileCard.error.invalid-socials": "The usernames for the following socials are not correct: {invalidSocials}", + "builderProfileCard.error.updating-socials": "Can't update your socials. Please try again.", + "builderProfileCard.joined": "Joined {date}", + "builderProfileCard.modal-socials.header": "Update your socials", + "builderProfileCard.set-socials.tooltip": "It's our way of reaching out to you. We could sponsor you an ENS, offer to be part of a build or set up an ETH stream for you.", + "builderProfileCard.set-socials.warning": "You haven't set your socials", + "builderProfileCard.success.updating-socials": "Your social links have been updated", + "builderProfileCard.update-socials": "Update socials", "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", + "error.access-error": "Access error", + "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", + "error.signature-from-wallet": "Couldn't get a signature from the Wallet", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:", @@ -19,5 +30,6 @@ "joinBg.success.title": "Welcome to the BuildGuidl :)", "locked": "Locked", "quest": "Quest", - "signatureSingUp.write-icon": "write icon" + "signatureSingUp.write-icon": "write icon", + "update": "Update" } \ No newline at end of file From 884ffc540e06ecd6254c1c281b170a0eae64f3f8 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Wed, 19 Apr 2023 12:35:44 +0200 Subject: [PATCH 11/25] Add i18n to JoinedBuidlGuidlBanner --- .../src/components/builder/JoinedBuidlGuidlBanner.jsx | 8 ++++++-- packages/react-app/src/lang/en.json | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/react-app/src/components/builder/JoinedBuidlGuidlBanner.jsx b/packages/react-app/src/components/builder/JoinedBuidlGuidlBanner.jsx index 57079db2..c06d5334 100644 --- a/packages/react-app/src/components/builder/JoinedBuidlGuidlBanner.jsx +++ b/packages/react-app/src/components/builder/JoinedBuidlGuidlBanner.jsx @@ -1,5 +1,6 @@ import React from "react"; import { Button, Center, Flex, Image, Link, Text, VStack, chakra, useColorModeValue } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import CrossedSwordsIcon from "../icons/CrossedSwordsIcon"; const BG_FRONTEND_URL = "https://buidlguidl.com"; @@ -36,7 +37,10 @@ export const JoinedBuidlGuidlBanner = ({ builderAddress }) => { fontWeight="extrabold" px="20px" > - This builder has upgraded to BuidlGuidl +
diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 13952fa5..0e9f8a57 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -28,6 +28,8 @@ "joinBg.signature-submission-error": "Submission Error. Please try again.", "joinBg.success.description": "Visit BuidlGuidl and start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", "joinBg.success.title": "Welcome to the BuildGuidl :)", + "joinedBuidlGuidlBanner.button": "View their profile on Buidlguidl", + "joinedBuidlGuidlBanner.label": "This builder has upgraded to BuidlGuidl", "locked": "Locked", "quest": "Quest", "signatureSingUp.write-icon": "write icon", From f8196eabf7c7e8fdcc97aaf82fd730b7240fe1fc Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Wed, 19 Apr 2023 12:41:42 +0200 Subject: [PATCH 12/25] Add i18n to BuilderProfileHeader --- .../src/components/builder/BuilderProfileHeader.jsx | 5 +++-- packages/react-app/src/lang/en.json | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/react-app/src/components/builder/BuilderProfileHeader.jsx b/packages/react-app/src/components/builder/BuilderProfileHeader.jsx index 4f78cec7..fa67dc56 100644 --- a/packages/react-app/src/components/builder/BuilderProfileHeader.jsx +++ b/packages/react-app/src/components/builder/BuilderProfileHeader.jsx @@ -1,6 +1,7 @@ import React from "react"; import { Flex, HStack, Tag, Text } from "@chakra-ui/react"; import { InfoOutlineIcon } from "@chakra-ui/icons"; +import { FormattedMessage } from "react-intl"; import { userFunctionDescription } from "../../helpers/constants"; import useCustomColorModes from "../../hooks/useCustomColorModes"; @@ -18,7 +19,7 @@ export const BuilderProfileHeader = ({ acceptedChallenges, builder }) => { {acceptedChallenges.length} - challenges completed + @@ -37,7 +38,7 @@ export const BuilderProfileHeader = ({ acceptedChallenges, builder }) => { )} - Role + diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 0e9f8a57..4a683c25 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -9,6 +9,7 @@ "builderProfileCard.set-socials.warning": "You haven't set your socials", "builderProfileCard.success.updating-socials": "Your social links have been updated", "builderProfileCard.update-socials": "Update socials", + "builderProfileHeader.challenges": "challenges completed", "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", @@ -32,6 +33,7 @@ "joinedBuidlGuidlBanner.label": "This builder has upgraded to BuidlGuidl", "locked": "Locked", "quest": "Quest", + "role": "Role", "signatureSingUp.write-icon": "write icon", "update": "Update" } \ No newline at end of file From 71a9fdf13a0830095c3bb852c47b0d58869bd1f0 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Wed, 19 Apr 2023 21:48:09 +0200 Subject: [PATCH 13/25] Add i18n to BuilderChallenges --- .../components/builder/BuilderChallenges.jsx | 43 +++++++++++++------ packages/react-app/src/lang/en.json | 13 ++++++ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/packages/react-app/src/components/builder/BuilderChallenges.jsx b/packages/react-app/src/components/builder/BuilderChallenges.jsx index 8ebd33cf..d74e39a9 100644 --- a/packages/react-app/src/components/builder/BuilderChallenges.jsx +++ b/packages/react-app/src/components/builder/BuilderChallenges.jsx @@ -16,6 +16,7 @@ import { Thead, Tr, } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import BuilderProfileChallengesTableSkeleton from "../skeletons/BuilderProfileChallengesTableSkeleton"; import { challengeInfo } from "../../data/challenges"; import DateWithTooltip from "../DateWithTooltip"; @@ -35,7 +36,7 @@ export const BuilderChallenges = ({ <> - Challenges + @@ -47,17 +48,27 @@ export const BuilderChallenges = ({ {isMyProfile && ( )} - Name - Contract - Live Demo - Updated - Status + + + + + + + + + + + + + + + @@ -84,7 +95,7 @@ export const BuilderChallenges = ({ target="_blank" rel="noopener noreferrer" > - Code + @@ -94,7 +105,7 @@ export const BuilderChallenges = ({ target="_blank" rel="noopener noreferrer" > - Demo + @@ -130,19 +141,25 @@ export const BuilderChallenges = ({ {isMyProfile ? ( - Start a new challenge + - Show off your skills. Learn everything you need to build on Ethereum! + ) : ( - This builder hasn't completed any challenges. + )} diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 4a683c25..4614f81a 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,6 +1,17 @@ { "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", + "builderChallenges.challenges": "Challenges", + "builderChallenges.empty-state.button": "Start a challenge", + "builderChallenges.empty-state.description": "Show off your skills. Learn everything you need to build on Ethereum!", + "builderChallenges.empty-state.other-profile": "This builder hasn't completed any challenges.", + "builderChallenges.empty-state.title": "Start a new challenge", + "builderChallenges.start-challenge": "Start a challenge", + "builderChallenges.table.contract": "Contract", + "builderChallenges.table.live-demo": "Live Demo", + "builderChallenges.table.name": "Name", + "builderChallenges.table.status": "Status", + "builderChallenges.table.updated": "Updated", "builderProfileCard.error.invalid-socials": "The usernames for the following socials are not correct: {invalidSocials}", "builderProfileCard.error.updating-socials": "Can't update your socials. Please try again.", "builderProfileCard.joined": "Joined {date}", @@ -11,6 +22,8 @@ "builderProfileCard.update-socials": "Update socials", "builderProfileHeader.challenges": "challenges completed", "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", + "code": "Code", + "demo": "Demo", "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", "error.signature-from-wallet": "Couldn't get a signature from the Wallet", From 3667738db4ffd9c636863d987ff31dc0b618f50d Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Wed, 19 Apr 2023 22:01:35 +0200 Subject: [PATCH 14/25] Add i18n to ChallengeStatusTag --- .../src/components/ChallengeStatusTag.jsx | 22 ++++++++++++++----- packages/react-app/src/lang/en.json | 5 +++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/react-app/src/components/ChallengeStatusTag.jsx b/packages/react-app/src/components/ChallengeStatusTag.jsx index 81441586..fb523772 100644 --- a/packages/react-app/src/components/ChallengeStatusTag.jsx +++ b/packages/react-app/src/components/ChallengeStatusTag.jsx @@ -18,11 +18,13 @@ import { QuestionOutlineIcon } from "@chakra-ui/icons"; import ReactMarkdown from "react-markdown"; import remarkBreaks from "remark-breaks"; import ChakraUIRenderer from "chakra-ui-markdown-renderer"; +import { FormattedMessage, useIntl } from "react-intl"; import { CHALLENGE_SUBMISSION_STATUS } from "../helpers/constants"; import { chakraMarkdownComponents } from "../helpers/chakraMarkdownTheme"; const ChallengeStatusTag = ({ status, comment, autograding }) => { const { isOpen, onOpen, onClose } = useDisclosure(); + const intl = useIntl(); let colorScheme; let label; @@ -30,16 +32,19 @@ const ChallengeStatusTag = ({ status, comment, autograding }) => { switch (status) { case CHALLENGE_SUBMISSION_STATUS.ACCEPTED: { colorScheme = "green"; - label = "Accepted"; + label = intl.formatMessage({ + id: "accepted", + defaultMessage: "Accepted", + }); break; } case CHALLENGE_SUBMISSION_STATUS.REJECTED: { colorScheme = "red"; - label = "Rejected"; + label = intl.formatMessage({ id: "rejected", defaultMessage: "Rejected" }); break; } case CHALLENGE_SUBMISSION_STATUS.SUBMITTED: { - label = "Submitted"; + label = intl.formatMessage({ id: "submitted", defaultMessage: "Submitted" }); break; } default: @@ -56,7 +61,12 @@ const ChallengeStatusTag = ({ status, comment, autograding }) => {
{status !== CHALLENGE_SUBMISSION_STATUS.SUBMITTED && comment && ( - + @@ -66,7 +76,9 @@ const ChallengeStatusTag = ({ status, comment, autograding }) => { - Review feedback + + + {autograding ? ( diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 4614f81a..0572675c 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,4 +1,5 @@ { + "accepted": "Accepted", "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", "builderChallenges.challenges": "Challenges", @@ -22,6 +23,8 @@ "builderProfileCard.update-socials": "Update socials", "builderProfileHeader.challenges": "challenges completed", "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", + "challengeStatusTag.modal.header": "Review feedback", + "challengeStatusTag.see-comments": "See comments", "code": "Code", "demo": "Demo", "error.access-error": "Access error", @@ -46,7 +49,9 @@ "joinedBuidlGuidlBanner.label": "This builder has upgraded to BuidlGuidl", "locked": "Locked", "quest": "Quest", + "rejected": "Rejected", "role": "Role", "signatureSingUp.write-icon": "write icon", + "submitted": "Submitted", "update": "Update" } \ No newline at end of file From a47ebb31bf3c24d8b089ad5f04f4bfde75060f7c Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 24 Apr 2023 12:39:46 +0200 Subject: [PATCH 15/25] Add i18n to ChallengeDetailView --- packages/react-app/src/lang/en.json | 4 ++++ .../src/views/ChallengeDetailView.jsx | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 0572675c..e5a78112 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -23,6 +23,10 @@ "builderProfileCard.update-socials": "Update socials", "builderProfileHeader.challenges": "challenges completed", "builderProfileView.error-getting-challenges": "Can't get challenges metadata. Please try again", + "challengeDetailView.github-button": "View it on Github", + "challengeDetailView.modal.header": "Submit Challenge", + "challengeDetailView.submit-button": "Submit challenge", + "challengeDetailView.submit-button.tooltip.register": "You need to register as a builder", "challengeStatusTag.modal.header": "Review feedback", "challengeStatusTag.see-comments": "See comments", "code": "Code", diff --git a/packages/react-app/src/views/ChallengeDetailView.jsx b/packages/react-app/src/views/ChallengeDetailView.jsx index 5619aaf5..4956365b 100644 --- a/packages/react-app/src/views/ChallengeDetailView.jsx +++ b/packages/react-app/src/views/ChallengeDetailView.jsx @@ -26,6 +26,7 @@ import ReactMarkdown from "react-markdown"; import ChakraUIRenderer from "chakra-ui-markdown-renderer"; import rehypeRaw from "rehype-raw"; +import { FormattedMessage } from "react-intl"; import { challengeInfo } from "../data/challenges"; import ChallengeSubmission from "../components/ChallengeSubmission"; import { chakraMarkdownComponents } from "../helpers/chakraMarkdownTheme"; @@ -98,13 +99,26 @@ export default function ChallengeDetailView({ serverUrl, address, userProvider, target="_blank" rel="noopener noreferrer" > - View it on Github + {" "} + - + + ) : ( + + ) + } + shouldWrapChildren + > @@ -146,7 +160,9 @@ export default function ChallengeDetailView({ serverUrl, address, userProvider, - Submit Challenge + + + Date: Mon, 24 Apr 2023 13:12:48 +0200 Subject: [PATCH 16/25] Add i18n to ChallengeSubmission --- .../src/components/ChallengeSubmission.jsx | 80 +++++++++++++++---- packages/react-app/src/components/JoinBG.jsx | 6 +- packages/react-app/src/lang/en.json | 19 ++++- 3 files changed, 82 insertions(+), 23 deletions(-) diff --git a/packages/react-app/src/components/ChallengeSubmission.jsx b/packages/react-app/src/components/ChallengeSubmission.jsx index 507ea2c6..9615bfe7 100644 --- a/packages/react-app/src/components/ChallengeSubmission.jsx +++ b/packages/react-app/src/components/ChallengeSubmission.jsx @@ -3,6 +3,7 @@ import axios from "axios"; import { useHistory, useParams } from "react-router-dom"; import { Button, Heading, FormControl, FormLabel, Input, Text, Tooltip, useToast } from "@chakra-ui/react"; import { QuestionOutlineIcon } from "@chakra-ui/icons"; +import { FormattedMessage, useIntl } from "react-intl"; import { isValidEtherscanTestnetUrl, isValidUrl } from "../helpers/strings"; const serverPath = "/challenges"; @@ -11,6 +12,7 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use const { challengeId } = useParams(); const history = useHistory(); const toast = useToast({ position: "top", isClosable: true }); + const intl = useIntl(); const [isSubmitting, setIsSubmitting] = useState(false); const [deployedUrl, setDeployedUrl] = useState(""); const [contractUrl, setContractUrl] = useState(""); @@ -20,7 +22,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use if (!deployedUrl || !contractUrl) { toast({ status: "error", - description: "Both fields are required", + description: intl.formatMessage({ + id: "challengeSubmission.error.both-fields-required", + defaultMessage: "Both fields are required", + }), }); return; } @@ -28,8 +33,14 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use if (!isValidUrl(deployedUrl) || !isValidUrl(contractUrl)) { toast({ status: "error", - title: "Please provide a valid URL", - description: "Valid URLs start with http:// or https://", + title: intl.formatMessage({ + id: "challengeSubmission.error.invalid-url.title", + defaultMessage: "Please provide a valid URL", + }), + description: intl.formatMessage({ + id: "challengeSubmission.error.invalid-url.description", + defaultMessage: "Valid URLs start with http:// or https://", + }), }); setHasErrorField({ @@ -43,9 +54,15 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use if (!isValidEtherscanTestnetUrl(contractUrl)) { toast({ status: "error", - title: "Incorrect Etherscan Contract URL", - description: - "Please submit your verified contract’s address on a valid testnet. e.g. https://goerli.etherscan.io/address/**Your Contract Address**", + title: intl.formatMessage({ + id: "challengeSubmission.error.incorrect-contract.title", + defaultMessage: "Incorrect Etherscan Contract URL", + }), + description: intl.formatMessage({ + id: "challengeSubmission.error.incorrect-contract.description", + defaultMessage: + "Please submit your verified contract’s address on a valid testnet. e.g. https://goerli.etherscan.io/address/**Your Contract Address**", + }), }); setHasErrorField({ @@ -70,7 +87,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use signMessage = JSON.stringify(signMessageResponse.data); } catch (error) { toast({ - description: "Can't get the message to sign. Please try again", + description: intl.formatMessage({ + id: "general.error.cant-get-message", + defaultMessage: "Can't get the message to sign. Please try again", + }), status: "error", }); setIsSubmitting(false); @@ -83,7 +103,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use } catch (error) { toast({ status: "error", - description: "The signature was cancelled", + description: intl.formatMessage({ + id: "general.error.signature-cancelled", + defaultMessage: "The signature was cancelled", + }), }); console.error(error); setIsSubmitting(false); @@ -108,7 +131,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use } catch (error) { toast({ status: "error", - description: "Submission Error. Please try again.", + description: intl.formatMessage({ + id: "general.error.submission-error", + defaultMessage: "Submission Error. Please try again.", + }), }); console.error(error); setIsSubmitting(false); @@ -118,7 +144,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use toast({ status: "success", - description: "Challenge submitted!", + description: intl.formatMessage({ + id: "challengeSubmission.challenge-submitted", + defaultMessage: "Challenge submitted!", + }), }); setIsSubmitting(false); history.push("/portfolio"); @@ -127,7 +156,10 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use if (!address) { return ( - Connect your wallet to submit this Challenge. + ); } @@ -139,14 +171,21 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use {challenge.isDisabled ? ( - This challenge is disabled. + ) : (
- Deployed URL{" "} - + {" "} + + } + > @@ -170,8 +209,15 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use - Etherscan Contract URL{" "} - + {" "} + + } + > @@ -195,7 +241,7 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use
diff --git a/packages/react-app/src/components/JoinBG.jsx b/packages/react-app/src/components/JoinBG.jsx index c1f2594a..e54d6a96 100644 --- a/packages/react-app/src/components/JoinBG.jsx +++ b/packages/react-app/src/components/JoinBG.jsx @@ -60,7 +60,7 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user } catch (error) { toast({ description: intl.formatMessage({ - id: `joinBg.get-message-failed`, + id: "general.error.cant-get-message", defaultMessage: "Can't get the message to sign. Please try again", }), status: "error", @@ -76,7 +76,7 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user toast({ status: "error", description: intl.formatMessage({ - id: "joinBg.signature-cancelled", + id: "general.error.signature-cancelled", defaultMessage: "The signature was cancelled", }), }); @@ -103,7 +103,7 @@ export default function JoinBG({ text, connectedBuilder, isChallengeLocked, user description: error?.response?.data ?? intl.formatMessage({ - id: "joinBg.signature-submission-error", + id: "general.error.submission-error", defaultMessage: "Submission Error. Please try again.", }), }); diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index e5a78112..5f491965 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,4 +1,5 @@ { + "Submit": "Submit", "accepted": "Accepted", "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", @@ -29,11 +30,26 @@ "challengeDetailView.submit-button.tooltip.register": "You need to register as a builder", "challengeStatusTag.modal.header": "Review feedback", "challengeStatusTag.see-comments": "See comments", + "challengeSubmission.challenge-submitted": "Challenge submitted!", + "challengeSubmission.connect-wallet": "Connect your wallet to submit this Challenge.", + "challengeSubmission.deployed-url": "Deployed URL", + "challengeSubmission.deployed-url.tooltip": "Your deployed challenge URL on surge / s3 / ipfs", + "challengeSubmission.disabled": "This challenge is disabled.", + "challengeSubmission.error.both-fields-required": "Both fields are required", + "challengeSubmission.error.incorrect-contract.description": "Please submit your verified contract’s address on a valid testnet. e.g. https://goerli.etherscan.io/address/**Your Contract Address**", + "challengeSubmission.error.incorrect-contract.title": "Incorrect Etherscan Contract URL", + "challengeSubmission.error.invalid-url.description": "Valid URLs start with http:// or https://", + "challengeSubmission.error.invalid-url.title": "Please provide a valid URL", + "challengeSubmission.etherscan-url": "Etherscan Contract URL", + "challengeSubmission.etherscan-url.tooltip": "Your verified contract URL on Etherscan", "code": "Code", "demo": "Demo", "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", "error.signature-from-wallet": "Couldn't get a signature from the Wallet", + "general.error.cant-get-message": "Can't get the message to sign. Please try again", + "general.error.signature-cancelled": "The signature was cancelled", + "general.error.submission-error": "Submission Error. Please try again.", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:", @@ -42,11 +58,8 @@ "index.step-3": "Watch this getting started playlist to become a power user and eth scripter.", "index.step-4": "When you are ready to test your knowledge, Speed Run Ethereum:", "joinBg.button.already-joined": "Already joined", - "joinBg.get-message-failed": "Can't get the message to sign. Please try again", "joinBg.missing-socials.description": "In order to join the BuildGuidl you need to set your socials in your portfolio. It's our way to contact you.", "joinBg.missing-socials.title": "Can't join the BuidlGuidl", - "joinBg.signature-cancelled": "The signature was cancelled", - "joinBg.signature-submission-error": "Submission Error. Please try again.", "joinBg.success.description": "Visit BuidlGuidl and start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", "joinBg.success.title": "Welcome to the BuildGuidl :)", "joinedBuidlGuidlBanner.button": "View their profile on Buidlguidl", From 1369ad944ecfa5179a66e1040f92049752a9bd3f Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 24 Apr 2023 13:17:08 +0200 Subject: [PATCH 17/25] Use 'general' to group generic messages --- .../src/components/ChallengeExpandedCard.jsx | 8 +++---- .../src/components/ChallengeStatusTag.jsx | 6 ++--- .../src/components/ChallengeSubmission.jsx | 2 +- .../components/builder/BuilderChallenges.jsx | 4 ++-- .../components/builder/BuilderProfileCard.jsx | 2 +- .../builder/BuilderProfileHeader.jsx | 2 +- packages/react-app/src/lang/en.json | 22 +++++++++---------- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/react-app/src/components/ChallengeExpandedCard.jsx b/packages/react-app/src/components/ChallengeExpandedCard.jsx index b48fef62..94c1b59f 100644 --- a/packages/react-app/src/components/ChallengeExpandedCard.jsx +++ b/packages/react-app/src/components/ChallengeExpandedCard.jsx @@ -146,7 +146,7 @@ const ChallengeExpandedCard = ({ - + @@ -286,7 +286,7 @@ const ChallengeExpandedCard = ({ - + )} @@ -317,14 +317,14 @@ const ChallengeExpandedCard = ({ - + ) : ( - + )} diff --git a/packages/react-app/src/components/ChallengeStatusTag.jsx b/packages/react-app/src/components/ChallengeStatusTag.jsx index fb523772..b37236fa 100644 --- a/packages/react-app/src/components/ChallengeStatusTag.jsx +++ b/packages/react-app/src/components/ChallengeStatusTag.jsx @@ -33,18 +33,18 @@ const ChallengeStatusTag = ({ status, comment, autograding }) => { case CHALLENGE_SUBMISSION_STATUS.ACCEPTED: { colorScheme = "green"; label = intl.formatMessage({ - id: "accepted", + id: "general.accepted", defaultMessage: "Accepted", }); break; } case CHALLENGE_SUBMISSION_STATUS.REJECTED: { colorScheme = "red"; - label = intl.formatMessage({ id: "rejected", defaultMessage: "Rejected" }); + label = intl.formatMessage({ id: "general.rejected", defaultMessage: "Rejected" }); break; } case CHALLENGE_SUBMISSION_STATUS.SUBMITTED: { - label = intl.formatMessage({ id: "submitted", defaultMessage: "Submitted" }); + label = intl.formatMessage({ id: "general.submitted", defaultMessage: "Submitted" }); break; } default: diff --git a/packages/react-app/src/components/ChallengeSubmission.jsx b/packages/react-app/src/components/ChallengeSubmission.jsx index 9615bfe7..8bfbb5b0 100644 --- a/packages/react-app/src/components/ChallengeSubmission.jsx +++ b/packages/react-app/src/components/ChallengeSubmission.jsx @@ -241,7 +241,7 @@ export default function ChallengeSubmission({ challenge, serverUrl, address, use
diff --git a/packages/react-app/src/components/builder/BuilderChallenges.jsx b/packages/react-app/src/components/builder/BuilderChallenges.jsx index d74e39a9..3560ec83 100644 --- a/packages/react-app/src/components/builder/BuilderChallenges.jsx +++ b/packages/react-app/src/components/builder/BuilderChallenges.jsx @@ -95,7 +95,7 @@ export const BuilderChallenges = ({ target="_blank" rel="noopener noreferrer" > - + @@ -105,7 +105,7 @@ export const BuilderChallenges = ({ target="_blank" rel="noopener noreferrer" > - + diff --git a/packages/react-app/src/components/builder/BuilderProfileCard.jsx b/packages/react-app/src/components/builder/BuilderProfileCard.jsx index a50e67a2..c63c0e05 100644 --- a/packages/react-app/src/components/builder/BuilderProfileCard.jsx +++ b/packages/react-app/src/components/builder/BuilderProfileCard.jsx @@ -375,7 +375,7 @@ const BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvide
))}
diff --git a/packages/react-app/src/components/builder/BuilderProfileHeader.jsx b/packages/react-app/src/components/builder/BuilderProfileHeader.jsx index fa67dc56..532c0b78 100644 --- a/packages/react-app/src/components/builder/BuilderProfileHeader.jsx +++ b/packages/react-app/src/components/builder/BuilderProfileHeader.jsx @@ -38,7 +38,7 @@ export const BuilderProfileHeader = ({ acceptedChallenges, builder }) => { )} - + diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index 5f491965..1b88fbda 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -1,6 +1,4 @@ { - "Submit": "Submit", - "accepted": "Accepted", "account.connect-wallet": "Connect Wallet", "announcementBanner": "Hey builder!! The BuidlGuidl is hosting a πŸ— Scaffold-Eth 2 hackathon. We are giving 10 ETH away to the best projects. {br}Come join the fun and learn the latest scaffold-eth techniques! Let's build a bunch of apps!", "builderChallenges.challenges": "Challenges", @@ -42,14 +40,22 @@ "challengeSubmission.error.invalid-url.title": "Please provide a valid URL", "challengeSubmission.etherscan-url": "Etherscan Contract URL", "challengeSubmission.etherscan-url.tooltip": "Your verified contract URL on Etherscan", - "code": "Code", - "demo": "Demo", "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", "error.signature-from-wallet": "Couldn't get a signature from the Wallet", + "general.Submit": "Submit", + "general.accepted": "Accepted", + "general.code": "Code", + "general.demo": "Demo", "general.error.cant-get-message": "Can't get the message to sign. Please try again", "general.error.signature-cancelled": "The signature was cancelled", "general.error.submission-error": "Submission Error. Please try again.", + "general.locked": "Locked", + "general.quest": "Quest", + "general.rejected": "Rejected", + "general.role": "Role", + "general.submitted": "Submitted", + "general.update": "Update", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:", @@ -64,11 +70,5 @@ "joinBg.success.title": "Welcome to the BuildGuidl :)", "joinedBuidlGuidlBanner.button": "View their profile on Buidlguidl", "joinedBuidlGuidlBanner.label": "This builder has upgraded to BuidlGuidl", - "locked": "Locked", - "quest": "Quest", - "rejected": "Rejected", - "role": "Role", - "signatureSingUp.write-icon": "write icon", - "submitted": "Submitted", - "update": "Update" + "signatureSingUp.write-icon": "write icon" } \ No newline at end of file From 01548a19f95027a45744d152793aa1df1376917e Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Mon, 24 Apr 2023 13:17:51 +0200 Subject: [PATCH 18/25] Fix typo --- packages/react-app/src/components/SignatureSignUp.jsx | 2 +- packages/react-app/src/lang/en.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-app/src/components/SignatureSignUp.jsx b/packages/react-app/src/components/SignatureSignUp.jsx index 75d3a228..b4f33f95 100644 --- a/packages/react-app/src/components/SignatureSignUp.jsx +++ b/packages/react-app/src/components/SignatureSignUp.jsx @@ -72,7 +72,7 @@ const SignatureSignUp = forwardRef(({ address, userProvider, onSuccess, setUserR
{ const { primaryFontColor, secondaryFontColor, borderColor, linkColor } = useCustomColorModes(); + const intl = useIntl(); + const challengeInfo = getChallengeInfo(intl); return ( <> diff --git a/packages/react-app/src/data/api.js b/packages/react-app/src/data/api.js index 2915f16f..bf93e13c 100644 --- a/packages/react-app/src/data/api.js +++ b/packages/react-app/src/data/api.js @@ -197,9 +197,9 @@ export const getDraftBuilds = async address => { } }; -export const getChallengeReadme = async (challengeId, version) => { +export const getChallengeReadme = async (challengeId, version, intl) => { try { - const response = await axios.get(getGithubChallengeReadmeUrl(challengeId, version)); + const response = await axios.get(getGithubChallengeReadmeUrl(challengeId, version, intl)); return response.data; } catch (err) { console.log("error fetching challenge README", err); diff --git a/packages/react-app/src/data/challenges.js b/packages/react-app/src/data/challenges.js index a5217afd..3ea4c9ac 100644 --- a/packages/react-app/src/data/challenges.js +++ b/packages/react-app/src/data/challenges.js @@ -1,45 +1,69 @@ -export const challengeInfo = { +export const getChallengeInfo = intl => ({ "simple-nft-example": { id: 0, branchName: "challenge-0-simple-nft", - label: "🚩 Challenge 0: 🎟 Simple NFT Example", + label: intl.formatMessage({ + id: "challenges.challenge-0-simple-nft.label", + defaultMessage: "🚩 Challenge 0: 🎟 Simple NFT Example", + }), disabled: false, - description: - "🎫 Create a simple NFT to learn basics of πŸ— scaffold-eth. You'll use πŸ‘·β€β™€οΈ HardHat to compile and deploy smart contracts. Then, you'll use a template React app full of important Ethereum components and hooks. Finally, you'll deploy an NFT to a public network to share with friends! πŸš€", + description: intl.formatMessage({ + id: "challenges.challenge-0-simple-nft.description", + defaultMessage: + "🎫 Create a simple NFT to learn basics of πŸ— scaffold-eth. You'll use πŸ‘·β€β™€οΈ HardHat to compile and deploy smart contracts. Then, you'll use a template React app full of important Ethereum components and hooks. Finally, you'll deploy an NFT to a public network to share with friends! πŸš€", + }), previewImage: "/assets/challenges/simpleNFT.svg", dependencies: [], }, "decentralized-staking": { id: 1, branchName: "challenge-1-decentralized-staking", - label: "🚩 Challenge 1: πŸ₯© Decentralized Staking App ", + label: intl.formatMessage({ + id: "challenges.challenge-1-decentralized-staking.label", + defaultMessage: "🚩 Challenge 1: πŸ₯© Decentralized Staking App ", + }), disabled: false, - description: - "🦸 A superpower of Ethereum is allowing you, the builder, to create a simple set of rules that an adversarial group of players can use to work together. In this challenge, you create a decentralized application where users can coordinate a group funding effort. The users only have to trust the code.", + description: intl.formatMessage({ + id: "challenges.challenge-1-decentralized-staking.description", + defaultMessage: + "🦸 A superpower of Ethereum is allowing you, the builder, to create a simple set of rules that an adversarial group of players can use to work together. In this challenge, you create a decentralized application where users can coordinate a group funding effort. The users only have to trust the code.", + }), previewImage: "/assets/challenges/stakingToken.svg", dependencies: [], }, "token-vendor": { id: 2, branchName: "challenge-2-token-vendor", - label: "🚩 Challenge 2: 🏡 Token Vendor", + label: intl.formatMessage({ + id: "challenges.challenge-2-token-vendor.label", + defaultMessage: "🚩 Challenge 2: 🏡 Token Vendor", + }), icon: "/assets/key_icon.svg", disabled: false, - description: - 'πŸ€– Smart contracts are kind of like "always on" vending machines that anyone can access. Let\'s make a decentralized, digital currency (an ERC20 token). Then, let\'s build an unstoppable vending machine that will buy and sell the currency. We\'ll learn about the "approve" pattern for ERC20s and how contract to contract interactions work.', + description: intl.formatMessage({ + id: "challenges.challenge-2-token-vendor.description", + defaultMessage: + 'πŸ€– Smart contracts are kind of like "always on" vending machines that anyone can access. Let\'s make a decentralized, digital currency (an ERC20 token). Then, let\'s build an unstoppable vending machine that will buy and sell the currency. We\'ll learn about the "approve" pattern for ERC20s and how contract to contract interactions work.', + }), previewImage: "/assets/challenges/tokenVendor.svg", dependencies: [], }, "buidl-guidl": { id: 4, branchName: "", - label: "Eligible to join 🏰️ BuidlGuidl", + label: intl.formatMessage({ + id: "challenges.buidl-guidl.label", + defaultMessage: "Eligible to join 🏰️ BuidlGuidl", + }), icon: "/assets/vault_icon.svg", // Not a challenge, just a checkpoint in the Challenge timeline. checkpoint: true, disabled: false, - description: - "The BuidlGuidl is a curated group of Ethereum builders creating products, prototypes, and tutorials to enrich the web3 ecosystem. A place to show off your builds and meet other builders. Start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", + description: intl.formatMessage({ + id: "challenges.buidl-guidl.description", + defaultMessage: + "The BuidlGuidl is a curated group of Ethereum builders creating products, prototypes, and tutorials to enrich the web3 ecosystem. A place to show off your builds and meet other builders. Start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", + }), previewImage: "assets/bg.png", dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor"], externalLink: { @@ -50,40 +74,64 @@ export const challengeInfo = { "dice-game": { id: 3, branchName: "challenge-3-dice-game", - label: "🚩 Challenge 3: 🎲 Dice Game", + label: intl.formatMessage({ + id: "challenges.challenge-3-dice-game.label", + defaultMessage: "🚩 Challenge 3: 🎲 Dice Game", + }), disabled: false, - description: - "🎰 Randomness is tricky on a public deterministic blockchain. The block hash is the result proof-of-work (for now) and some builders use this as a weak form of randomness. In this challenge you will take advantage of a Dice Game contract by predicting the randomness in order to only roll winning dice!", + description: intl.formatMessage({ + id: "challenges.challenge-3-dice-game.description", + defaultMessage: + "🎰 Randomness is tricky on a public deterministic blockchain. The block hash is the result proof-of-work (for now) and some builders use this as a weak form of randomness. In this challenge you will take advantage of a Dice Game contract by predicting the randomness in order to only roll winning dice!", + }), previewImage: "/assets/challenges/diceGame.svg", dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor"], }, "minimum-viable-exchange": { id: 5, branchName: "challenge-4-dex", - label: "βš–οΈ Build a DEX Challenge", + label: intl.formatMessage({ + id: "challenges.challenge-4-dex.label", + defaultMessage: "βš–οΈ Build a DEX Challenge", + }), disabled: false, - description: - "πŸ’΅ Build an exchange that swaps ETH to tokens and tokens to ETH. πŸ’° This is possible because the smart contract holds reserves of both assets and has a price function based on the ratio of the reserves. Liquidity providers are issued a token that represents their share of the reserves and fees...", + description: intl.formatMessage({ + id: "challenges.challenge-4-dex.description", + defaultMessage: + "πŸ’΅ Build an exchange that swaps ETH to tokens and tokens to ETH. πŸ’° This is possible because the smart contract holds reserves of both assets and has a price function based on the ratio of the reserves. Liquidity providers are issued a token that represents their share of the reserves and fees...", + }), previewImage: "assets/challenges/dex.svg", dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor", "dice-game"], }, "state-channels": { id: 9, branchName: "challenge-9-state-channels", - label: "πŸ“Ί A State Channel Application Challenge", + label: intl.formatMessage({ + id: "challenges.challenge-9-state-channels.label", + defaultMessage: "πŸ“Ί A State Channel Application Challenge", + }), disabled: false, - description: - "πŸ›£οΈ The Ethereum blockchain has great decentralization & security properties but these properties come at a price: transaction throughput is low, and transactions can be expensive. This makes many traditional web applications infeasible on a blockchain... or does it? State channels look to solve these problems by allowing participants to securely transact off-chain while keeping interaction with Ethereum Mainnet at a minimum.", + description: intl.formatMessage({ + id: "challenges.challenge-9-state-channels.description", + defaultMessage: + "πŸ›£οΈ The Ethereum blockchain has great decentralization & security properties but these properties come at a price: transaction throughput is low, and transactions can be expensive. This makes many traditional web applications infeasible on a blockchain... or does it? State channels look to solve these problems by allowing participants to securely transact off-chain while keeping interaction with Ethereum Mainnet at a minimum.", + }), previewImage: "assets/challenges/state.svg", dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor", "dice-game"], }, "learn-multisig": { id: 6, branchName: "challenge-3-multi-sig", - label: "πŸ‘› Multisig Wallet Challenge", + label: intl.formatMessage({ + id: "challenges.challenge-3-multi-sig.label", + defaultMessage: "πŸ‘› Multisig Wallet Challenge", + }), disabled: false, - description: - 'πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§ Using a smart contract as a wallet we can secure assets by requiring multiple accounts to "vote" on transactions. The contract will keep track of transactions in an array of structs and owners will confirm or reject each one. Any transaction with enough confirmations can "execute".', + description: intl.formatMessage({ + id: "challenges.challenge-3-multi-sig.description", + defaultMessage: + 'πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§ Using a smart contract as a wallet we can secure assets by requiring multiple accounts to "vote" on transactions. The contract will keep track of transactions in an array of structs and owners will confirm or reject each one. Any transaction with enough confirmations can "execute".', + }), previewImage: "assets/challenges/multiSig.svg", // Challenge locked until the builder completed these challenges dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor", "dice-game"], @@ -97,10 +145,16 @@ export const challengeInfo = { "nft-cohort": { id: 7, branchName: "challenge-5-svg-nft-cohort", - label: "🎁 SVG NFT 🎫 Building Cohort Challenge", + label: intl.formatMessage({ + id: "challenges.challenge-5-svg-nft-cohort.label", + defaultMessage: "🎁 SVG NFT 🎫 Building Cohort Challenge", + }), disabled: false, - description: - "πŸ§™ Tinker around with cutting edge smart contracts that render SVGs in Solidity. 🧫 We quickly discovered that the render function needs to be public... πŸ€” This allows NFTs that own other NFTs to render their stash. Just wait until you see an Optimistic Loogie and a Fancy Loogie swimming around in the same Loogie Tank!", + description: intl.formatMessage({ + id: "challenges.challenge-5-svg-nft-cohort.description", + defaultMessage: + "πŸ§™ Tinker around with cutting edge smart contracts that render SVGs in Solidity. 🧫 We quickly discovered that the render function needs to be public... πŸ€” This allows NFTs that own other NFTs to render their stash. Just wait until you see an Optimistic Loogie and a Fancy Loogie swimming around in the same Loogie Tank!", + }), previewImage: "assets/challenges/dynamicSvgNFT.svg", // Challenge locked until the builder completed these challenges dependencies: ["simple-nft-example", "decentralized-staking", "token-vendor", "dice-game"], @@ -111,12 +165,12 @@ export const challengeInfo = { claim: "Join the 🎁 SVG NFT 🎫 Building Cohort", }, }, -}; +}); const githubChallengesRepoBaseRawUrl = { js: "https://raw.githubusercontent.com/scaffold-eth/scaffold-eth-challenges", ts: "https://raw.githubusercontent.com/scaffold-eth/scaffold-eth-typescript-challenges", }; -export const getGithubChallengeReadmeUrl = (challengeId, version) => - `${githubChallengesRepoBaseRawUrl[version]}/${challengeInfo[challengeId].branchName}/README.md`; +export const getGithubChallengeReadmeUrl = (challengeId, version, intl) => + `${githubChallengesRepoBaseRawUrl[version]}/${getChallengeInfo(intl)[challengeId].branchName}/README.md`; diff --git a/packages/react-app/src/index.jsx b/packages/react-app/src/index.jsx index 67ad25ce..ef51667b 100644 --- a/packages/react-app/src/index.jsx +++ b/packages/react-app/src/index.jsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import ReactDOM from "react-dom"; import { BrowserRouter } from "react-router-dom"; import "@fontsource/space-grotesk/400.css"; @@ -20,14 +20,18 @@ const translations = { // TODO: change from ui const userLocale = "en"; -ReactDOM.render( - - - - - - - - , - document.getElementById("root"), -); +const Root = () => { + const [locale, setLocale] = useState(userLocale); + return ( + + + + + + + + + ); +}; + +ReactDOM.render(, document.getElementById("root")); diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index dbb1609a..bce9234c 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -40,6 +40,24 @@ "challengeSubmission.error.invalid-url.title": "Please provide a valid URL", "challengeSubmission.etherscan-url": "Etherscan Contract URL", "challengeSubmission.etherscan-url.tooltip": "Your verified contract URL on Etherscan", + "challenges.buidl-guidl.description": "The BuidlGuidl is a curated group of Ethereum builders creating products, prototypes, and tutorials to enrich the web3 ecosystem. A place to show off your builds and meet other builders. Start crafting your Web3 portfolio by submitting your DEX, Multisig or SVG NFT build.", + "challenges.buidl-guidl.label": "Eligible to join 🏰️ BuidlGuidl", + "challenges.challenge-0-simple-nft.description": "🎫 Create a simple NFT to learn basics of πŸ— scaffold-eth. You'll use πŸ‘·β€β™€οΈ HardHat to compile and deploy smart contracts. Then, you'll use a template React app full of important Ethereum components and hooks. Finally, you'll deploy an NFT to a public network to share with friends! πŸš€", + "challenges.challenge-0-simple-nft.label": "🚩 Challenge 0: 🎟 Simple NFT Example", + "challenges.challenge-1-decentralized-staking.description": "🦸 A superpower of Ethereum is allowing you, the builder, to create a simple set of rules that an adversarial group of players can use to work together. In this challenge, you create a decentralized application where users can coordinate a group funding effort. The users only have to trust the code.", + "challenges.challenge-1-decentralized-staking.label": "🚩 Challenge 1: πŸ₯© Decentralized Staking App", + "challenges.challenge-2-token-vendor.description": "πŸ€– Smart contracts are kind of like \"always on\" vending machines that anyone can access. Let's make a decentralized, digital currency (an ERC20 token). Then, let's build an unstoppable vending machine that will buy and sell the currency. We'll learn about the \"approve\" pattern for ERC20s and how contract to contract interactions work.", + "challenges.challenge-2-token-vendor.label": "🚩 Challenge 2: 🏡 Token Vendor", + "challenges.challenge-3-dice-game.description": "🎰 Randomness is tricky on a public deterministic blockchain. The block hash is the result proof-of-work (for now) and some builders use this as a weak form of randomness. In this challenge you will take advantage of a Dice Game contract by predicting the randomness in order to only roll winning dice!", + "challenges.challenge-3-dice-game.label": "🚩 Challenge 3: 🎲 Dice Game", + "challenges.challenge-3-multi-sig.description": "πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§ Using a smart contract as a wallet we can secure assets by requiring multiple accounts to \"vote\" on transactions. The contract will keep track of transactions in an array of structs and owners will confirm or reject each one. Any transaction with enough confirmations can \"execute\".", + "challenges.challenge-3-multi-sig.label": "πŸ‘› Multisig Wallet Challenge", + "challenges.challenge-4-dex.description": "πŸ’΅ Build an exchange that swaps ETH to tokens and tokens to ETH. πŸ’° This is possible because the smart contract holds reserves of both assets and has a price function based on the ratio of the reserves. Liquidity providers are issued a token that represents their share of the reserves and fees...", + "challenges.challenge-4-dex.label": "βš–οΈ Build a DEX Challenge", + "challenges.challenge-5-svg-nft-cohort.description": "πŸ§™ Tinker around with cutting edge smart contracts that render SVGs in Solidity. 🧫 We quickly discovered that the render function needs to be public... πŸ€” This allows NFTs that own other NFTs to render their stash. Just wait until you see an Optimistic Loogie and a Fancy Loogie swimming around in the same Loogie Tank!", + "challenges.challenge-5-svg-nft-cohort.label": "🎁 SVG NFT 🎫 Building Cohort Challenge", + "challenges.challenge-9-state-channels.description": "πŸ›£οΈ The Ethereum blockchain has great decentralization & security properties but these properties come at a price: transaction throughput is low, and transactions can be expensive. This makes many traditional web applications infeasible on a blockchain... or does it? State channels look to solve these problems by allowing participants to securely transact off-chain while keeping interaction with Ethereum Mainnet at a minimum.", + "challenges.challenge-9-state-channels.label": "πŸ“Ί A State Channel Application Challenge", "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", "error.signature-from-wallet": "Couldn't get a signature from the Wallet", diff --git a/packages/react-app/src/lang/es.json b/packages/react-app/src/lang/es.json index a753fd93..69d21ebc 100644 --- a/packages/react-app/src/lang/es.json +++ b/packages/react-app/src/lang/es.json @@ -1,4 +1,5 @@ { "account.connect-wallet": "Conectar Wallet", - "index.learn-ethereum": "Aprender a desarrollar en Ethereum; los super poderes y los trucos." + "index.learn-ethereum": "Aprender a desarrollar en Ethereum; los super poderes y los trucos.", + "challenges.simple-nft-example.label": "🚩 Reto 0: 🎟 Ejemplo de NFT Simple" } diff --git a/packages/react-app/src/views/BuilderProfileView.jsx b/packages/react-app/src/views/BuilderProfileView.jsx index 89ae6dfd..ddc9e5a6 100644 --- a/packages/react-app/src/views/BuilderProfileView.jsx +++ b/packages/react-app/src/views/BuilderProfileView.jsx @@ -4,7 +4,7 @@ import axios from "axios"; import { useToast, useColorModeValue, Container, SimpleGrid, GridItem, Box } from "@chakra-ui/react"; import { useIntl } from "react-intl"; import BuilderProfileCard from "../components/builder/BuilderProfileCard"; -import { challengeInfo } from "../data/challenges"; +import { getChallengeInfo } from "../data/challenges"; import { BG_BACKEND_URL as bgBackendUrl } from "../constants"; import { getAcceptedChallenges } from "../helpers/builders"; import { getChallengeEventsForUser } from "../data/api"; @@ -28,6 +28,7 @@ export default function BuilderProfileView({ const [isBuilderOnBg, setIsBuilderOnBg] = useState(false); const [isLoadingTimestamps, setIsLoadingTimestamps] = useState(false); const intl = useIntl(); + const challengeInfo = getChallengeInfo(intl); const toast = useToast({ position: "top", isClosable: true }); const toastVariant = useColorModeValue("subtle", "solid"); const bgColor = useColorModeValue("sre.cardBackground", "sreDark.cardBackground"); diff --git a/packages/react-app/src/views/ChallengeDetailView.jsx b/packages/react-app/src/views/ChallengeDetailView.jsx index 4956365b..d9555569 100644 --- a/packages/react-app/src/views/ChallengeDetailView.jsx +++ b/packages/react-app/src/views/ChallengeDetailView.jsx @@ -26,8 +26,8 @@ import ReactMarkdown from "react-markdown"; import ChakraUIRenderer from "chakra-ui-markdown-renderer"; import rehypeRaw from "rehype-raw"; -import { FormattedMessage } from "react-intl"; -import { challengeInfo } from "../data/challenges"; +import { FormattedMessage, useIntl } from "react-intl"; +import { getChallengeInfo } from "../data/challenges"; import ChallengeSubmission from "../components/ChallengeSubmission"; import { chakraMarkdownComponents } from "../helpers/chakraMarkdownTheme"; import { USER_ROLES, JS_CHALLENGE_REPO, TS_CHALLENGE_REPO } from "../helpers/constants"; @@ -43,6 +43,8 @@ export default function ChallengeDetailView({ serverUrl, address, userProvider, const [openModalOnLoad, setOpenModalOnLoad] = useState(false); const bgColor = useColorModeValue("sre.cardBackground", "sreDark.cardBackground"); + const intl = useIntl(); + const challengeInfo = getChallengeInfo(intl); const challenge = challengeInfo[challengeId]; const isWalletConnected = !!userRole; const isAnonymous = userRole && USER_ROLES.anonymous === userRole; @@ -51,11 +53,11 @@ export default function ChallengeDetailView({ serverUrl, address, userProvider, // In the future, this might be a fetch to the repos/branchs README // (Ideally fetched at build time) useEffect(() => { - getChallengeReadme(challengeId, "js") + getChallengeReadme(challengeId, "js", intl) .then(text => setDescriptionJs(parseGithubReadme(text))) .catch(() => setDescriptionJs(null)); - getChallengeReadme(challengeId, "ts") + getChallengeReadme(challengeId, "ts", intl) .then(text => setDescriptionTs(parseGithubReadme(text))) .catch(() => setDescriptionTs(null)); }, [challengeId, challenge]); diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index e544ddea..87e5d87a 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -1,8 +1,8 @@ import React, { useMemo } from "react"; import { Container, Box, Text, Center, useColorModeValue } from "@chakra-ui/react"; -import { FormattedMessage } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import ChallengeExpandedCard from "../components/ChallengeExpandedCard"; -import { challengeInfo } from "../data/challenges"; +import { getChallengeInfo } from "../data/challenges"; import useCustomColorModes from "../hooks/useCustomColorModes"; import HeroLogo from "../components/icons/HeroLogo"; import HeroDiamond from "../components/icons/HeroDiamond"; @@ -27,7 +27,8 @@ const BulletNumber = ({ children, bgColor, primaryFontColor }) => ( export default function HomeView({ connectedBuilder, userProvider }) { const { primaryFontColor, bgColor } = useCustomColorModes(); const cardBgColor = useColorModeValue("sre.cardBackground", "sreDark.cardBackground"); - + const intl = useIntl(); + const challengeInfo = getChallengeInfo(intl); const builderAttemptedChallenges = useMemo(() => { if (!connectedBuilder?.challenges) { return []; From 441875b2f938056ebc2df519b12707a278d11168 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Fri, 28 Apr 2023 13:17:09 +0200 Subject: [PATCH 20/25] Remove lang switch example button --- packages/react-app/src/App.jsx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/react-app/src/App.jsx b/packages/react-app/src/App.jsx index 22315c38..2f1e7323 100644 --- a/packages/react-app/src/App.jsx +++ b/packages/react-app/src/App.jsx @@ -171,19 +171,6 @@ function App({ setLocale }) { return ( -
Date: Wed, 3 May 2023 12:18:30 +0200 Subject: [PATCH 21/25] Remove unused import --- packages/react-app/src/App.jsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-app/src/App.jsx b/packages/react-app/src/App.jsx index 2f1e7323..72754708 100644 --- a/packages/react-app/src/App.jsx +++ b/packages/react-app/src/App.jsx @@ -6,7 +6,6 @@ import Web3Modal from "web3modal"; import WalletConnectProvider from "@walletconnect/web3-provider"; import { useUserAddress } from "eth-hooks"; import axios from "axios"; -import { useIntl } from "react-intl"; import { useUserProvider } from "./hooks"; import { Header, ColorModeSwitcher } from "./components"; import { INFURA_ID, SERVER_URL as serverUrl } from "./constants"; @@ -167,7 +166,6 @@ function App({ setLocale }) { } }, [address, fetchUserData]); - const intl = useIntl(); return ( From 146cf9cbfb6467edc4d23543949603e7b32748bb Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Wed, 3 May 2023 12:21:19 +0200 Subject: [PATCH 22/25] Fix div as child of p --- packages/react-app/src/views/HomeView.jsx | 90 +++++++++++------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/packages/react-app/src/views/HomeView.jsx b/packages/react-app/src/views/HomeView.jsx index 87e5d87a..632aa985 100644 --- a/packages/react-app/src/views/HomeView.jsx +++ b/packages/react-app/src/views/HomeView.jsx @@ -156,56 +156,54 @@ export default function HomeView({ connectedBuilder, userProvider }) { }} textAlign="center" > -
- global units, primitives, mappings, structs, modifiers, events, `} - values={{ - a_globalUnits: chunks => ( - - {chunks} - - ), - a_primitives: chunks => ( - - {chunks} - - ), - a_mappings: chunks => ( - - {chunks} - - ), - a_structs: chunks => ( - - {chunks} - - ), - a_modifiers: chunks => ( - - {chunks} - - ), - a_events: chunks => ( - - {chunks} - - ), - }} - /> -
{" "} + values={{ + a_globalUnits: chunks => ( + + {chunks} + + ), + a_primitives: chunks => ( + + {chunks} + + ), + a_mappings: chunks => ( + + {chunks} + + ), + a_structs: chunks => ( + + {chunks} + + ), + a_modifiers: chunks => ( + + {chunks} + + ), + a_events: chunks => ( + + {chunks} + + ), + }} + />{" "} Date: Wed, 3 May 2023 13:01:29 +0200 Subject: [PATCH 23/25] Add intl dependency to useEffect --- packages/react-app/src/views/ChallengeDetailView.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-app/src/views/ChallengeDetailView.jsx b/packages/react-app/src/views/ChallengeDetailView.jsx index d9555569..db3fe5b9 100644 --- a/packages/react-app/src/views/ChallengeDetailView.jsx +++ b/packages/react-app/src/views/ChallengeDetailView.jsx @@ -60,7 +60,7 @@ export default function ChallengeDetailView({ serverUrl, address, userProvider, getChallengeReadme(challengeId, "ts", intl) .then(text => setDescriptionTs(parseGithubReadme(text))) .catch(() => setDescriptionTs(null)); - }, [challengeId, challenge]); + }, [challengeId, challenge, intl]); useEffect(() => { if (!isWalletConnected || isAnonymous) return; From 6a85ac3225a08eebef0e9ed889339c22ed2acb06 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Thu, 11 May 2023 22:12:52 +0200 Subject: [PATCH 24/25] Removed unused prop setLocale --- packages/react-app/src/App.jsx | 5 ++--- packages/react-app/src/index.jsx | 24 ++++++++++-------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/react-app/src/App.jsx b/packages/react-app/src/App.jsx index 084a1602..eab64028 100644 --- a/packages/react-app/src/App.jsx +++ b/packages/react-app/src/App.jsx @@ -41,7 +41,7 @@ const web3Modal = new Web3Modal({ }, }); -function App({ setLocale }) { +function App() { const [providers, setProviders] = useState({ mainnet: { provider: null, isReady: false }, local: { provider: null, isReady: false }, @@ -129,7 +129,7 @@ function App({ setLocale }) { const logoutOfWeb3Modal = async () => { await web3Modal.clearCachedProvider(); - if (injectedProvider && injectedProvider.provider && typeof injectedProvider.provider.disconnect == "function") { + if (injectedProvider && injectedProvider.provider && typeof injectedProvider.provider.disconnect === "function") { await injectedProvider.provider.disconnect(); } setTimeout(() => { @@ -165,7 +165,6 @@ function App({ setLocale }) { } }, [address, fetchUserData]); - return (
diff --git a/packages/react-app/src/index.jsx b/packages/react-app/src/index.jsx index ef51667b..64033624 100644 --- a/packages/react-app/src/index.jsx +++ b/packages/react-app/src/index.jsx @@ -20,18 +20,14 @@ const translations = { // TODO: change from ui const userLocale = "en"; -const Root = () => { - const [locale, setLocale] = useState(userLocale); - return ( - - - - - - - - - ); -}; - +const Root = () => ( + + + + + + + + +); ReactDOM.render(, document.getElementById("root")); From 8b8f395124aff1bf866da5555f2ec9466960f6f4 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Reina Date: Thu, 11 May 2023 22:49:59 +0200 Subject: [PATCH 25/25] Add i18n to navlinks and footer --- packages/react-app/src/components/Header.jsx | 9 ++++--- .../react-app/src/components/SiteFooter.jsx | 25 +++++++++++++------ packages/react-app/src/lang/en.json | 6 +++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/packages/react-app/src/components/Header.jsx b/packages/react-app/src/components/Header.jsx index 98db63fd..bdb8e255 100644 --- a/packages/react-app/src/components/Header.jsx +++ b/packages/react-app/src/components/Header.jsx @@ -1,6 +1,7 @@ import React from "react"; import { NavLink, useLocation } from "react-router-dom"; import { chakra, useColorModeValue, Box, Flex, HStack, Spacer } from "@chakra-ui/react"; +import { FormattedMessage } from "react-intl"; import { Account } from "./index"; import { USER_ROLES } from "../helpers/constants"; import { ENVIRONMENT } from "../constants"; @@ -83,7 +84,7 @@ export default function Header({ color: primaryColorString, }} > - Portfolio + )} @@ -98,7 +99,7 @@ export default function Header({ color: primaryColorString, }} > - Builders + @@ -113,7 +114,7 @@ export default function Header({ color: primaryColorString, }} > - Review Submissions + @@ -124,7 +125,7 @@ export default function Header({ color: primaryColorString, }} > - Activity + diff --git a/packages/react-app/src/components/SiteFooter.jsx b/packages/react-app/src/components/SiteFooter.jsx index 4dcebdae..a33ca11c 100644 --- a/packages/react-app/src/components/SiteFooter.jsx +++ b/packages/react-app/src/components/SiteFooter.jsx @@ -1,6 +1,7 @@ import React from "react"; import { Box, HStack, Link } from "@chakra-ui/react"; import { GithubFilled, HeartFilled } from "@ant-design/icons"; +import { FormattedMessage } from "react-intl"; import useCustomColorModes from "../hooks/useCustomColorModes"; const SiteFooter = () => { @@ -12,17 +13,27 @@ const SiteFooter = () => { {" "} - Fork me +

|

- - Built with at - - - BuidlGuidl - + + + + ), + Link: chunks => ( + + {chunks} + + ), + }} + /> diff --git a/packages/react-app/src/lang/en.json b/packages/react-app/src/lang/en.json index bce9234c..bc63d4f7 100644 --- a/packages/react-app/src/lang/en.json +++ b/packages/react-app/src/lang/en.json @@ -61,6 +61,8 @@ "error.access-error": "Access error", "error.server-overloaded": "Sorry, the server is overloaded. πŸ§―πŸš’πŸ”₯", "error.signature-from-wallet": "Couldn't get a signature from the Wallet", + "footer.built-with-love-at-buidlguidl": "Built with {heartIcon} at BuidlGuidl", + "footer.fork-me": "Fork me", "general.Submit": "Submit", "general.accepted": "Accepted", "general.code": "Code", @@ -74,6 +76,10 @@ "general.role": "Role", "general.submitted": "Submitted", "general.update": "Update", + "header.activity": "Activity", + "header.builders": "Builders", + "header.portfolio": "Portfolio", + "header.review-submissions": "Review Submissions", "index.learn-ethereum": "Learn how to build on Ethereum; the superpowers and the gotchas.", "index.step-1": "Watch this quick video as an Intro to Ethereum Development.", "index.step-2.1": "Then use πŸ— Scaffold-ETH to copy/paste each Solidity concept and tinker:",