From 0297ae24f0f7942edcf182deb64c3065ecde1527 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 19 Nov 2024 12:53:58 +0100 Subject: [PATCH 01/51] add deps --- packages/frontend/package.json | 6 ++++- yarn.lock | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/packages/frontend/package.json b/packages/frontend/package.json index ddf29229..44115613 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -42,6 +42,8 @@ "es6-error": "4.1.1", "firebase": "10.0.0", "html2canvas": "1.4.1", + "i18next": "^23.16.5", + "i18next-browser-languagedetector": "^8.0.0", "ionicons": "7.3.0", "md5": "2.3.0", "moment": "2.30.1", @@ -51,6 +53,7 @@ "react-dom": "18.2.0", "react-ga4": "2.1.0", "react-hot-toast": "2.4.1", + "react-i18next": "^15.1.1", "react-laag": "2.0.5", "react-markdown": "8.0.7", "react-microsoft-clarity": "1.2.0", @@ -62,6 +65,7 @@ "react-use-audio-player": "AlphadayHQ/useAudioPlayer", "redux-persist": "6.0.0", "remark-breaks": "3.0.3", + "sharp": "0.32.6", "unist-util-visit": "5.0.0", "uuid": "9.0.0", "viem": "1.2.5", @@ -98,4 +102,4 @@ "vite-plugin-pwa": "0.19.2", "vite-plugin-svgr": "3.2.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 06c128f1..6dac9780 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1357,6 +1357,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.25.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" @@ -10128,6 +10135,13 @@ howler@^2.2.1: resolved "https://registry.yarnpkg.com/howler/-/howler-2.2.4.tgz#bd3df4a4f68a0118a51e4bd84a2bfc2e93e6e5a1" integrity sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w== +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + html2canvas@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/html2canvas/-/html2canvas-1.4.1.tgz#7cef1888311b5011d507794a066041b14669a543" @@ -10239,6 +10253,20 @@ husky@8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +i18next-browser-languagedetector@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz#b6fdd9b43af67c47f2c26c9ba27710a1eaf31e2f" + integrity sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw== + dependencies: + "@babel/runtime" "^7.23.2" + +i18next@^23.16.5: + version "23.16.5" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.5.tgz#53d48ae9f985fd73fc1fcb96e6c7d90ababf0831" + integrity sha512-KTlhE3EP9x6pPTAW7dy0WKIhoCpfOGhRQlO+jttQLgzVaoOjWwBWramu7Pp0i+8wDNduuzXfe3kkVbzrKyrbTA== + dependencies: + "@babel/runtime" "^7.23.2" + ico-endec@*: version "0.1.6" resolved "https://registry.yarnpkg.com/ico-endec/-/ico-endec-0.1.6.tgz#9b320cc3ed0a0c779f54e998a8db49002abd7c6e" @@ -13459,6 +13487,14 @@ react-hot-toast@2.4.1: dependencies: goober "^2.1.10" +react-i18next@^15.1.1: + version "15.1.1" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.1.tgz#30bc76b39ded6ee37f1457677e46e6d6f11d9f64" + integrity sha512-R/Vg9wIli2P3FfeI8o1eNJUJue5LWpFsQePCHdQDmX0Co3zkr6kdT8gAseb/yGeWbNz1Txc4bKDQuZYsC0kQfw== + dependencies: + "@babel/runtime" "^7.25.0" + html-parse-stringify "^3.0.1" + "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" @@ -16329,6 +16365,11 @@ vm-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + wagmi@1.3.9: version "1.3.9" resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-1.3.9.tgz#c21b0bc045e9888bd283accedcd9ef9606f04a70" From 4fdc7bf745c8f0385281729b4258229b3f89ce99 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 19 Nov 2024 14:31:53 +0100 Subject: [PATCH 02/51] hide overflow of screen --- packages/frontend/src/layout/MainLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/layout/MainLayout.tsx b/packages/frontend/src/layout/MainLayout.tsx index 2a960fe6..69134c51 100644 --- a/packages/frontend/src/layout/MainLayout.tsx +++ b/packages/frontend/src/layout/MainLayout.tsx @@ -25,7 +25,7 @@ const MainLayout: React.FC = ({ }) => { const [isBoardsLibOpen, setIsBoardsLibOpen] = useState(false); return ( -
+
Date: Tue, 19 Nov 2024 20:12:50 +0100 Subject: [PATCH 03/51] set up japanese translation --- packages/frontend/package.json | 6 +- .../board-library/BoardsLibrary.tsx | 21 ++- .../widget-library/WidgetLibrary.tsx | 15 +- .../ProfileDropdownWrapper.tsx | 18 +- .../search/HeaderSearchContainer.tsx | 4 +- packages/frontend/src/i18n.ts | 36 ++++ packages/frontend/src/layout/LayoutHeader.tsx | 13 +- packages/frontend/src/locales/translation.ts | 172 ++++++++++++++++++ packages/frontend/src/main.tsx | 1 + 9 files changed, 261 insertions(+), 25 deletions(-) create mode 100644 packages/frontend/src/i18n.ts create mode 100644 packages/frontend/src/locales/translation.ts diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 44115613..46860ccf 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -42,8 +42,8 @@ "es6-error": "4.1.1", "firebase": "10.0.0", "html2canvas": "1.4.1", - "i18next": "^23.16.5", - "i18next-browser-languagedetector": "^8.0.0", + "i18next": "23.16.5", + "i18next-browser-languagedetector": "8.0.0", "ionicons": "7.3.0", "md5": "2.3.0", "moment": "2.30.1", @@ -53,7 +53,7 @@ "react-dom": "18.2.0", "react-ga4": "2.1.0", "react-hot-toast": "2.4.1", - "react-i18next": "^15.1.1", + "react-i18next": "15.1.1", "react-laag": "2.0.5", "react-markdown": "8.0.7", "react-microsoft-clarity": "1.2.0", diff --git a/packages/frontend/src/components/board-library/BoardsLibrary.tsx b/packages/frontend/src/components/board-library/BoardsLibrary.tsx index 7728de88..099658cf 100644 --- a/packages/frontend/src/components/board-library/BoardsLibrary.tsx +++ b/packages/frontend/src/components/board-library/BoardsLibrary.tsx @@ -7,6 +7,7 @@ import { TabsBar, twMerge, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { EItemsSortBy, TRemoteUserViewPreview, @@ -147,6 +148,7 @@ const BoardsLibrary: FC = ({ subscribedViews, onEditView, }) => { + const { t } = useTranslation(); const customBoards = subscribedViews ?.filter((board) => !board.is_system_view) .sort((a, b) => a.sort_order - b.sort_order); @@ -212,10 +214,11 @@ const BoardsLibrary: FC = ({ >
-
Boards Library
+
+ {t("navigation.boards_library.title")} +
- Switch between boards to optimize your workflow, and pin - the ones you use most often. + {t("navigation.boards_library.description")}
= ({
- Custom Boards + {t( + "navigation.boards_library.custom_boards_title" + )} {isAuthenticated - ? "Create an empty board and add widgets" - : "Connect and verify your wallet to create new boards and see your custom boards"} + ? t( + "navigation.boards_library.custom_boards_description_with_auth" + ) + : t( + "navigation.boards_library.custom_boards_description" + )} = ({ isLoading, handlePaginate, }) => { + const { t } = useTranslation(); const handleFilterChange = (e: ChangeEvent) => { onFilter(e.target.value); }; @@ -168,7 +170,7 @@ const WidgetLibrary: FC = ({
- Widgets Library + {t("navigation.widgets_library.title")}
@@ -176,7 +178,9 @@ const WidgetLibrary: FC = ({ onChange={handleFilterChange} id="widgetlib-search" name="widgetlib-search" - placeholder="Quick Search..." + placeholder={t( + "navigation.widgets_library.searchBarPlaceholder" + )} height="28px" className="outline-none border-none focus:outline-none focus:border-none bg-backgroundVariant200" /> @@ -207,7 +211,7 @@ const WidgetLibrary: FC = ({ onClick={() => handleSelectCategory(undefined)} > - All Widgets + {t("navigation.widgets_library.allWidgets")}
{categories.map((cat) => { const icon = cat.slug.split( @@ -239,7 +243,10 @@ const WidgetLibrary: FC = ({
- {widgets.length} Widgets + + {widgets.length}{" "} + {t("navigation.widgets")} +
= ({ setTutFocusElemRef, profile, }) => { + const { t } = useTranslation(); const [toggleTutorialState, setToggleTutorialState] = useState(false); const handleToggle = () => { @@ -54,13 +56,13 @@ const ProfileDropdownWrapper: React.FC = ({ const walletMenuOption = isAuthenticated ? { handler: onSignOut, - menuTitle: "Sign Out", - title: "Sign Out", + menuTitle: t("navigation.menu.sign_out"), + title: t("navigation.menu.sign_out"), dataTestId: "profile-dropdown-sign-out", } : { handler: onSignUpSignIn, - menuTitle: "Sign Up / Sign In", + menuTitle: `${t("navigation.menu.sign_up")} / ${t("navigation.menu.sign_in")}`, title: globalMessages.portfolio.signUp, dataTestId: "profile-dropdown-sign-up", }; @@ -119,7 +121,7 @@ const ProfileDropdownWrapper: React.FC = ({ - Tutorial{" "} + {t("navigation.menu.tutorial")}{" "} = ({ - About Us + {t("navigation.menu.about_us")} {CONFIG.APP.VERSION && CONFIG.APP.COMMIT && (
- Version: {CONFIG.APP.VERSION} + {t("navigation.menu.version")}:{" "} + {CONFIG.APP.VERSION}
- Commit: {CONFIG.APP.COMMIT} + {t("navigation.menu.commit")}:{" "} + {CONFIG.APP.COMMIT}
)} diff --git a/packages/frontend/src/containers/search/HeaderSearchContainer.tsx b/packages/frontend/src/containers/search/HeaderSearchContainer.tsx index e7e51165..a20714db 100644 --- a/packages/frontend/src/containers/search/HeaderSearchContainer.tsx +++ b/packages/frontend/src/containers/search/HeaderSearchContainer.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { SearchBar } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { ActionMeta } from "react-select"; import { useGlobalSearch, useActivityLogger } from "src/api/hooks"; import { useKeywordSearch } from "src/api/hooks/useKeywordSearch"; @@ -24,6 +25,7 @@ type TOption = { type TOptions = ReadonlyArray; const HeaderSearchContainer: FC = () => { + const { t: translate } = useTranslation(); const { keywordSearchList, setKeywordSearchList, @@ -185,7 +187,7 @@ const HeaderSearchContainer: FC = () => { onInputChange={debounce((e: string) => { setSearchState(e); }, 500)} - placeholder="Search for assets, projects, events, etc." + placeholder={translate("navigation.searchBarPlaceholder")} initialSearchValues={ keywordSearchList === undefined ? [] diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts new file mode 100644 index 00000000..bbf9a800 --- /dev/null +++ b/packages/frontend/src/i18n.ts @@ -0,0 +1,36 @@ +import i18n from "i18next"; +import LanguageDetector from "i18next-browser-languagedetector"; +import { initReactI18next } from "react-i18next"; +import { Logger } from "./api/utils/logging"; +import { translationEN, translationJA } from "./locales/translation"; + +const resources = { + en: { + translation: translationEN, + }, + ja: { + translation: translationJA, + }, +}; + +i18n.use(LanguageDetector) + .use(initReactI18next) + .init({ + debug: true, + resources, + fallbackLng: "en", + detection: { + order: ["navigator", "htmlTag", "path", "subdomain"], + }, + interpolation: { + escapeValue: false, + }, + }) + .then(() => { + Logger.info("i18n.ts: i18n initialized successfully"); + }) + .catch((e) => { + Logger.error("i18n.ts: could not initialize i18n", e); + }); + +export default i18n; diff --git a/packages/frontend/src/layout/LayoutHeader.tsx b/packages/frontend/src/layout/LayoutHeader.tsx index aa7d8fc8..0d9d6337 100644 --- a/packages/frontend/src/layout/LayoutHeader.tsx +++ b/packages/frontend/src/layout/LayoutHeader.tsx @@ -8,6 +8,7 @@ import { HeaderNavElement, HeaderNavbar, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { useWindowSize } from "src/api/hooks"; import { ReactComponent as Close2 } from "src/assets/icons/close2.svg"; import { ReactComponent as MenuMobile } from "src/assets/icons/menuMobile.svg"; @@ -34,6 +35,8 @@ const LayoutHeader: FC = ({ isBoardsLibOpen, setIsBoardsLibOpen, }) => { + const { t } = useTranslation(); + const [mobileOpen, setMobileOpen] = useState(false); const headerRef = useRef(null); @@ -78,9 +81,11 @@ const LayoutHeader: FC = ({ open={false} uppercase={false} onClick={toggleBoardsLib} - title="Open Boards Library" + title={t( + "navigation.openBoardsLibrary" + )} > - Boards + {t("navigation.boards")} = ({ onClick={toggleWidgetLib} title="Open Widget Library" > - Widgets + {t("navigation.widgets")} @@ -158,7 +163,7 @@ const LayoutHeader: FC = ({

- Boards + {t("navigation.boards")}

import("./MobileApp")); const App = lazyRetry(() => import("./App")); From 28e3316110ab7be58ed2dce8368dc53487a093ca Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 20 Nov 2024 07:27:41 +0100 Subject: [PATCH 04/51] make all navigation text translateable --- .../frontend/src/api/utils/sortOptions.ts | 17 +++---- .../src/api/utils/translationUtils.ts | 45 +++++++++++++++++++ .../board-library/BoardsLibrary.tsx | 19 ++++++-- .../widget-library/WidgetLibrary.tsx | 19 ++++++-- .../board-library/BoardsLibraryContainer.tsx | 4 +- .../widgets-library/WidgetsLibContainer.tsx | 4 +- packages/frontend/src/locales/translation.ts | 38 ++++++++++++++++ .../ui-kit/src/components/dropdown/SortBy.tsx | 11 ++--- 8 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 packages/frontend/src/api/utils/translationUtils.ts diff --git a/packages/frontend/src/api/utils/sortOptions.ts b/packages/frontend/src/api/utils/sortOptions.ts index 5c39e812..3ccc6cb5 100644 --- a/packages/frontend/src/api/utils/sortOptions.ts +++ b/packages/frontend/src/api/utils/sortOptions.ts @@ -1,29 +1,26 @@ import { EItemsSortBy } from "../services"; +import { translateLabels } from "./translationUtils"; -const SORT_OPTIONS: { +export const SORT_OPTIONS: { label: string; value: EItemsSortBy; }[] = [ { - label: "(A-Z)", value: EItemsSortBy.Name, + label: translateLabels("(A-Z)"), }, { - label: "Popular", value: EItemsSortBy.Popular, + label: translateLabels("Popular"), }, { - label: "New", value: EItemsSortBy.New, + label: translateLabels("New"), }, ]; -export const getSortOptionsArray = (): string[] => { - return SORT_OPTIONS.map((option) => option.label); -}; - -export const getSortOptionValue = (label: string): EItemsSortBy | null => { - const option = SORT_OPTIONS.find((op) => op.label === label); +export const getSortOptionValue = (value: string): EItemsSortBy | null => { + const option = SORT_OPTIONS.find((op) => op.value === value); if (!option) { return null; } diff --git a/packages/frontend/src/api/utils/translationUtils.ts b/packages/frontend/src/api/utils/translationUtils.ts new file mode 100644 index 00000000..a8564631 --- /dev/null +++ b/packages/frontend/src/api/utils/translationUtils.ts @@ -0,0 +1,45 @@ +import i18next from "i18next"; +import { Logger } from "./logging"; + +export enum ETranslationValues { + name = "(A-Z)", + popular = "Popular", + new = "New", + feed = "Feed", + trending = "Trending", + readLater = "ReadLater", + bookmarks = "Bookmarks", + timeRange = "timeRange", + media = "Media", + all = "All", + general = "General", + nfts = "NFTs", + dao = "DAO", + layer2 = "Layer2", + defi = "DeFi", + trading = "Trading", +} + +// const allowedKeys = ["Popular", "(A-Z)", "New"] as const; +// export type TTranslationKeys = (typeof allowedKeys)[number]; +export type TTranslationValues = `${ETranslationValues}`; +const allowedValues: TTranslationValues[] = Object.values(ETranslationValues); +const allowedKeys = Object.keys(ETranslationValues); + +export const translateLabels = ( + text: TTranslationValues, + { isKey }: { isKey: boolean } = { isKey: false } +) => { + if (isKey && allowedKeys.includes(text)) { + return i18next.t(`navigation.general.${text}`); + } + if (!allowedValues.includes(text)) { + Logger.error( + `translationUtils::translateLabels:: Translation value ${text} is not allowed` + ); + return text; + } + const key = allowedKeys[allowedValues.indexOf(text)]; + + return i18next.t(`navigation.general.${key}`); +}; diff --git a/packages/frontend/src/components/board-library/BoardsLibrary.tsx b/packages/frontend/src/components/board-library/BoardsLibrary.tsx index 099658cf..8a6b76d9 100644 --- a/packages/frontend/src/components/board-library/BoardsLibrary.tsx +++ b/packages/frontend/src/components/board-library/BoardsLibrary.tsx @@ -16,9 +16,14 @@ import { import { TUserViewPreview, TViewMeta } from "src/api/types"; import { validateEthAddr } from "src/api/utils/accountUtils"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; -import { getSortOptionsArray } from "src/api/utils/sortOptions"; +import { SORT_OPTIONS } from "src/api/utils/sortOptions"; import { truncateWithEllipsis } from "src/api/utils/textUtils"; import { EToastRole, toast } from "src/api/utils/toastUtils"; +import { + ETranslationValues, + translateLabels, + TTranslationValues, +} from "src/api/utils/translationUtils"; import { ReactComponent as CloseSVG } from "src/assets/icons/close2.svg"; import { ReactComponent as EmptySVG } from "src/assets/icons/empty.svg"; import { ReactComponent as PlusSVG } from "src/assets/icons/plus.svg"; @@ -203,6 +208,13 @@ const BoardsLibrary: FC = ({ const sortByKey = Object.keys(EItemsSortBy)[Object.values(EItemsSortBy).indexOf(sortBy)]; + const selectedSortValue = + Object.keys(ETranslationValues).indexOf(sortByKey.toLowerCase()) !== -1 + ? translateLabels(sortByKey.toLowerCase() as TTranslationValues, { + isKey: true, + }) + : sortByKey; + return (
= ({
diff --git a/packages/frontend/src/components/widget-library/WidgetLibrary.tsx b/packages/frontend/src/components/widget-library/WidgetLibrary.tsx index 1ddcce11..a65a7610 100644 --- a/packages/frontend/src/components/widget-library/WidgetLibrary.tsx +++ b/packages/frontend/src/components/widget-library/WidgetLibrary.tsx @@ -12,7 +12,12 @@ import { useTranslation } from "react-i18next"; import { EItemsSortBy, TRemoteWidgetCategory } from "src/api/services"; import { TWidget, TWidgetMini } from "src/api/types"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; -import { getSortOptionsArray } from "src/api/utils/sortOptions"; +import { SORT_OPTIONS } from "src/api/utils/sortOptions"; +import { + ETranslationValues, + translateLabels, + TTranslationValues, +} from "src/api/utils/translationUtils"; import { ReactComponent as ChartSVG } from "src/assets/icons/chart.svg"; import { ReactComponent as CloseSVG } from "src/assets/icons/close3.svg"; import { ReactComponent as DefiSVG } from "src/assets/icons/defi.svg"; @@ -99,6 +104,13 @@ const WidgetLibrary: FC = ({ const sortByKey = Object.keys(EItemsSortBy)[Object.values(EItemsSortBy).indexOf(sortBy)]; + const selectedSortValue = + Object.keys(ETranslationValues).indexOf(sortByKey.toLowerCase()) !== -1 + ? translateLabels(sortByKey.toLowerCase() as TTranslationValues, { + isKey: true, + }) + : sortByKey; + const renderModulePreview = useCallback( (widget: TWidgetMini) => { const widgetCount = @@ -249,9 +261,10 @@ const WidgetLibrary: FC = ({
diff --git a/packages/frontend/src/containers/board-library/BoardsLibraryContainer.tsx b/packages/frontend/src/containers/board-library/BoardsLibraryContainer.tsx index 1bd4d83b..511e7c0a 100644 --- a/packages/frontend/src/containers/board-library/BoardsLibraryContainer.tsx +++ b/packages/frontend/src/containers/board-library/BoardsLibraryContainer.tsx @@ -226,8 +226,8 @@ const BoardsLibraryContainer: FC = ({ ] ); - const handleSortBy = (sortLabel: string): void => { - const sort = getSortOptionValue(sortLabel); + const handleSortBy = (sortvalue: string): void => { + const sort = getSortOptionValue(sortvalue); if (isFetching || sort === null || sortBy === sort) return; if (allViews.length > 0) setAllViews([]); if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); diff --git a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx index 188f7b70..93faa19b 100644 --- a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx +++ b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx @@ -185,8 +185,8 @@ const WidgetsLibContainer: FC = ({ layoutState }) => { setFilter(normalizedValue); }, 300); - const handleSortBy = (sortLabel: string): void => { - const sort = getSortOptionValue(sortLabel); + const handleSortBy = (sortValue: string): void => { + const sort = getSortOptionValue(sortValue); if (isFetching || sort === null || sortBy === sort) return; if (widgets.length > 0) setWidgets([]); if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 38c2c08e..dcf80382 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -4,6 +4,7 @@ export const translationEN = { boards: "Boards", openBoardsLibrary: "Open Boards Library", widgets: "Widgets", + sortBy: "Sort by", menu: { sign_in: "Sign In", sign_out: "Sign Out", @@ -28,6 +29,24 @@ export const translationEN = { searchBarPlaceholder: "Search for widgets", allWidgets: "All Widgets", }, + general: { + all: "All", + general: "General", + nfts: "NFTs", + daos: "DAOs", + layer2: "Layer 2", + defi: "DeFi", + trading: "Trading", + popular: "Popular", + name: "(A-Z)", + new: "New", + feed: "Feed", + trending: "Trending", + readLater: "Read Later", + bookmarks: "Bookmarks", + timeRange: "Time Range", + media: "Media", + }, }, categories: { @@ -91,6 +110,7 @@ export const translationJA: typeof translationEN = { boards: "ボード", openBoardsLibrary: "ボードライブラリを開く", widgets: "ウィジェット", + sortBy: "並び替え", menu: { sign_in: "サインイン", sign_out: "サインアウト", @@ -115,6 +135,24 @@ export const translationJA: typeof translationEN = { searchBarPlaceholder: "ウィジェットを検索", allWidgets: "すべてのウィジェット", }, + general: { + all: "すべて", + general: "一般", + nfts: "NFT", + daos: "DAO", + layer2: "レイヤー2", + defi: "DeFi", + trading: "取引", + popular: "人気", + name: "名前", + new: "新着", + feed: "フィード", + trending: "トレンド", + readLater: "後で読む", + bookmarks: "ブックマーク", + timeRange: "時間帯", + media: "メディア", + }, }, categories: { all: "すべて", diff --git a/packages/ui-kit/src/components/dropdown/SortBy.tsx b/packages/ui-kit/src/components/dropdown/SortBy.tsx index 13c3e9ba..99b6bb8d 100644 --- a/packages/ui-kit/src/components/dropdown/SortBy.tsx +++ b/packages/ui-kit/src/components/dropdown/SortBy.tsx @@ -6,16 +6,17 @@ import { twMerge } from "tailwind-merge"; interface ISortBy { selected: string; onSortBy: (sort: string) => void; - options: string[]; + options: { label: string; value: string }[]; + label: string; } -export const SortBy: FC = ({ selected, onSortBy, options }) => { +export const SortBy: FC = ({ selected, onSortBy, options, label }) => { return (
- Sort by: + {label}: {selected} @@ -41,11 +42,11 @@ export const SortBy: FC = ({ selected, onSortBy, options }) => { "border-b-0 rounded-b-md", index === 1 && "rounded-t-md" )} - onClick={() => onSortBy(option)} + onClick={() => onSortBy(option.value)} tabIndex={0} role="button" > - {option} + {option.label} ))} From 84b3d7cfb48586e4995cc1565055b0cfbe6e64b6 Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 20 Nov 2024 09:38:12 +0100 Subject: [PATCH 05/51] news and portfolio translation --- .../src/components/news/NewsModule.tsx | 7 +- .../src/components/portfolio/AddressInput.tsx | 8 +- .../components/portfolio/AddressTabSelect.tsx | 6 +- .../components/portfolio/PortfolioModule.tsx | 9 +- .../components/portfolio/PortfolioStats.tsx | 15 +- .../src/components/portfolio/TopBar.tsx | 10 +- .../src/containers/base/BaseContainerMenu.tsx | 17 +- .../WalletConnectionDialogContainer.tsx | 35 ++-- packages/frontend/src/locales/translation.ts | 174 +++++++++++------- packages/ui-kit/src/utils/dateUtils.ts | 2 +- 10 files changed, 170 insertions(+), 113 deletions(-) diff --git a/packages/frontend/src/components/news/NewsModule.tsx b/packages/frontend/src/components/news/NewsModule.tsx index e15fc96d..20e753cc 100644 --- a/packages/frontend/src/components/news/NewsModule.tsx +++ b/packages/frontend/src/components/news/NewsModule.tsx @@ -2,6 +2,7 @@ import { FC, memo } from "react"; import { ModuleLoader, TabsBar } from "@alphaday/ui-kit"; import { TNewsItem, EItemFeedPreference } from "src/api/types"; import { Logger } from "src/api/utils/logging"; +import { translateLabels } from "src/api/utils/translationUtils"; import NewsItemList from "./NewsItemList"; interface INews { @@ -21,15 +22,15 @@ interface INews { */ const NEWS_NAV_ITEMS = [ { - label: "Feed", + label: translateLabels("Feed"), value: EItemFeedPreference.Last, }, { - label: "Trending", + label: translateLabels("Trending"), value: EItemFeedPreference.Trending, }, { - label: "Read Later", + label: translateLabels("ReadLater"), value: EItemFeedPreference.Bookmark, auth: true, }, diff --git a/packages/frontend/src/components/portfolio/AddressInput.tsx b/packages/frontend/src/components/portfolio/AddressInput.tsx index 1e55c4ee..bfc88ff8 100644 --- a/packages/frontend/src/components/portfolio/AddressInput.tsx +++ b/packages/frontend/src/components/portfolio/AddressInput.tsx @@ -1,5 +1,6 @@ import { FC, useState } from "react"; import { Dialog, Input } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { useKeyPress } from "src/api/hooks"; interface IAddressInput { @@ -17,14 +18,15 @@ const AddressInput: FC = ({ onClose, disabled, }) => { + const { t } = useTranslation(); const [value, setValue] = useState(""); return ( { onAddAddress(value); @@ -44,7 +46,7 @@ const AddressInput: FC = ({ }} id="wallet-input" name="walletInput" - placeholder="Enter an Ethereum or ENS address" + placeholder={t("portfolio.inputPlaceholder")} />
diff --git a/packages/frontend/src/components/portfolio/AddressTabSelect.tsx b/packages/frontend/src/components/portfolio/AddressTabSelect.tsx index 6c2afce3..fa48fde8 100644 --- a/packages/frontend/src/components/portfolio/AddressTabSelect.tsx +++ b/packages/frontend/src/components/portfolio/AddressTabSelect.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { TabsBar } from "@alphaday/ui-kit"; +import i18next from "i18next"; import { TCryptoAccount } from "src/api/types"; import { truncateWithEllipsis } from "src/api/utils/textUtils"; import { TPortfolioTabAccount } from "./types"; @@ -18,7 +19,10 @@ interface IAddressTabSelect { onSelectAddress: (address: string) => void; } -const DEFAULT_ACCOUNT_TAB = { label: "All wallets", value: "all-wallets" }; +const DEFAULT_ACCOUNT_TAB = { + label: i18next.t("portfolio.allWallets"), + value: "all-wallets", +}; const AddressTabSelect: FC = ({ accounts, diff --git a/packages/frontend/src/components/portfolio/PortfolioModule.tsx b/packages/frontend/src/components/portfolio/PortfolioModule.tsx index 2e88f947..579622e7 100644 --- a/packages/frontend/src/components/portfolio/PortfolioModule.tsx +++ b/packages/frontend/src/components/portfolio/PortfolioModule.tsx @@ -1,5 +1,6 @@ import { FC, useState, useMemo } from "react"; import { Button, ModuleLoader } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import useHeaderScroll from "src/api/hooks/useHeaderScroll"; import { TCryptoAccount } from "src/api/types"; import { validateHexOrEnsAddr } from "src/api/utils/accountUtils"; @@ -76,6 +77,8 @@ const Portfolio: FC = ({ const [showEnterAddress, setShowEnterAddress] = useState(false); const [disableAddAddressInput, setDisableAddAddressInput] = useState(true); + const { t } = useTranslation(); + const portfolioData = useMemo( () => !showAllAssets @@ -117,7 +120,7 @@ const Portfolio: FC = ({ .verifyWallet } > - Verify Wallet + {t("buttons.verifyWallet")}
)} @@ -177,14 +180,14 @@ const Portfolio: FC = ({ title="Connect your Wallet" onClick={onConnectWallet} > - Connect Wallet + {t("buttons.connect_wallet")}
diff --git a/packages/frontend/src/components/portfolio/PortfolioStats.tsx b/packages/frontend/src/components/portfolio/PortfolioStats.tsx index 96a17c97..e886b690 100644 --- a/packages/frontend/src/components/portfolio/PortfolioStats.tsx +++ b/packages/frontend/src/components/portfolio/PortfolioStats.tsx @@ -6,6 +6,7 @@ import { themeColors, twMerge, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { useWidgetSize } from "src/api/hooks"; import { formatNumber, ENumberStyle } from "src/api/utils/format"; import { makeRepeated } from "src/api/utils/itemUtils"; @@ -57,6 +58,8 @@ const PortfolioStats: FC = ({ const LegendWrapRef = useRef(null); const chartRef = useRef(null); + const { t } = useTranslation(); + const widgetSize = useWidgetSize([450, 330]); const assets = useMemo( @@ -194,10 +197,10 @@ const PortfolioStats: FC = ({ ) : ( <>
-
+

- Total Balance{" "} + {t("portfolio.totalBalance")}{" "} = ({

- Asset + {t("portfolio.asset")}

- Balance + {t("portfolio.balance")}

- Price + {t("portfolio.price")}

- Value + {t("portfolio.value")}

diff --git a/packages/frontend/src/components/portfolio/TopBar.tsx b/packages/frontend/src/components/portfolio/TopBar.tsx index a864de81..df91ca35 100644 --- a/packages/frontend/src/components/portfolio/TopBar.tsx +++ b/packages/frontend/src/components/portfolio/TopBar.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { Switch, TabButton } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { ReactComponent as PlusSVG } from "src/assets/icons/plus.svg"; import { EPortfolioType } from "./types"; @@ -22,10 +23,11 @@ const TopBar: FC = ({ selectedIsAuthWallet, isWalletConnected, }) => { + const { t } = useTranslation(); return (
@@ -42,7 +44,7 @@ const TopBar: FC = ({ marginRight: "5px", }} />{" "} - Add New Wallet + {t("buttons.add_wallet")} {(selectedIsAuthWallet || !isWalletConnected) && ( = ({ className="portfolio-addWallet border border-borderLine text-primary" > {isWalletConnected - ? "Disconnect wallet" - : "Connect wallet"} + ? t("buttons.disconnect_wallet") + : t("buttons.connect_wallet")} )} diff --git a/packages/frontend/src/containers/base/BaseContainerMenu.tsx b/packages/frontend/src/containers/base/BaseContainerMenu.tsx index 527f802c..b8947901 100644 --- a/packages/frontend/src/containers/base/BaseContainerMenu.tsx +++ b/packages/frontend/src/containers/base/BaseContainerMenu.tsx @@ -1,5 +1,6 @@ import { FC, useMemo, useState } from "react"; import { themeColors, twMerge, useLayer } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { ReactComponent as CameraSVG } from "src/assets/icons/camera.svg"; import { ReactComponent as CloseSVG } from "src/assets/icons/close.svg"; import { ReactComponent as InfoSVG } from "src/assets/icons/info.svg"; @@ -84,6 +85,8 @@ const BaseContainerMenu: FC = ({ onOutsideClick: () => setShowMenu(false), }); + const { t } = useTranslation(); + const styledLayerProps = useMemo( () => ({ ...layerProps, @@ -152,7 +155,9 @@ const BaseContainerMenu: FC = ({ className="icon" />
- {isWidgetOptions ? "Close Options" : "Options"} + {isWidgetOptions + ? t("navigation.close_options") + : t("widget.options")}
@@ -171,7 +176,7 @@ const BaseContainerMenu: FC = ({ className="icon" />
- Maximize + {t("widget.maximize")}
@@ -194,7 +199,9 @@ const BaseContainerMenu: FC = ({ )}
- {toggleExpand ? "Expand" : "Minimize"} + {toggleExpand + ? t("widget.expand") + : t("widget.minimize")}
@@ -210,7 +217,7 @@ const BaseContainerMenu: FC = ({ >
- Screenshot + {t("widget.screenshot")}
= ({ />
- Remove Widget + {t("widget.remove_widget")}
diff --git a/packages/frontend/src/containers/dialogs/WalletConnectionDialogContainer.tsx b/packages/frontend/src/containers/dialogs/WalletConnectionDialogContainer.tsx index 674affee..a5c209f8 100644 --- a/packages/frontend/src/containers/dialogs/WalletConnectionDialogContainer.tsx +++ b/packages/frontend/src/containers/dialogs/WalletConnectionDialogContainer.tsx @@ -1,5 +1,6 @@ import { FC, memo } from "react"; import { Dialog, ErrorModal } from "@alphaday/ui-kit"; +import i18next from "i18next"; import { useWallet, useAccount, @@ -24,6 +25,10 @@ type TPropsDict = Partial< > >; +const translate = (key: string) => { + return i18next.t(`portfolio.${key}`); +}; + const WalletConnectionDialogContainer: FC = memo(() => { const { authWallet, resetAuthState } = useAccount(); const { enabled: isWalletConnectFeatureAllowed } = useFeatureFlags( @@ -48,54 +53,52 @@ const WalletConnectionDialogContainer: FC = memo(() => { id: "wallet-connect", onClick: onConnect(EWalletConnectionMethod.WalletConnect), disabled: !isWalletConnectFeatureAllowed, - title: `Wallet Connect ${ - isWalletConnectFeatureAllowed ? "" : "(soon)" + title: `${translate("modals.title")} ${ + isWalletConnectFeatureAllowed ? "" : translate("modals.soon") }`, icon: WalletConnectSVG, }, { id: "metamask", onClick: onConnect(EWalletConnectionMethod.Metamask), - title: `Metamask`, + title: translate("modals.metamask"), icon: MetamaskSVG, }, ]; const dialogPropsDict: TPropsDict = { [WalletConnectionState.SelectingMethod]: { - title: "Choose a Wallet Provider", + title: translate("modals.selectingMethod.title"), onClose: resetWalletConnection, content: , }, [WalletConnectionState.Prompted]: { - title: "Verify Wallet", - saveButtonText: "Verify Wallet", + title: translate("modals.prompted.title"), + saveButtonText: translate("modals.prompted.saveButtonText"), onSave: verifyWallet, onClose: resetWalletVerification, buttonProps: { title: globalMessages.portfolio.verifyWallet, }, - content: - "Your wallet has been connected successfully. To save your customized boards please login to Alphaday by signing a text message.", + content: translate("modals.prompted.content"), }, }; + const errorPropsDict: TPropsDict = { [WalletConnectionState.ConnectionError]: { - title: "Wallet Connection Error", + title: translate("modals.connectionError.title"), onClose: resetWalletConnection, - content: - "An error ocurred trying to connect to your wallet provider. Please make sure your wallet is correctly setup.", + content: translate("modals.connectionError.content"), }, [WalletConnectionState.VerificationError]: { - title: "Wallet Verification Error", + title: translate("modals.verificationError.title"), onClose: resetWalletVerification, - content: - "Authentication failed. Is your wallet unlocked? Have you switched accounts?", + content: translate("modals.verificationError.content"), }, [WalletConnectionState.GenericError]: { - title: "Unexpected Error", + title: translate("modals.genericError.title"), onClose: resetAuthState, - content: "Oops! Something went wrong. Please try again later.", + content: translate("modals.genericError.content"), }, }; diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index dcf80382..715e277b 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -48,40 +48,14 @@ export const translationEN = { media: "Media", }, }, - - categories: { - all: "All", - general: "General", - nfts: "NFTs", - dao: "DAO", - layer2: "Layer 2", - defi: "DeFi", - trading: "Trading", - }, - platforms: { - aave: { - name: "AAVE", - description: - "Earn interest, borrow assets, and build applications.", - }, - ai: { - name: "AI", - description: "Top AI-themed projects", - }, - alchemix: { - name: "ALCHEMIX", - description: - "Alchemix Finance is a future-yield-backed synthetic asset protocol and community", - }, - alpha: { - name: "ALPHA", - description: "A bird's-eye view on everything happening in crypto.", - }, - aptos: { - name: "APTOS", - description: - "Aptos is a Layer-1 blockchain with a strong focus on scalability, security, and", - }, + widget: { + options: "Options", + close_options: "Close Options", + expand: "Expand", + maximize: "Maximize", + minimize: "Minimize", + screenshot: "Screenshot", + remove_widget: "Remove Widget", }, tabs: { news: "NEWS", @@ -93,9 +67,50 @@ export const translationEN = { }, buttons: { connect_wallet: "Connect Wallet", + verify_wallet: "Verify Wallet", + add_wallet: "Add New Wallet", + disconnect_wallet: "Disconnect_Wallet", enter_address: "Enter Address", - sort_by: "Sort by", - name: "Name", + save: "Save", + }, + portfolio: { + addAWallet: "Add a Wallet Address", + inputPlaceholder: "Enter an Ethereum or ENS address", + totalBalance: "Total Balance", + allWallets: "All Wallets", + asset: "Asset", + assets: "Assets", + nfts: "NFTs", + balance: "Balance", + price: "Price", + value: "Value", + modals: { + title: "Wallet Connect", + soon: "(soon)", + metamask: "Metamask", + selectingMethod: { + title: "Choose a Wallet Provider", + }, + prompted: { + title: "Verify Wallet", + content: + "Your wallet has been connected successfully. To save your customized boards, please login to Alphaday by signing a text message.", + }, + connectionError: { + title: "Wallet Connection Error", + content: + "An error occurred trying to connect to your wallet provider. Please make sure your wallet is correctly set up.", + }, + verificationError: { + title: "Wallet Verification Error", + content: + "Authentication failed. Is your wallet unlocked? Have you switched accounts?", + }, + genericError: { + title: "Unexpected Error", + content: "Oops! Something went wrong. Please try again later.", + }, + }, }, market: { title: "MARKET", @@ -154,39 +169,14 @@ export const translationJA: typeof translationEN = { media: "メディア", }, }, - categories: { - all: "すべて", - general: "一般", - nfts: "NFT", - dao: "DAO", - layer2: "レイヤー2", - defi: "DeFi", - trading: "取引", - }, - platforms: { - aave: { - name: "AAVE", - description: - "利息を稼ぎ、資産を借り入れ、アプリケーションを構築する。", - }, - ai: { - name: "AI", - description: "主要なAI関連プロジェクト", - }, - alchemix: { - name: "ALCHEMIX", - description: - "Alchemix Financeは、将来の収益に裏付けられた合成資産プロトコルとコミュニティです", - }, - alpha: { - name: "ALPHA", - description: "暗号資産の動向を俯瞰的に把握", - }, - aptos: { - name: "APTOS", - description: - "Aptosはスケーラビリティ、セキュリティを重視したレイヤー1ブロックチェーン", - }, + widget: { + options: "オプション", + close_options: "オプションを閉じる", + expand: "拡大", + maximize: "最大化", + minimize: "最小化", + screenshot: "スクリーンショット", + remove_widget: "ウィジェットを削除", }, tabs: { news: "ニュース", @@ -198,9 +188,51 @@ export const translationJA: typeof translationEN = { }, buttons: { connect_wallet: "ウォレットを接続", + verify_wallet: "ウォレットを確認", + add_wallet: "新しいウォレットを追加", + disconnect_wallet: "ウォレットを切断", enter_address: "アドレスを入力", - sort_by: "並び替え", - name: "名前", + save: "保存", + }, + portfolio: { + addAWallet: "ウォレットアドレスを追加", + inputPlaceholder: "EthereumまたはENSアドレスを入力してください", + totalBalance: "合計残高", + allWallets: "すべてのウォレット", + asset: "資産", + assets: "資産", + nfts: "NFTs", + balance: "残高", + price: "価格", + value: "価値", + modals: { + title: "ウォレットコネクト", + soon: "(近日中)", + metamask: "メタマスク", + selectingMethod: { + title: "ウォレットプロバイダーを選択", + }, + prompted: { + title: "ウォレットの確認", + content: + "ウォレットが正常に接続されました。カスタマイズしたボードを保存するには、テキストメッセージに署名してAlphadayにログインしてください。", + }, + connectionError: { + title: "ウォレット接続エラー", + content: + "ウォレットプロバイダーへの接続中にエラーが発生しました。ウォレットが正しく設定されていることを確認してください。", + }, + verificationError: { + title: "ウォレット確認エラー", + content: + "認証に失敗しました。ウォレットがロック解除されていますか?アカウントを切り替えましたか?", + }, + genericError: { + title: "予期しないエラー", + content: + "おっと!問題が発生しました。後でもう一度お試しください。", + }, + }, }, market: { title: "マーケット", diff --git a/packages/ui-kit/src/utils/dateUtils.ts b/packages/ui-kit/src/utils/dateUtils.ts index efdb4731..a1cb4165 100644 --- a/packages/ui-kit/src/utils/dateUtils.ts +++ b/packages/ui-kit/src/utils/dateUtils.ts @@ -6,7 +6,7 @@ import moment from "moment"; * @returns string */ export const computeDuration = (date: string | Date): string => { - moment.updateLocale("en", { + moment.updateLocale("ja", { relativeTime: { future: "in %s", // this shouldn't occur If it does there's an error. past: "%s ago", From 264825ac450cd125b38f3e719444b9d6705c937f Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 20 Nov 2024 09:51:03 +0100 Subject: [PATCH 06/51] add tutorials transcription --- .../src/components/tutorial/Tutorial.tsx | 6 ++- .../src/containers/tutorial/staticData.ts | 41 ++++++++----------- packages/frontend/src/locales/translation.ts | 41 +++++++++++++++++++ 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/components/tutorial/Tutorial.tsx b/packages/frontend/src/components/tutorial/Tutorial.tsx index caa23c43..1d5395de 100644 --- a/packages/frontend/src/components/tutorial/Tutorial.tsx +++ b/packages/frontend/src/components/tutorial/Tutorial.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { twMerge, Button, FadeIn } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { ETutorialIndicatorType, ETutorialTipId, @@ -19,6 +20,7 @@ const TutorialItem: FC = ({ closeTutorial, toggleNextTutorial, }) => { + const { t } = useTranslation(); return (
= ({ variant="secondary" className="border-none bg-primaryVariant200 p-[4px_12px_5px] h-[26px] fontGroup-normal" > - Not Now + {t("buttons.notNow")} )} diff --git a/packages/frontend/src/containers/tutorial/staticData.ts b/packages/frontend/src/containers/tutorial/staticData.ts index 2a633624..65f7a539 100644 --- a/packages/frontend/src/containers/tutorial/staticData.ts +++ b/packages/frontend/src/containers/tutorial/staticData.ts @@ -3,61 +3,52 @@ import { ETutorialIndicatorType, ETutorialTipId, } from "src/api/types"; +import i18n from "src/i18n"; + +const translate = (key: string) => { + return i18n.t(`tutorials.${key}`); +}; export const tutorials = [ { id: ETutorialTipId.SwitchView, - title: "Switch between boards", - text: "Optimize your workflow by using different boards curated with various widgets, or create your own.", + title: translate("switchView_title"), + text: translate("switchView_text"), align: ETutorialTipAlign.Center, indicatorType: ETutorialIndicatorType.Rect, }, { id: ETutorialTipId.WalletView, - title: "Create a Wallet board", - text: "Keep track of all information on alphaday regarding assets in your wallet.", + title: translate("walletView_title"), + text: translate("walletView_text"), align: ETutorialTipAlign.Left, indicatorType: ETutorialIndicatorType.Rect, }, { id: ETutorialTipId.UseSeachBar, - title: "Search Bar", - text: "Search for your favorite tokens, projects, or topics to filter the content inside the widgets.", + title: translate("useSeachBar_title"), + text: translate("useSeachBar_text"), align: ETutorialTipAlign.Center, indicatorType: ETutorialIndicatorType.Rect, }, { id: ETutorialTipId.ReArrangeWidget, - title: "Re-arrange widgets", - text: "Click and drag widgets by the top bar to change their position in the dashboard, or click once to minimize.", + title: translate("reArrangeWidget_title"), + text: translate("reArrangeWidget_text"), align: ETutorialTipAlign.Center, indicatorType: ETutorialIndicatorType.Rect, }, - // { - // id: ETutorialTipId.ResizeWidget, - // title: "Widget resizing", - // text: - // "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - // align: ETutorialTipAlign.Center,indicatorType: ETutorialIndicatorType.Ring, - // }, - // { - // id: ETutorialTipId.MaximizeWidget, - // title: "Maximize widgets", - // text: - // "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - // align: ETutorialTipAlign.Center,indicatorType: ETutorialIndicatorType.Ring, - // }, { id: ETutorialTipId.UseWidgetLib, - title: "Widgets Library", - text: "There are dozens of useful widgets available for you in the Widgets Library to pick and choose from.", + title: translate("useWidgetLib_title"), + text: translate("useWidgetLib_text"), align: ETutorialTipAlign.Right, indicatorType: ETutorialIndicatorType.Rect, }, { id: ETutorialTipId.ComeBack, title: undefined, - text: "Come back to the walk-through at any time in the user menu.", + text: translate("comeBack_text"), align: ETutorialTipAlign.Right, indicatorType: ETutorialIndicatorType.Ring, }, diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 715e277b..238ccc67 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -72,6 +72,8 @@ export const translationEN = { disconnect_wallet: "Disconnect_Wallet", enter_address: "Enter Address", save: "Save", + notNow: "Not Now", + next: "Next", }, portfolio: { addAWallet: "Add a Wallet Address", @@ -112,6 +114,25 @@ export const translationEN = { }, }, }, + tutorials: { + switchView_title: "Switch between boards", + switchView_text: + "Optimize your workflow by using different boards curated with various widgets, or create your own.", + walletView_title: "Create a Wallet board", + walletView_text: + "Keep track of all information on Alphaday regarding assets in your wallet.", + useSeachBar_title: "Search Bar", + useSeachBar_text: + "Search for your favorite tokens, projects, or topics to filter the content inside the widgets.", + reArrangeWidget_title: "Re-arrange widgets", + reArrangeWidget_text: + "Click and drag widgets by the top bar to change their position in the dashboard, or click once to minimize.", + useWidgetLib_title: "Widgets Library", + useWidgetLib_text: + "There are dozens of useful widgets available for you in the Widgets Library to pick and choose from.", + comeBack_text: + "Come back to the walk-through at any time in the user menu.", + }, market: { title: "MARKET", line: "Line", @@ -193,6 +214,8 @@ export const translationJA: typeof translationEN = { disconnect_wallet: "ウォレットを切断", enter_address: "アドレスを入力", save: "保存", + notNow: "今はしない", + next: "次へ", }, portfolio: { addAWallet: "ウォレットアドレスを追加", @@ -234,6 +257,24 @@ export const translationJA: typeof translationEN = { }, }, }, + tutorials: { + switchView_title: "ボード間を切り替える", + switchView_text: + "さまざまなウィジェットを使って異なるボードを活用したり、自分で作成したりして、ワークフローを最適化しましょう。", + walletView_title: "ウォレットボードを作成", + walletView_text: + "ウォレット内の資産に関するすべての情報をAlphadayで追跡できます。", + useSeachBar_title: "検索バー", + useSeachBar_text: + "お気に入りのトークン、プロジェクト、またはトピックを検索して、ウィジェット内のコンテンツをフィルタリングできます。", + reArrangeWidget_title: "ウィジェットを再配置", + reArrangeWidget_text: + "上部のバーを使ってウィジェットをドラッグして位置を変更するか、1回クリックして最小化できます。", + useWidgetLib_title: "ウィジェットライブラリ", + useWidgetLib_text: + "ウィジェットライブラリには、選んで使える便利なウィジェットが多数用意されています。", + comeBack_text: "ユーザーメニューからいつでもウォークスルーに戻れます。", + }, market: { title: "マーケット", line: "ライン", From cf0ac7dbf8ee91ad568cc61bb86790e7774d8543 Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 20 Nov 2024 20:36:01 +0100 Subject: [PATCH 07/51] add more nav translations --- packages/frontend/src/api/utils/translationUtils.ts | 4 ++-- packages/frontend/src/components/podcast/PodcastModule.tsx | 7 ++++--- packages/frontend/src/components/tvl/TvlModule.tsx | 5 +++-- packages/frontend/src/components/video/VideoModule.tsx | 7 ++++--- packages/frontend/src/locales/translation.ts | 4 ++++ 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/api/utils/translationUtils.ts b/packages/frontend/src/api/utils/translationUtils.ts index a8564631..82748af2 100644 --- a/packages/frontend/src/api/utils/translationUtils.ts +++ b/packages/frontend/src/api/utils/translationUtils.ts @@ -18,10 +18,10 @@ export enum ETranslationValues { layer2 = "Layer2", defi = "DeFi", trading = "Trading", + chains = "Chains", + protocols = "Protocols", } -// const allowedKeys = ["Popular", "(A-Z)", "New"] as const; -// export type TTranslationKeys = (typeof allowedKeys)[number]; export type TTranslationValues = `${ETranslationValues}`; const allowedValues: TTranslationValues[] = Object.values(ETranslationValues); const allowedKeys = Object.keys(ETranslationValues); diff --git a/packages/frontend/src/components/podcast/PodcastModule.tsx b/packages/frontend/src/components/podcast/PodcastModule.tsx index af53727e..57dc59c1 100644 --- a/packages/frontend/src/components/podcast/PodcastModule.tsx +++ b/packages/frontend/src/components/podcast/PodcastModule.tsx @@ -8,6 +8,7 @@ import { TPodcastItem, } from "src/api/types"; import { Logger } from "src/api/utils/logging"; +import { translateLabels } from "src/api/utils/translationUtils"; import AudioPlayer from "src/components/podcast/AudioPlayer"; import PodcastChannelsList from "./PodcastChannelsList"; import PodcastItemList from "./PodcastItemList"; @@ -40,15 +41,15 @@ const CHANNELS_LIST_HEIGHT_COLLAPSED = 36; const PODCAST_NAV_ITEMS = [ { - label: "Feed", + label: translateLabels("Feed"), value: EItemFeedPreference.Last, }, { - label: "Trending", + label: translateLabels("Trending"), value: EItemFeedPreference.Trending, }, { - label: "Bookmarks", + label: translateLabels("Bookmarks"), value: EItemFeedPreference.Bookmark, auth: true, }, diff --git a/packages/frontend/src/components/tvl/TvlModule.tsx b/packages/frontend/src/components/tvl/TvlModule.tsx index b7a9a3ec..836c63b6 100644 --- a/packages/frontend/src/components/tvl/TvlModule.tsx +++ b/packages/frontend/src/components/tvl/TvlModule.tsx @@ -4,6 +4,7 @@ import useElementSize from "src/api/hooks/useElementSize"; import { TProjectTvlHistory, TProjectData, TProjectType } from "src/api/types"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; import { Logger } from "src/api/utils/logging"; +import { translateLabels } from "src/api/utils/translationUtils"; import globalMessages from "src/globalMessages"; import { ProtocolTvlItem, ChainTvlItem, TvlItemsHeader } from "./TvlItem"; @@ -23,11 +24,11 @@ interface ITvl { const TVL_NAV_ITEMS = [ { - label: "Chains", + label: translateLabels("Chains"), value: ETVLItemPreference.Chain, }, { - label: "Protocols", + label: translateLabels("Protocols"), value: ETVLItemPreference.Protocol, }, ]; diff --git a/packages/frontend/src/components/video/VideoModule.tsx b/packages/frontend/src/components/video/VideoModule.tsx index b391f0d5..7cb4f691 100644 --- a/packages/frontend/src/components/video/VideoModule.tsx +++ b/packages/frontend/src/components/video/VideoModule.tsx @@ -3,6 +3,7 @@ import { TabsBar, twMerge } from "@alphaday/ui-kit"; import useHeaderScroll from "src/api/hooks/useHeaderScroll"; import { EItemFeedPreference, TVideoChannel, TVideoItem } from "src/api/types"; import { Logger } from "src/api/utils/logging"; +import { translateLabels } from "src/api/utils/translationUtils"; import VideoPlayer from "src/components/video/VideoPlayer"; import VideoChannelsList from "./VideoChannelsList"; import VideoItemList from "./VideoItemList"; @@ -32,15 +33,15 @@ const CHANNELS_LIST_HEIGHT_COLLAPSED = 36; const VIDEO_NAV_ITEMS = [ { - label: "Feed", + label: translateLabels("Feed"), value: EItemFeedPreference.Last, }, { - label: "Trending", + label: translateLabels("Trending"), value: EItemFeedPreference.Trending, }, { - label: "Bookmarks", + label: translateLabels("Bookmarks"), value: EItemFeedPreference.Bookmark, auth: true, }, diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 238ccc67..bea0d27a 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -46,6 +46,8 @@ export const translationEN = { bookmarks: "Bookmarks", timeRange: "Time Range", media: "Media", + chains: "Chains", + protocols: "Protocols", }, }, widget: { @@ -188,6 +190,8 @@ export const translationJA: typeof translationEN = { bookmarks: "ブックマーク", timeRange: "時間帯", media: "メディア", + chains: "チェーン", + protocols: "プロトコル", }, }, widget: { From bb57837d9d736e50d8784a878120dc83a7d216d9 Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 20 Nov 2024 21:09:51 +0100 Subject: [PATCH 08/51] add podcast and video translations --- .../components/podcast/PodcastChannelsList.tsx | 16 ++++++++++++---- .../src/components/video/VideoChannelsList.tsx | 17 +++++++++++++---- packages/frontend/src/locales/translation.ts | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/components/podcast/PodcastChannelsList.tsx b/packages/frontend/src/components/podcast/PodcastChannelsList.tsx index 4544dd01..0a536194 100644 --- a/packages/frontend/src/components/podcast/PodcastChannelsList.tsx +++ b/packages/frontend/src/components/podcast/PodcastChannelsList.tsx @@ -1,5 +1,6 @@ import React, { FC, useEffect, useMemo, useRef, useState } from "react"; import { ChannelSkeleton, IconButton, Input, twMerge } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TPodcastChannel } from "src/api/types"; import { ReactComponent as ChevronSVG } from "src/assets/icons/chevron-down2.svg"; @@ -39,6 +40,7 @@ const PodcastChannelsList: FC = ({ preferredChannelIds, setPreferredChannelIds, }) => { + const { t } = useTranslation(); const [searchState, setSearchState] = useState(""); const preferredChannelIdsCountRef = useRef( preferredChannelIds?.length @@ -111,7 +113,9 @@ const PodcastChannelsList: FC = ({ className="min-w-max flex" > - {showAllChannels ? "Selected Channels" : "Channels"} + {showAllChannels + ? t("podcasts.selected_channels") + : t("podcasts.channels")}
{!showAllChannels && ( @@ -138,7 +142,9 @@ const PodcastChannelsList: FC = ({ : "text-primary" )} > - {showAllChannels ? "less" : "more"} + {showAllChannels + ? t("navigation.general.less") + : t("navigation.general.more")}
@@ -209,13 +215,15 @@ const PodcastChannelsList: FC = ({ {!isLoadingChannels && (

- All Channels + {t("podcasts.all_channels")}

setSearchState(e.target.value)} - placeholder="Filter channels..." + placeholder={t( + "podcasts.channels_input_placeholder" + )} id="search-podcast-channels" name="search podcast channels" /> diff --git a/packages/frontend/src/components/video/VideoChannelsList.tsx b/packages/frontend/src/components/video/VideoChannelsList.tsx index 190dce8f..8baae946 100644 --- a/packages/frontend/src/components/video/VideoChannelsList.tsx +++ b/packages/frontend/src/components/video/VideoChannelsList.tsx @@ -1,5 +1,6 @@ import React, { FC, useEffect, useMemo, useRef, useState } from "react"; import { ChannelSkeleton, IconButton, Input, twMerge } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TVideoChannel } from "src/api/types"; import { ReactComponent as ChevronSVG } from "src/assets/icons/chevron-down2.svg"; @@ -39,6 +40,8 @@ const VideoChannelsList: FC = ({ preferredChannelIds, setPreferredChannelIds, }) => { + const { t } = useTranslation(); + const [searchState, setSearchState] = useState(""); const preferredChannelIdsCountRef = useRef( preferredChannelIds?.length @@ -110,7 +113,9 @@ const VideoChannelsList: FC = ({ className="min-w-max flex" > - {showAllChannels ? "Selected Channels" : "Channels"} + {showAllChannels + ? t("podcasts.selected_channels") + : t("podcasts.channels")}
{!showAllChannels && ( @@ -137,7 +142,9 @@ const VideoChannelsList: FC = ({ : "text-primary" )} > - {showAllChannels ? "less" : "more"} + {showAllChannels + ? t("navigation.general.less") + : t("navigation.general.more")}
@@ -208,13 +215,15 @@ const VideoChannelsList: FC = ({ {!isLoadingChannels && (

- All Channels + {t("podcasts.all_channels")}

{" "}
setSearchState(e.target.value)} - placeholder="Filter channels..." + placeholder={t( + "podcasts.channels_input_placeholder" + )} id="search-video-channels" name="search video channels" /> diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index bea0d27a..97fd5854 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -48,6 +48,8 @@ export const translationEN = { media: "Media", chains: "Chains", protocols: "Protocols", + less: "Less", + more: "More", }, }, widget: { @@ -140,6 +142,12 @@ export const translationEN = { line: "Line", candlestick: "Candlestick", }, + podcasts: { + channels: "Channels", + selected_channels: "Selected Channels", + all_channels: "All Channels", + channels_input_placeholder: "Search for channels", + }, }; export const translationJA: typeof translationEN = { @@ -192,6 +200,8 @@ export const translationJA: typeof translationEN = { media: "メディア", chains: "チェーン", protocols: "プロトコル", + less: "少なく", + more: "もっと", }, }, widget: { @@ -284,4 +294,10 @@ export const translationJA: typeof translationEN = { line: "ライン", candlestick: "ローソク足", }, + podcasts: { + channels: "チャンネル", + selected_channels: "選択したチャンネル", + all_channels: "すべてのチャンネル", + channels_input_placeholder: "チャンネルを検索", + }, }; From 24ef9673eecce0d96cc7e714d52000ef54948d08 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 09:38:43 +0100 Subject: [PATCH 09/51] translate more items --- .../components/discord/DiscordFeedItem.tsx | 6 +++++- .../frontend/src/components/tvl/TvlItem.tsx | 14 ++++++++----- .../src/containers/base/BaseContainerMenu.tsx | 1 - .../containers/base/BaseContainerOptions.tsx | 16 ++++++++++++--- packages/frontend/src/locales/translation.ts | 20 +++++++++++++++++++ .../src/components/base/BaseComponents.tsx | 7 +++---- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/packages/frontend/src/components/discord/DiscordFeedItem.tsx b/packages/frontend/src/components/discord/DiscordFeedItem.tsx index b39d851f..9fe743b9 100644 --- a/packages/frontend/src/components/discord/DiscordFeedItem.tsx +++ b/packages/frontend/src/components/discord/DiscordFeedItem.tsx @@ -1,6 +1,7 @@ import { FC, FormEvent, useState } from "react"; import { listItemVariants, HRElement } from "@alphaday/ui-kit"; import moment from "moment"; +import { useTranslation } from "react-i18next"; import ReactMarkdown from "react-markdown"; import { TDiscordItem } from "src/api/types"; import { imgOnError, wideImgOnError } from "src/api/utils/errorHandling"; @@ -47,6 +48,7 @@ const MIN_CONTENT_LENGTH = 200; const discordStyle = listItemVariants("discord"); const DiscordFeedItem: FC = ({ item }) => { + const { t } = useTranslation(); const [isExpanded, setIsExpanded] = useState(false); const contentPreview = item.content.slice(0, MIN_CONTENT_LENGTH) + @@ -149,7 +151,9 @@ const DiscordFeedItem: FC = ({ item }) => { setIsExpanded((prev) => !prev); }} > - {isExpanded ? "Less" : "Read More"} + {isExpanded + ? t("navigation.general.less") + : t("navigation.general.readMore")}
diff --git a/packages/frontend/src/components/tvl/TvlItem.tsx b/packages/frontend/src/components/tvl/TvlItem.tsx index 6fcf444c..7b4adfa8 100644 --- a/packages/frontend/src/components/tvl/TvlItem.tsx +++ b/packages/frontend/src/components/tvl/TvlItem.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { Arrow } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TProjectData, TProjectTvlHistory, TProjectType } from "src/api/types"; import { imgOnError } from "src/api/utils/errorHandling"; import { formatNumber, ENumberStyle } from "src/api/utils/format"; @@ -26,6 +27,7 @@ const handleOnClick = (projectData: TProjectData) => () => { export const TvlItemsHeader: FC<{ projectType: TProjectType }> = ({ projectType, }) => { + const { t } = useTranslation(); return (
= ({ justifyContent: "right", }} > - 1D Change + 1D {t("others.change")}
= ({ justifyContent: "right", }} > - 7D Change + 7D {t("others.change")}
= ({ index, twoRowCellLayout, }) => { + const { t } = useTranslation(); + const history7d = projectHistory?.history; const { tvl } = projectData; @@ -208,7 +212,7 @@ export const ProtocolTvlItem: FC = ({
- 1d change + 1d {t("others.change")} {(percentChange1d / 100).toLocaleString( @@ -230,7 +234,7 @@ export const ProtocolTvlItem: FC = ({
- 7d change + 7d {t("others.change")} {(percentChange7d / 100).toLocaleString( @@ -382,7 +386,7 @@ interface IChainlTvlProps { } /** - * Chains, as oppose to protocols, do not include 1d/7d percentage change, + * Chains, as oppose to protocols, do not include 1d/7d percentage {t("others.change")}")}, * nor history data. */ export const ChainTvlItem: FC = ({ index, projectData }) => { diff --git a/packages/frontend/src/containers/base/BaseContainerMenu.tsx b/packages/frontend/src/containers/base/BaseContainerMenu.tsx index b8947901..a24c29dd 100644 --- a/packages/frontend/src/containers/base/BaseContainerMenu.tsx +++ b/packages/frontend/src/containers/base/BaseContainerMenu.tsx @@ -234,7 +234,6 @@ const BaseContainerMenu: FC = ({ style={IconStyle} className="icon text-primaryVariant200" /> -
{t("widget.remove_widget")}
diff --git a/packages/frontend/src/containers/base/BaseContainerOptions.tsx b/packages/frontend/src/containers/base/BaseContainerOptions.tsx index aaee2753..4e687241 100644 --- a/packages/frontend/src/containers/base/BaseContainerOptions.tsx +++ b/packages/frontend/src/containers/base/BaseContainerOptions.tsx @@ -12,6 +12,7 @@ import { import { ReactComponent as PinSVG } from "@alphaday/ui-kit/src/assets/svg/pin.svg"; import { ReactComponent as PinnedSVG } from "@alphaday/ui-kit/src/assets/svg/pinned.svg"; import { DraggableProvidedDragHandleProps } from "react-beautiful-dnd"; +import { useTranslation } from "react-i18next"; import { components, GroupBase, @@ -199,6 +200,7 @@ const BaseContainerOptions: FC = ({ headerRef, dragProps, }) => { + const { t: translate } = useTranslation(); const { name, settings, widget } = moduleData; const widgetTitle = (name || widget.name).toUpperCase(); const isAuthenticated = useAppSelector(selectIsAuthenticated); @@ -281,7 +283,10 @@ const BaseContainerOptions: FC = ({ searchResults={keywordResults} searchState={searchState} setSearchState={setSearchState} - placeholder="ethereum, bitcoin, etc." + // placeholder="ethereum, bitcoin, etc." + placeholder={translate( + "others.tag_options.auth" + )} onIncludeTag={(tag) => { const tagExists = tags.find( (t) => t.id === tag.id @@ -320,8 +325,12 @@ const BaseContainerOptions: FC = ({ setSearchState={setCoinSearch} placeholder={ isAuthenticated - ? "eth, btc, etc." - : "Sign up to pin coins and more" + ? translate( + "others.tag_options.auth" + ) + : translate( + "others.tag_options.unAuth" + ) } title={ isAuthenticated @@ -384,6 +393,7 @@ const BaseContainerOptions: FC = ({ diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 97fd5854..ae4febfb 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -43,6 +43,7 @@ export const translationEN = { feed: "Feed", trending: "Trending", readLater: "Read Later", + readMore: "Read More", bookmarks: "Bookmarks", timeRange: "Time Range", media: "Media", @@ -148,6 +149,15 @@ export const translationEN = { all_channels: "All Channels", channels_input_placeholder: "Search for channels", }, + others: { + tag_options: { + auth: "ethereum, bitcoin, etc.", + unAuth: "Sign up to pin coins and more", + }, + change: "Change", + name: "Name", + tvl: "TVL", + }, }; export const translationJA: typeof translationEN = { @@ -195,6 +205,7 @@ export const translationJA: typeof translationEN = { feed: "フィード", trending: "トレンド", readLater: "後で読む", + readMore: "続きを読む", bookmarks: "ブックマーク", timeRange: "時間帯", media: "メディア", @@ -300,4 +311,13 @@ export const translationJA: typeof translationEN = { all_channels: "すべてのチャンネル", channels_input_placeholder: "チャンネルを検索", }, + others: { + tag_options: { + auth: "ethereum、bitcoinなど", + unAuth: "コインをピン留めなどのためにサインアップ", + }, + change: "変更", + name: "名前", + tvl: "TVL", + }, }; diff --git a/packages/ui-kit/src/components/base/BaseComponents.tsx b/packages/ui-kit/src/components/base/BaseComponents.tsx index 622c3507..36f67d85 100644 --- a/packages/ui-kit/src/components/base/BaseComponents.tsx +++ b/packages/ui-kit/src/components/base/BaseComponents.tsx @@ -59,8 +59,8 @@ export const BaseModuleHeader = forwardRef< export const BaseModuleOptionsFooter = forwardRef< HTMLDivElement | null, - { removeWidget: () => void } ->(({ removeWidget }, ref) => { + { text: string; removeWidget: () => void } +>(({ removeWidget, text }, ref) => { return (
@@ -70,8 +70,7 @@ export const BaseModuleOptionsFooter = forwardRef< title="Removes this widget from the current board" className="hover:border-borderLine focus:border-borderLine border-borderLine" > -   Remove - Widget +   R {text}
From 91704ea4e1a6781f51d96846401b8ccb214aaeb1 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 13:40:07 +0100 Subject: [PATCH 10/51] add translation for global messages --- packages/frontend/src/api/utils/textUtils.tsx | 10 ++ .../event-details/components/parts.tsx | 10 +- packages/frontend/src/globalMessages.ts | 67 +++++++------ packages/frontend/src/locales/translation.ts | 94 +++++++++++++++++++ 4 files changed, 150 insertions(+), 31 deletions(-) diff --git a/packages/frontend/src/api/utils/textUtils.tsx b/packages/frontend/src/api/utils/textUtils.tsx index 3fe8202b..71d557ed 100644 --- a/packages/frontend/src/api/utils/textUtils.tsx +++ b/packages/frontend/src/api/utils/textUtils.tsx @@ -209,3 +209,13 @@ export const renderToString = (node: JSX.Element): string => { flushSync(() => root.render(node)); return wrapper.innerHTML; }; + +// Function to evaluate the template literal +export const evaluateTemplate = ( + templateString: string, + data: Record +) => { + return templateString.replace(/\${(\w+)}/g, (match, key) => { + return data[key] || match; + }); +}; diff --git a/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx b/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx index a74a0c93..19661ca0 100644 --- a/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx +++ b/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx @@ -1,6 +1,7 @@ import { FC } from "react"; import { Button, twMerge } from "@alphaday/ui-kit"; import DOMPurify from "dompurify"; +import { useTranslation } from "react-i18next"; import { TEventDetails } from "src/api/types"; import { ReactComponent as ExternalLinkSVG } from "src/assets/icons/external-link.svg"; @@ -8,6 +9,7 @@ export const EventOrganizer: FC<{ event: TEventDetails; className?: string; }> = ({ event, className }) => { + const { t } = useTranslation(); return (
- Organizers + {t("calendar.organizer")}
@@ -29,11 +31,12 @@ export const EventSpeakers: FC<{ event: TEventDetails; className?: string; }> = ({ event, className }) => { + const { t } = useTranslation(); return (
- Speakers + {t("calendar.speakers")}
@@ -44,6 +47,7 @@ export const EventSpeakers: FC<{ }; export const EventLink: FC<{ event: TEventDetails }> = ({ event }) => { + const { t } = useTranslation(); return ( diff --git a/packages/frontend/src/globalMessages.ts b/packages/frontend/src/globalMessages.ts index 340b63b1..b87ad00d 100644 --- a/packages/frontend/src/globalMessages.ts +++ b/packages/frontend/src/globalMessages.ts @@ -1,20 +1,24 @@ +import i18next from "i18next"; +import { evaluateTemplate } from "./api/utils/textUtils"; + const SlugToWidgetNameMap: Record = { calendar_template: "Calendar", }; const globalMessages = { error: { - title: "Error", - notFound: "The requested page could not be found.", - generic: "An error occurred while processing your request.", - forbidden: "You do not have permission to access this page.", - unauthorized: "You are not authorized to access this page.", - notAuthenticated: "Please connect and verify your wallet to continue", - maxViews: "You have created maximum allowed boards", - maxWidgets: "Your board has more widgets than allowed", - maxViewWidgets: - "You have exceeded the allowed count of this widget on a board", + title: i18next.t("messages.error.title"), + notFound: i18next.t("messages.error.notFound"), + generic: i18next.t("messages.error.generic"), + forbidden: i18next.t("messages.error.forbidden"), + unauthorized: i18next.t("messages.error.unauthorized"), + notAuthenticated: i18next.t("messages.error.notAuthenticated"), + maxViews: i18next.t("messages.error.maxViews"), + maxWidgets: i18next.t("messages.error.maxWidgets"), + maxViewWidgets: i18next.t("messages.error.maxViewWidgets"), requestFailed(term = "the data"): string { - return `An error occurred fetching ${term}, please try again later`; + return evaluateTemplate(i18next.t("messages.error.requestFailed"), { + term, + }); }, boardHasNoRequiredWidget( widget_template: string | undefined, @@ -25,39 +29,46 @@ const globalMessages = { widget_template && widget_template in SlugToWidgetNameMap ) { - return `This ${ - boardName || "" - } board does not have the required ${ - SlugToWidgetNameMap[widget_template] - } widget, to access this route you need to add the ${ - SlugToWidgetNameMap[widget_template] - } widget to this board and refresh the page.`; + return evaluateTemplate( + i18next.t("messages.error.boardHasNoRequiredWidget"), + { + boardName: boardName || "", + widgetName: SlugToWidgetNameMap[widget_template], + } + ); } return ""; }, }, success: { - title: "Success", - generic: "Your request was processed successfully.", + title: i18next.t("messages.success.title"), + generic: i18next.t("messages.success.generic"), }, queries: { - noResults: "No results found", - noMatchFound: (item: string): string => `No matching ${item} found.`, + noResults: i18next.t("messages.queries.noResults"), + noMatchFound: (item: string): string => + evaluateTemplate(i18next.t("messages.queries.noMatchFound"), { + item, + }), }, portfolio: { - signUp: "Sign up to save your portfolio", - connectWallet: "To signup, first connect your wallet.", - verifyWallet: - "Sign a fee-less message to confirm ownership and log in to Alphaday to save your configuration.", + signUp: i18next.t("messages.portfolio.signUp"), + connectWallet: i18next.t("messages.portfolio.connectWallet"), + verifyWallet: i18next.t("messages.portfolio.verifyWallet"), }, callToAction: { signUpToBookmark: (item?: string) => - `Sign up to bookmark ${item ?? ""} and unlock more features`, + evaluateTemplate( + i18next.t("messages.callToAction.signUpToBookmark"), + { + item: item || "", + } + ), }, }; export const calendarMessages = { - noEvents: "No upcoming events found", + noEvents: i18next.t("calendar.no_events"), }; export default globalMessages; diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index ae4febfb..ef111632 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -149,6 +149,12 @@ export const translationEN = { all_channels: "All Channels", channels_input_placeholder: "Search for channels", }, + calendar: { + organizers: "Organizers", + speakers: "Speakers", + more_details: "More Details", + noEvents: "No upcoming events found", + }, others: { tag_options: { auth: "ethereum, bitcoin, etc.", @@ -158,6 +164,46 @@ export const translationEN = { name: "Name", tvl: "TVL", }, + messages: { + error: { + title: "Error", + notFound: "The requested page could not be found.", + generic: "An error occurred while processing your request.", + forbidden: "You do not have permission to access this page.", + unauthorized: "You are not authorized to access this page.", + notAuthenticated: + "Please connect and verify your wallet to continue", + maxViews: "You have created maximum allowed boards", + maxWidgets: "Your board has more widgets than allowed", + maxViewWidgets: + "You have exceeded the allowed count of this widget on a board", + requestFailed: + // eslint-disable-next-line no-template-curly-in-string + "An error occurred fetching ${term}, please try again later", + boardHasNoRequiredWidget: + // eslint-disable-next-line no-template-curly-in-string + "This ${boardName} board does not have the required ${SlugToWidgetNameMap[widget_template]} widget, to access this route you need to add the ${SlugToWidgetNameMap[widget_template]} widget to this board and refresh the page.", + }, + success: { + title: "Success", + generic: "Your request was processed successfully.", + }, + queries: { + noResults: "No results found", + // eslint-disable-next-line no-template-curly-in-string + noMatchFound: "No matching ${item} found.", + }, + portfolio: { + signUp: "Sign up to save your portfolio", + connectWallet: "To signup, first connect your wallet.", + verifyWallet: + "Sign a fee-less message to confirm ownership and log in to Alphaday to save your configuration.", + }, + callToAction: { + // eslint-disable-next-line no-template-curly-in-string + signUpToBookmark: "Sign up to bookmark this ${item}", + }, + }, }; export const translationJA: typeof translationEN = { @@ -311,6 +357,12 @@ export const translationJA: typeof translationEN = { all_channels: "すべてのチャンネル", channels_input_placeholder: "チャンネルを検索", }, + calendar: { + organizers: "主催者", + speakers: "スピーカー", + more_details: "詳細", + noEvents: "近日開催されるイベントはありませ", + }, others: { tag_options: { auth: "ethereum、bitcoinなど", @@ -320,4 +372,46 @@ export const translationJA: typeof translationEN = { name: "名前", tvl: "TVL", }, + messages: { + error: { + title: "エラー", + notFound: "リクエストされたページが見つかりませんでした。", + generic: "リクエストの処理中にエラーが発生しました。", + forbidden: "このページにアクセスする権限がありません。", + unauthorized: "このページにアクセスする権限がありません。", + notAuthenticated: + "続行するにはウォレットを接続して確認してください", + maxViews: "作成できるボードの最大数に達しました", + maxWidgets: "ボードに追加できるウィジェットの数を超えました", + maxViewWidgets: + "ボード上のこのウィジェットの許可された数を超えました", + requestFailed: + // eslint-disable-next-line no-template-curly-in-string + "${term}の取得中にエラーが発生しました。後で再試行してください", + boardHasNoRequiredWidget: + // eslint-disable-next-line no-template-curly-in-string + "この${boardName}ボードには、${SlugToWidgetNameMap[widget_template]}ウィジェットが必要です。このルートにアクセスするには、${SlugToWidgetNameMap[widget_template]}ウィジェットをこのボードに追加してページを更新する必要があります。", + }, + success: { + title: "成功", + generic: "リクエストが正常に処理されました。", + }, + queries: { + noResults: "結果が見つかりません", + // eslint-disable-next-line no-template-curly-in-string + noMatchFound: "${item}が見つかりませんでした。", + }, + portfolio: { + signUp: "ポートフォリオを保存するにはサインアップしてください", + connectWallet: + "サインアップするには、まずウォレットを接続してください。", + verifyWallet: + "所有権を確認し、設定を保存するためにAlphadayにログインするには、手数料のないメッセージに署名してください。", + }, + callToAction: { + signUpToBookmark: + // eslint-disable-next-line no-template-curly-in-string + "この${item}をブックマークするにはサインアップしてください", + }, + }, }; From 08405ed1231cac6f0bb44192ca510e37e2666ccf Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 13:53:56 +0100 Subject: [PATCH 11/51] add translation verasity widget --- .../client/VerasityTokenomicsModule.tsx | 14 ++++++++------ packages/frontend/src/locales/translation.ts | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx b/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx index 3e2adc38..65694dac 100644 --- a/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx +++ b/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx @@ -1,4 +1,5 @@ import { useEffect, useState, FC, useMemo } from "react"; +import { useTranslation } from "react-i18next"; import { useHover, useLayer, useMousePositionAsTrigger } from "react-laag"; import { toast } from "src/api/utils/toastUtils"; import CONFIG from "src/config"; @@ -39,6 +40,7 @@ export interface IPieChart { } const PieChartModule: FC = ({ data }) => { + const { t } = useTranslation(); const { name, ticker, @@ -223,19 +225,19 @@ const PieChartModule: FC = ({ data }) => {
- Token Name: + {t("verasity.token_name")}: {" "} {name}
- Token Ticker: + {t("verasity.token_ticker")}: {" "} ${ticker}
- Smart contract address: + {t("verasity.sm_address")}: {" "} = ({ data }) => {
- Total supply: + {t("verasity.total_supply")}: {" "} {totalSupply}
- Max. Circulating supply: + {t("verasity.max_circle_supply")}: {" "} {maxSupply}
- Circulating supply: + {t("verasity.circle_supply")}: {" "} {supply}
diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index ef111632..dd680578 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -164,6 +164,14 @@ export const translationEN = { name: "Name", tvl: "TVL", }, + verasity: { + token_name: "Token Name", + token_ticker: "Token Ticker", + sm_address: "Smart Contract Address", + total_supply: "Total Supply", + max_circle_supply: "Max Circulating Supply", + circle_supply: "Circulating Supply", + }, messages: { error: { title: "Error", @@ -372,6 +380,14 @@ export const translationJA: typeof translationEN = { name: "名前", tvl: "TVL", }, + verasity: { + token_name: "トークン名", + token_ticker: "トークンティッカー", + sm_address: "スマートコントラクトアドレス", + total_supply: "総供給量", + max_circle_supply: "最大循環供給量", + circle_supply: "循環供給量", + }, messages: { error: { title: "エラー", From 2a7f5ad926e48579462ab3134c7416ecf0b22cc1 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:09:45 +0100 Subject: [PATCH 12/51] add cookies translate --- .../components/cookie-disclaimer/CookieDisclaimer.tsx | 6 ++---- .../cookie-disclaimer/CookieDisclaimerContainer.tsx | 5 +++-- packages/frontend/src/locales/translation.ts | 10 ++++++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/cookie-disclaimer/CookieDisclaimer.tsx b/packages/frontend/src/components/cookie-disclaimer/CookieDisclaimer.tsx index 64cca42b..5704fb6f 100644 --- a/packages/frontend/src/components/cookie-disclaimer/CookieDisclaimer.tsx +++ b/packages/frontend/src/components/cookie-disclaimer/CookieDisclaimer.tsx @@ -1,6 +1,7 @@ import { FC } from "react"; import { Button, Overlay } from "@alphaday/ui-kit"; import CONFIG from "src/config"; +import i18n from "src/i18n"; const { Z_INDEX_REGISTRY } = CONFIG.UI; @@ -25,10 +26,7 @@ const CookieDisclaimer: FC = ({ choices }) => ( >

- We use essential cookies to make Alphaday work. We'd like - to use other cookies to improve and personalize your visit and - to analyze our website's performance, but only if you - accept. + {i18n.t("others.cookie.text")}

{choices diff --git a/packages/frontend/src/containers/cookie-disclaimer/CookieDisclaimerContainer.tsx b/packages/frontend/src/containers/cookie-disclaimer/CookieDisclaimerContainer.tsx index 20738106..e73e4248 100644 --- a/packages/frontend/src/containers/cookie-disclaimer/CookieDisclaimerContainer.tsx +++ b/packages/frontend/src/containers/cookie-disclaimer/CookieDisclaimerContainer.tsx @@ -8,6 +8,7 @@ import CookieDisclaimer, { TCookieChoiceProps, } from "src/components/cookie-disclaimer/CookieDisclaimer"; import CONFIG from "src/config"; +import i18n from "src/i18n"; const CookieDisclaimerContainer: React.FC = () => { const dispatch = useAppDispatch(); @@ -44,7 +45,7 @@ const CookieDisclaimerContainer: React.FC = () => { const choices: Array = [ { key: ECookieChoice.AcceptAll, - buttonText: "Accept All", + buttonText: i18n.t("others.cookie.acceptAll"), handler: () => { setChoice(ECookieChoice.AcceptAll); }, @@ -52,7 +53,7 @@ const CookieDisclaimerContainer: React.FC = () => { }, { key: ECookieChoice.AcceptEssential, - buttonText: "Accept Essential", + buttonText: i18n.t("others.cookie.acceptEssential"), handler: () => { setChoice(ECookieChoice.AcceptEssential); }, diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index dd680578..ce3a3725 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -163,6 +163,11 @@ export const translationEN = { change: "Change", name: "Name", tvl: "TVL", + cookie: { + text: "We use essential cookies to make Alphaday work. We'd like to use other cookies to improve and personalize your visit and to analyze our website's performance, but only if you accept.", + acceptAll: "Accept All", + acceptEssential: "Accept Essential", + }, }, verasity: { token_name: "Token Name", @@ -379,6 +384,11 @@ export const translationJA: typeof translationEN = { change: "変更", name: "名前", tvl: "TVL", + cookie: { + text: "Alphadayを動作させるために必要なクッキーを使用しています。他のクッキーを使用して、訪問を改善し、パーソナライズし、ウェブサイトのパフォーマンスを分析したいと考えていますが、それはあなたが受け入れる場合にのみです。", + acceptAll: "すべてを受け入れる", + acceptEssential: "必要なものを受け入れる", + }, }, verasity: { token_name: "トークン名", From 2467503a540e6d66dcb5433ca88affdcefce4ab6 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:18:26 +0100 Subject: [PATCH 13/51] countdown mudule --- .../src/components/countdown/CountdownModule.tsx | 12 +++++++++++- packages/frontend/src/locales/translation.ts | 16 ++++++++++++++++ packages/ui-kit/src/components/timer/Timer.tsx | 16 +++++++++++----- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/countdown/CountdownModule.tsx b/packages/frontend/src/components/countdown/CountdownModule.tsx index 77039486..8de27f62 100644 --- a/packages/frontend/src/components/countdown/CountdownModule.tsx +++ b/packages/frontend/src/components/countdown/CountdownModule.tsx @@ -1,6 +1,7 @@ import { FC, ReactNode, useEffect, useState } from "react"; import { KeyValueTable, Timer, twMerge } from "@alphaday/ui-kit"; import moment from "moment"; +import { useTranslation } from "react-i18next"; interface IProps { targetDate: number; // unix timestamp in s @@ -18,6 +19,7 @@ const CountdownModule: FC = ({ children, items, }) => { + const { t } = useTranslation(); const [secondsToDate, setSecondsToDate] = useState( targetDate - moment().unix() ); @@ -37,7 +39,15 @@ const CountdownModule: FC = ({ return (
- +
= ({ count, label }) => ( interface IProps { secondsToDate: number; + labels: { + days: string; + hours: string; + minutes: string; + seconds: string; + }; } -export const Timer: FC = ({ secondsToDate }) => { +export const Timer: FC = ({ secondsToDate, labels }) => { // make sure we don't display negative values const nonNegativeSecondsToDate = secondsToDate >= 0 ? secondsToDate : 0; @@ -32,22 +38,22 @@ export const Timer: FC = ({ secondsToDate }) => { count={leftPadDate( Math.floor(nonNegativeSecondsToDate / (24 * 3600)) )} - label="Days" + label={labels.days} />
); From b9f834824af791a48b8d38c5808c6d7c6e23917a Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:27:35 +0100 Subject: [PATCH 14/51] update date --- packages/frontend/src/api/utils/dateUtils.ts | 27 ++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/frontend/src/api/utils/dateUtils.ts b/packages/frontend/src/api/utils/dateUtils.ts index efdb4731..7ec02d04 100644 --- a/packages/frontend/src/api/utils/dateUtils.ts +++ b/packages/frontend/src/api/utils/dateUtils.ts @@ -1,3 +1,4 @@ +import i18next from "i18next"; import moment from "moment"; /** * returns a text that represents the given datetime @@ -8,19 +9,19 @@ import moment from "moment"; export const computeDuration = (date: string | Date): string => { moment.updateLocale("en", { relativeTime: { - future: "in %s", // this shouldn't occur If it does there's an error. - past: "%s ago", - s: "%ds", - m: "%dm", - mm: "%dm", - h: "%dh", - hh: "%dh", - d: "%dd", - dd: "%dd", - M: "%dmo", - MM: "%dmo", - y: "%dy", - yy: "%dy", + future: i18next.t("datelocale.future"), // this shouldn't occur If it does there's an error. + past: i18next.t("datelocale.past"), + s: i18next.t("datelocale.s"), + m: i18next.t("datelocale.m"), + mm: i18next.t("datelocale.mm"), + h: i18next.t("datelocale.h"), + hh: i18next.t("datelocale.hh"), + d: i18next.t("datelocale.d"), + dd: i18next.t("datelocale.dd"), + M: i18next.t("datelocale.M"), + MM: i18next.t("datelocale.MM"), + y: i18next.t("datelocale.y"), + yy: i18next.t("datelocale.yy"), }, }); From a21ee0d965b69249810fb9b052f034b8dd0d2a9c Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:27:49 +0100 Subject: [PATCH 15/51] custom data module --- .../custom-modules/CustomTableModule.tsx | 4 ++- packages/frontend/src/locales/translation.ts | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/custom-modules/CustomTableModule.tsx b/packages/frontend/src/components/custom-modules/CustomTableModule.tsx index a2730953..f4f9d71e 100644 --- a/packages/frontend/src/components/custom-modules/CustomTableModule.tsx +++ b/packages/frontend/src/components/custom-modules/CustomTableModule.tsx @@ -1,5 +1,6 @@ import { FC, FormEvent, useRef, useState } from "react"; import { ModuleLoader, ScrollBar } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { useWidgetSize } from "src/api/hooks"; import { TCustomLayoutEntry, @@ -34,6 +35,7 @@ const CustomTableModule: FC = ({ handlePaginate, setWidgetHeight, }) => { + const { t } = useTranslation(); const widgetSize = useWidgetSize([500]); const isCompactMode = widgetSize === "sm" || columns.length > STD_LAYOUT_MAX_SIZE; @@ -72,7 +74,7 @@ const CustomTableModule: FC = ({ if (items.length === 0) { return (
-

No Items Found

+

{t("others.no_items_found")}

); } diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index e47ecdc6..6053c93b 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -163,6 +163,7 @@ export const translationEN = { change: "Change", name: "Name", tvl: "TVL", + no_items_found: "No Items Found", cookie: { text: "We use essential cookies to make Alphaday work. We'd like to use other cookies to improve and personalize your visit and to analyze our website's performance, but only if you accept.", acceptAll: "Accept All", @@ -225,6 +226,21 @@ export const translationEN = { seconds: "Seconds", }, }, + datelocale: { + future: "in %s", + past: "%s ago", + s: "%ds", + m: "%dm", + mm: "%dm", + h: "%dh", + hh: "%dh", + d: "%dd", + dd: "%dd", + M: "%dmo", + MM: "%dmo", + y: "%dy", + yy: "%dy", + }, }; export const translationJA: typeof translationEN = { @@ -392,6 +408,7 @@ export const translationJA: typeof translationEN = { change: "変更", name: "名前", tvl: "TVL", + no_items_found: "アイテムが見つかりません", cookie: { text: "Alphadayを動作させるために必要なクッキーを使用しています。他のクッキーを使用して、訪問を改善し、パーソナライズし、ウェブサイトのパフォーマンスを分析したいと考えていますが、それはあなたが受け入れる場合にのみです。", acceptAll: "すべてを受け入れる", @@ -456,4 +473,19 @@ export const translationJA: typeof translationEN = { seconds: "秒", }, }, + datelocale: { + future: "%s後", + past: "%s前", + s: "%ds", + m: "%dm", + mm: "%dm", + h: "%dh", + hh: "%dh", + d: "%dd", + dd: "%dd", + M: "%dmo", + MM: "%dmo", + y: "%dy", + yy: "%dy", + }, }; From 4d92ddb9757f3cdbf9b3e8ac90a96dce86ea2411 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:31:39 +0100 Subject: [PATCH 16/51] add error page --- packages/frontend/src/components/error/GeneralError.tsx | 4 +++- packages/frontend/src/locales/translation.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/error/GeneralError.tsx b/packages/frontend/src/components/error/GeneralError.tsx index 9837fe06..d9f53155 100644 --- a/packages/frontend/src/components/error/GeneralError.tsx +++ b/packages/frontend/src/components/error/GeneralError.tsx @@ -1,8 +1,10 @@ import { FC } from "react"; +import { useTranslation } from "react-i18next"; import logoDay from "src/assets/svg/logo-white.svg"; import CONFIG from "src/config"; const GeneralError: FC<{ children?: React.ReactNode }> = ({ children }) => { + const { t } = useTranslation(); const isHome = window.location.pathname === "/"; return (
@@ -26,7 +28,7 @@ const GeneralError: FC<{ children?: React.ReactNode }> = ({ children }) => { alt="alphaday logo" className="m-0 mr-2 h-5" />{" "} - Back to Home + {t("back_to_home")} )}
diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 6053c93b..eb1af8ee 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -197,6 +197,7 @@ export const translationEN = { boardHasNoRequiredWidget: // eslint-disable-next-line no-template-curly-in-string "This ${boardName} board does not have the required ${SlugToWidgetNameMap[widget_template]} widget, to access this route you need to add the ${SlugToWidgetNameMap[widget_template]} widget to this board and refresh the page.", + back_to_home: "Back to Home", }, success: { title: "Success", @@ -442,6 +443,7 @@ export const translationJA: typeof translationEN = { boardHasNoRequiredWidget: // eslint-disable-next-line no-template-curly-in-string "この${boardName}ボードには、${SlugToWidgetNameMap[widget_template]}ウィジェットが必要です。このルートにアクセスするには、${SlugToWidgetNameMap[widget_template]}ウィジェットをこのボードに追加してページを更新する必要があります。", + back_to_home: "ホームに戻る", }, success: { title: "成功", From ea72e7e9a9fe356f82d77ef26bff7fe778b14a2e Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 14:38:14 +0100 Subject: [PATCH 17/51] gas --- .../frontend/src/components/gas/GasPriceBox.tsx | 10 +++++++--- .../frontend/src/components/gas/GasPriceTable.tsx | 5 ++++- packages/frontend/src/components/gas/Item.tsx | 13 ++++++++++--- packages/frontend/src/locales/translation.ts | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/packages/frontend/src/components/gas/GasPriceBox.tsx b/packages/frontend/src/components/gas/GasPriceBox.tsx index 22e36ea3..b9083225 100644 --- a/packages/frontend/src/components/gas/GasPriceBox.tsx +++ b/packages/frontend/src/components/gas/GasPriceBox.tsx @@ -1,5 +1,6 @@ import { FC, HTMLProps } from "react"; import { twMerge, Skeleton } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; const GasSkeleton = () => (
@@ -37,6 +38,7 @@ const GasPriceBox: FC = ({ usdPrice, isCard, }) => { + const { t } = useTranslation(); return (
= ({ )} > {type === "fast" && ( - {type} + + {t("gas.fast")} + )} {type === "standard" && ( - {type} + {t("gas.standard")} )} {type === "slow" && ( - {type} + {t("gas.slow")} )}
diff --git a/packages/frontend/src/components/gas/GasPriceTable.tsx b/packages/frontend/src/components/gas/GasPriceTable.tsx index c225d61f..9999cc92 100644 --- a/packages/frontend/src/components/gas/GasPriceTable.tsx +++ b/packages/frontend/src/components/gas/GasPriceTable.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { KeyValueTable } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; const formatNumber = (value: number) => new Intl.NumberFormat("en-US", { @@ -24,6 +25,8 @@ const GasPriceTable: FC = ({ finalizedEpoch, finalizedSlot, }) => { + const { t } = useTranslation(); + const items = [ [ { @@ -59,7 +62,7 @@ const GasPriceTable: FC = ({ return ( <>
- Beacon Chain Data + {t("gas.beacon_chain_data")}
diff --git a/packages/frontend/src/components/gas/Item.tsx b/packages/frontend/src/components/gas/Item.tsx index a5017148..4b92d92b 100644 --- a/packages/frontend/src/components/gas/Item.tsx +++ b/packages/frontend/src/components/gas/Item.tsx @@ -1,4 +1,5 @@ import { FC } from "react"; +import { useTranslation } from "react-i18next"; import { TAssetValue, TGasPrices } from "src/api/types"; import CONFIG from "src/config"; @@ -21,19 +22,25 @@ const Item: FC = ({ gasUnits, gasPrices, }) => { + const { t } = useTranslation(); + if (ethPrice && gasPrices) { if (type === "title") { return (
{title} - Fast (est.) + + {t("gas.fast")} (est.) + - Standard (est.) + {t("gas.standard")} (est.) - Slow (est.) + + {t("gas.slow")} (est.) +
); diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index eb1af8ee..1c9ad5e4 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -242,6 +242,13 @@ export const translationEN = { y: "%dy", yy: "%dy", }, + gas: { + title: "Gas Price", + fast: "Fast", + standard: "Standard", + slow: "Slow", + beacon_chain_data: "Beacon Chain Data", + }, }; export const translationJA: typeof translationEN = { @@ -490,4 +497,11 @@ export const translationJA: typeof translationEN = { y: "%dy", yy: "%dy", }, + gas: { + title: "ガス価格", + fast: "高速", + standard: "標準", + slow: "遅い", + beacon_chain_data: "ビーコンチェーンデータ", + }, }; From e705efa79900ab5edacec24ef9aeaf43d52c27da Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:21:14 +0100 Subject: [PATCH 18/51] market --- packages/frontend/src/api/types/market.ts | 17 +++-- packages/frontend/src/api/utils/dateUtils.ts | 27 +++---- .../src/components/market/CoinInfo.tsx | 3 +- .../src/components/market/MarketModule.tsx | 13 +++- .../module-disclaimer/ModuleDisclaimer.tsx | 6 +- .../src/components/portfolio/nfts/NftCard.tsx | 4 +- .../src/components/portfolio/nfts/NftList.tsx | 6 +- packages/frontend/src/locales/translation.ts | 75 ++++++++++++------- 8 files changed, 95 insertions(+), 56 deletions(-) diff --git a/packages/frontend/src/api/types/market.ts b/packages/frontend/src/api/types/market.ts index e8d5f98a..5630fbe0 100644 --- a/packages/frontend/src/api/types/market.ts +++ b/packages/frontend/src/api/types/market.ts @@ -1,3 +1,4 @@ +import i18next from "i18next"; import { TCoin } from "./primitives"; export type TAssetPrice = { @@ -38,14 +39,14 @@ export type TCoinMarketHistory = { }; export const CHART_RANGE_OPTIONS = { - oneDay: "1D", - oneWeek: "1W", - oneMonth: "1M", - threeMonths: "3M", - yearToDate: "YTD", - oneYear: "1Y", - threeYear: "3Y", - all: "ALL", + oneDay: `1${i18next.t("datelocale.d")}`, + oneWeek: `1${i18next.t("datelocale.w")}`, + oneMonth: `1${i18next.t("datelocale.M")}`, + threeMonths: `3${i18next.t("datelocale.M")}`, + yearToDate: i18next.t("datelocale.ytd"), + oneYear: `1${i18next.t("datelocale.y")}`, + threeYear: `3${i18next.t("datelocale.y")}`, + all: i18next.t("navigation.general.all"), } as const; type TRangeKeys = keyof typeof CHART_RANGE_OPTIONS; export type TChartRange = (typeof CHART_RANGE_OPTIONS)[TRangeKeys]; diff --git a/packages/frontend/src/api/utils/dateUtils.ts b/packages/frontend/src/api/utils/dateUtils.ts index 7ec02d04..7ce7f593 100644 --- a/packages/frontend/src/api/utils/dateUtils.ts +++ b/packages/frontend/src/api/utils/dateUtils.ts @@ -6,22 +6,23 @@ import moment from "moment"; * @param date | date-string * @returns string */ + export const computeDuration = (date: string | Date): string => { moment.updateLocale("en", { relativeTime: { - future: i18next.t("datelocale.future"), // this shouldn't occur If it does there's an error. - past: i18next.t("datelocale.past"), - s: i18next.t("datelocale.s"), - m: i18next.t("datelocale.m"), - mm: i18next.t("datelocale.mm"), - h: i18next.t("datelocale.h"), - hh: i18next.t("datelocale.hh"), - d: i18next.t("datelocale.d"), - dd: i18next.t("datelocale.dd"), - M: i18next.t("datelocale.M"), - MM: i18next.t("datelocale.MM"), - y: i18next.t("datelocale.y"), - yy: i18next.t("datelocale.yy"), + future: `%s${i18next.t("datelocale.future")}`, // this shouldn't occur If it does there's an error. + past: `%s${i18next.t("datelocale.past")}`, + s: `%d${i18next.t("datelocale.s")}`, + m: `%d${i18next.t("datelocale.m")}`, + mm: `%d${i18next.t("datelocale.mm")}`, + h: `%d${i18next.t("datelocale.h")}`, + hh: `%d${i18next.t("datelocale.hh")}`, + d: `%d${i18next.t("datelocale.d")}`, + dd: `%d${i18next.t("datelocale.dd")}`, + M: `%d${i18next.t("datelocale.M")}`, + MM: `%d${i18next.t("datelocale.MM")}`, + y: `%d${i18next.t("datelocale.y")}`, + yy: `%d${i18next.t("datelocale.yy")}`, }, }); diff --git a/packages/frontend/src/components/market/CoinInfo.tsx b/packages/frontend/src/components/market/CoinInfo.tsx index ba497810..a14d57ac 100644 --- a/packages/frontend/src/components/market/CoinInfo.tsx +++ b/packages/frontend/src/components/market/CoinInfo.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { twMerge } from "@alphaday/ui-kit"; +import i18next from "i18next"; import { TBaseEntity, TCoin } from "src/api/types"; import { ENumberStyle, formatNumber } from "src/api/utils/format"; import ItemBookmark from "src/components/listItem/ItemBookmark"; @@ -62,7 +63,7 @@ const CoinInfo: FC<{ }).value } - / 24h + / 24{i18next.t("datelocale.h")}
diff --git a/packages/frontend/src/components/market/MarketModule.tsx b/packages/frontend/src/components/market/MarketModule.tsx index ba81df54..c61fd322 100644 --- a/packages/frontend/src/components/market/MarketModule.tsx +++ b/packages/frontend/src/components/market/MarketModule.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { ModuleLoader, Switch, twMerge } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import useHeaderScroll from "src/api/hooks/useHeaderScroll"; import { TChartRange, @@ -8,6 +9,7 @@ import { TBaseEntity, } from "src/api/types"; import { formatNumber, ENumberStyle } from "src/api/utils/format"; +import { evaluateTemplate } from "src/api/utils/textUtils"; import globalMessages from "src/globalMessages"; import CandlestickChart from "./CandlestickChart"; import CoinInfo from "./CoinInfo"; @@ -49,6 +51,7 @@ const MarketModule: FC = ({ onTogglePin, pinnedCoins, }) => { + const { t } = useTranslation(); const { width, squareRef, @@ -68,14 +71,16 @@ const MarketModule: FC = ({ if (selectedMarket === undefined) { chartComponent = (
- No coins with selected tags + {t("market.no_coins_selected")}
); } else if (priceHistoryData === undefined && !isLoadingHistory) { chartComponent = (
{globalMessages.error.requestFailed( - `the ${selectedChartRange} history for this coin` + evaluateTemplate(t("market.history_error"), { + selectedChartRange, + }) )}
); @@ -170,7 +175,7 @@ const MarketModule: FC = ({ >
- Market Cap + {t("market.market_cap")} @@ -186,7 +191,7 @@ const MarketModule: FC = ({
- 24 hours volume + {t("market.volume_24h")} diff --git a/packages/frontend/src/components/module-disclaimer/ModuleDisclaimer.tsx b/packages/frontend/src/components/module-disclaimer/ModuleDisclaimer.tsx index 9ac3d224..71007f13 100644 --- a/packages/frontend/src/components/module-disclaimer/ModuleDisclaimer.tsx +++ b/packages/frontend/src/components/module-disclaimer/ModuleDisclaimer.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { Button, ScrollBar, TextOverlay } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import ReactMarkdown from "react-markdown"; import { REMARK_URL_REGEX, remarkRegex } from "src/api/utils/textUtils"; import CONFIG from "src/config"; @@ -23,6 +24,7 @@ const ModuleDisclaimer: FC = ({ onAccept, onReject, }) => { + const { t } = useTranslation(); if (!show) { return null; } @@ -44,7 +46,7 @@ const ModuleDisclaimer: FC = ({ variant="primaryXL" className="ml-4" > - Accept + {t("others.accept")} {onReject && ( )}
diff --git a/packages/frontend/src/components/portfolio/nfts/NftCard.tsx b/packages/frontend/src/components/portfolio/nfts/NftCard.tsx index 88f042de..77e756cc 100644 --- a/packages/frontend/src/components/portfolio/nfts/NftCard.tsx +++ b/packages/frontend/src/components/portfolio/nfts/NftCard.tsx @@ -1,5 +1,6 @@ import { FC, useCallback, useState } from "react"; import { twMerge } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { formatNumber } from "src/api/utils/format"; import { ReactComponent as NoImageSVG } from "src/assets/icons/no-image.svg"; @@ -10,6 +11,7 @@ interface INft { } const NftCard: FC = ({ img, name, value }) => { + const { t } = useTranslation(); const [imgLoadFailed, setImgLoadFailed] = useState(false); const [videoLoadFailed, setVideoLoadFailed] = useState(false); @@ -59,7 +61,7 @@ const NftCard: FC = ({ img, name, value }) => { title="Value in Eth" > - Est. value + {t("others.est_value")}

Ξ {formatNumber({ value }).value} diff --git a/packages/frontend/src/components/portfolio/nfts/NftList.tsx b/packages/frontend/src/components/portfolio/nfts/NftList.tsx index 9d91ccd9..3af6ae58 100644 --- a/packages/frontend/src/components/portfolio/nfts/NftList.tsx +++ b/packages/frontend/src/components/portfolio/nfts/NftList.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { ScrollBar } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TZapperNftAsset } from "src/api/services"; import globalMessages from "src/globalMessages"; import CONFIG from "../../../config"; @@ -30,6 +31,7 @@ const getImage = (data: TZapperNftAsset): string | undefined => { }; const NftList: FC = ({ nftData, widgetHeight, nftsQueryFailed }) => { + const { t } = useTranslation(); const nftCards = nftData.items.map((item) => ( = ({ nftData, widgetHeight, nftsQueryFailed }) => { const message = nftData.items.length === 0 ? (

- No NFTs found for the wallet(s) provided. + {t("messages.no_nfts_found")}
) : ( @@ -62,7 +64,7 @@ const NftList: FC = ({ nftData, widgetHeight, nftsQueryFailed }) => { const error = nftsQueryFailed && (
- {globalMessages.error.requestFailed("your nfts")} + {globalMessages.error.requestFailed(t("others.your_nfts"))}
); diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 1c9ad5e4..527557ee 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -142,6 +142,11 @@ export const translationEN = { title: "MARKET", line: "Line", candlestick: "Candlestick", + no_coins_selected: "No coins with selected tags", + // eslint-disable-next-line no-template-curly-in-string + history_error: "the ${selectedChartRange} history for this coin", + market_cap: "Market Cap", + volume_24h: "Volume 24h", }, podcasts: { channels: "Channels", @@ -162,8 +167,12 @@ export const translationEN = { }, change: "Change", name: "Name", + your_nfts: "Your NFTs", + est_value: "Est. Value", tvl: "TVL", no_items_found: "No Items Found", + accept: "Accept", + decline: "Decline", cookie: { text: "We use essential cookies to make Alphaday work. We'd like to use other cookies to improve and personalize your visit and to analyze our website's performance, but only if you accept.", acceptAll: "Accept All", @@ -198,6 +207,7 @@ export const translationEN = { // eslint-disable-next-line no-template-curly-in-string "This ${boardName} board does not have the required ${SlugToWidgetNameMap[widget_template]} widget, to access this route you need to add the ${SlugToWidgetNameMap[widget_template]} widget to this board and refresh the page.", back_to_home: "Back to Home", + no_nfts_found: "No NFTs found for the wallet(s) provided.", }, success: { title: "Success", @@ -229,18 +239,20 @@ export const translationEN = { }, datelocale: { future: "in %s", - past: "%s ago", - s: "%ds", - m: "%dm", - mm: "%dm", - h: "%dh", - hh: "%dh", - d: "%dd", - dd: "%dd", - M: "%dmo", - MM: "%dmo", - y: "%dy", - yy: "%dy", + past: " ago", + s: "s", + m: "m", + mm: "m", + h: "h", + hh: "h", + d: "d", + dd: "d", + w: "w", + M: "mo", + MM: "mo", + y: "y", + ytd: "ytd", + yy: "y", }, gas: { title: "Gas Price", @@ -395,6 +407,11 @@ export const translationJA: typeof translationEN = { title: "マーケット", line: "ライン", candlestick: "ローソク足", + no_coins_selected: "選択したタグのコインはありません", + // eslint-disable-next-line no-template-curly-in-string + history_error: "このコインの${selectedChartRange}履歴", + market_cap: "時価総額", + volume_24h: "24時間の出来高", }, podcasts: { channels: "チャンネル", @@ -415,8 +432,12 @@ export const translationJA: typeof translationEN = { }, change: "変更", name: "名前", + your_nfts: "あなたのNFT", + est_value: "見積もり価値", tvl: "TVL", no_items_found: "アイテムが見つかりません", + accept: "受け入れる", + decline: "辞退", cookie: { text: "Alphadayを動作させるために必要なクッキーを使用しています。他のクッキーを使用して、訪問を改善し、パーソナライズし、ウェブサイトのパフォーマンスを分析したいと考えていますが、それはあなたが受け入れる場合にのみです。", acceptAll: "すべてを受け入れる", @@ -451,6 +472,8 @@ export const translationJA: typeof translationEN = { // eslint-disable-next-line no-template-curly-in-string "この${boardName}ボードには、${SlugToWidgetNameMap[widget_template]}ウィジェットが必要です。このルートにアクセスするには、${SlugToWidgetNameMap[widget_template]}ウィジェットをこのボードに追加してページを更新する必要があります。", back_to_home: "ホームに戻る", + no_nfts_found: + "指定されたウォレット用のNFTが見つかりませんでした。", }, success: { title: "成功", @@ -483,19 +506,21 @@ export const translationJA: typeof translationEN = { }, }, datelocale: { - future: "%s後", - past: "%s前", - s: "%ds", - m: "%dm", - mm: "%dm", - h: "%dh", - hh: "%dh", - d: "%dd", - dd: "%dd", - M: "%dmo", - MM: "%dmo", - y: "%dy", - yy: "%dy", + future: "後", + past: "前", + s: "秒", + m: "分", + mm: "分", + h: "時間", + hh: "時間", + d: "日", + dd: "日", + w: "週", + M: "ヶ月", + MM: "ヶ月", + y: "年", + yy: "年", + ytd: "今年", }, gas: { title: "ガス価格", From ba7c83955d73502b55f164e5110d23addad6b433 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:26:42 +0100 Subject: [PATCH 19/51] qna --- .../frontend/src/components/qna/QnAModule.tsx | 15 +++++---------- packages/frontend/src/locales/translation.ts | 12 ++++++++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/frontend/src/components/qna/QnAModule.tsx b/packages/frontend/src/components/qna/QnAModule.tsx index 0334d1fa..c4bd8f22 100644 --- a/packages/frontend/src/components/qna/QnAModule.tsx +++ b/packages/frontend/src/components/qna/QnAModule.tsx @@ -1,25 +1,20 @@ import { FC, FormEvent, useEffect, useRef, useState } from "react"; import { Button, ScrollBar, IconButton, ChatForm } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TConversation } from "src/api/types"; import { EToastRole, toast } from "src/api/utils/toastUtils"; import globalMessages from "src/globalMessages"; import QnAGroup from "./ConversationGroup"; const QnAStarter: FC<{ onClick: () => void }> = ({ onClick }) => { + const { t } = useTranslation(); return (
-

- This widget is an interface to Alphaday's aggregated crypto - data. You can query this data by simply typing arbitrary - questions in natural language, like for instance "what is - the project with the highest tvl?" -

-

- You need to connect and verify your wallet to use this widget. -

+

{t("qna.intro")}

+

{t("qna.highlight")}

diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 527557ee..4201fb7c 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -261,6 +261,12 @@ export const translationEN = { slow: "Slow", beacon_chain_data: "Beacon Chain Data", }, + qna: { + intro: "This widget is an interface to Alphaday's aggregated crypto data. You can query this data by simply typing arbitrary questions in natural language, like for instance "what is the project with the highest tvl?"", + highlight: + "You need to connect and verify your wallet to use this widget.", + button: "Ask a question", + }, }; export const translationJA: typeof translationEN = { @@ -529,4 +535,10 @@ export const translationJA: typeof translationEN = { slow: "遅い", beacon_chain_data: "ビーコンチェーンデータ", }, + qna: { + intro: "このウィジェットはAlphadayの集約された暗号データへのインターフェイスです。たとえば、「最高のtvlを持つプロジェクトは何ですか?」など、自然言語で任意の質問を入力してこのデータをクエリできます。", + highlight: + "このウィジェットを使用するには、ウォレットを接続して確認する必要があります。", + button: "質問する", + }, }; From b35d195713d3cd74bda880a72f1b7d54420187aa Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:28:44 +0100 Subject: [PATCH 20/51] summary --- packages/frontend/src/components/summary/SummaryModule.tsx | 4 +++- packages/frontend/src/locales/translation.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/components/summary/SummaryModule.tsx b/packages/frontend/src/components/summary/SummaryModule.tsx index 5fab8c9e..8124cd07 100644 --- a/packages/frontend/src/components/summary/SummaryModule.tsx +++ b/packages/frontend/src/components/summary/SummaryModule.tsx @@ -2,6 +2,7 @@ import { FC } from "react"; import { ModuleLoader } from "@alphaday/ui-kit"; import DOMPurify from "dompurify"; import moment from "moment"; +import { useTranslation } from "react-i18next"; import { TNewsSummary } from "src/api/types"; import CONFIG from "src/config/config"; @@ -53,6 +54,7 @@ const getHighLights = (summary: TNewsSummary) => { }; const SummaryModule: FC = ({ isLoadingSummary, summary }) => { + const { t } = useTranslation(); if (isLoadingSummary || summary === undefined) { return ( = ({ isLoadingSummary, summary }) => {

- Briefing for{" "} + {t("others.briefing_for")}{" "} {moment(summary.updated_at).format("Do MMMM, YYYY")}

diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 4201fb7c..78a6a01c 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -173,6 +173,7 @@ export const translationEN = { no_items_found: "No Items Found", accept: "Accept", decline: "Decline", + briefing_for: "Briefing for", cookie: { text: "We use essential cookies to make Alphaday work. We'd like to use other cookies to improve and personalize your visit and to analyze our website's performance, but only if you accept.", acceptAll: "Accept All", @@ -444,6 +445,7 @@ export const translationJA: typeof translationEN = { no_items_found: "アイテムが見つかりません", accept: "受け入れる", decline: "辞退", + briefing_for: "ブリーフィング", cookie: { text: "Alphadayを動作させるために必要なクッキーを使用しています。他のクッキーを使用して、訪問を改善し、パーソナライズし、ウェブサイトのパフォーマンスを分析したいと考えていますが、それはあなたが受け入れる場合にのみです。", acceptAll: "すべてを受け入れる", From 37f4aeb778335f57a26021d22d9650513b1747f3 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:31:56 +0100 Subject: [PATCH 21/51] video --- packages/frontend/src/components/video/VideoPlayer.tsx | 6 ++++-- packages/frontend/src/locales/translation.ts | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/video/VideoPlayer.tsx b/packages/frontend/src/components/video/VideoPlayer.tsx index 9fa4e625..84317382 100644 --- a/packages/frontend/src/components/video/VideoPlayer.tsx +++ b/packages/frontend/src/components/video/VideoPlayer.tsx @@ -1,5 +1,6 @@ import { FC, useMemo } from "react"; import { Button } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import useElementSize from "src/api/hooks/useElementSize"; import { TVideoItem } from "src/api/types"; import { computeDuration } from "src/api/utils/dateUtils"; @@ -23,6 +24,7 @@ const VideoPlayer: FC = ({ isAuthenticated, isFullSize, }) => { + const { t } = useTranslation(); const [ setVideoPlayerWrapRef, { width: videoPlayerWrapWidth, height: videoPlayerWrapHeight }, @@ -49,7 +51,7 @@ const VideoPlayer: FC = ({ if (video === null) { return (
- No Video Selected + {t("messages.error.no_video")}
); } @@ -57,7 +59,7 @@ const VideoPlayer: FC = ({ if (!video) { return (
- Something went wrong. + {t("messages.error.something_wrong")}
); } diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 78a6a01c..1335fd2b 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -209,6 +209,8 @@ export const translationEN = { "This ${boardName} board does not have the required ${SlugToWidgetNameMap[widget_template]} widget, to access this route you need to add the ${SlugToWidgetNameMap[widget_template]} widget to this board and refresh the page.", back_to_home: "Back to Home", no_nfts_found: "No NFTs found for the wallet(s) provided.", + no_video: "No Video Selected", + something_wrong: "Something went wrong.", }, success: { title: "Success", @@ -482,6 +484,8 @@ export const translationJA: typeof translationEN = { back_to_home: "ホームに戻る", no_nfts_found: "指定されたウォレット用のNFTが見つかりませんでした。", + no_video: "ビデオが選択されていません", + something_wrong: "何かが間違っています。", }, success: { title: "成功", From 53b8f016ca61e40c3373809ad356014662af7073 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:46:24 +0100 Subject: [PATCH 22/51] translate about us --- .../frontend/src/components/AboutUsModal.tsx | 51 ++++++++--------- packages/frontend/src/locales/translation.ts | 56 +++++++++++++++++++ 2 files changed, 80 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/components/AboutUsModal.tsx b/packages/frontend/src/components/AboutUsModal.tsx index 9906a8c4..7d2ec5bd 100644 --- a/packages/frontend/src/components/AboutUsModal.tsx +++ b/packages/frontend/src/components/AboutUsModal.tsx @@ -6,95 +6,92 @@ import { ModalHeader, ModalTitle, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; interface IProps { showModal: boolean; onClose?: () => void; } + export const AboutUsModal: React.FC = ({ showModal, onClose }) => { + const { t } = useTranslation(); return ( - About Us + {t("about_us.title")} -
Company Overview:
+
{t("about_us.company_overview.title")}

- Registered Name: Alphabox Solutions Pte. Ltd. + {t("about_us.company_overview.registered_name")}
- Registration Number: 202136261C + {t("about_us.company_overview.registration_number")}
- Registered Office: 45 North Canal Road #01-01 Lew Building - Singapore + {t("about_us.company_overview.registered_office")}

-
Contact Information:
+
{t("about_us.contact_info.title")}

- Email Address:{" "} + {t("about_us.contact_info.email")}{" "} hello@alphaday.com
- X.com:{" "} + {t("about_us.contact_info.xcom")}{" "} https://x.com/AlphadayHQ

-
Legal Information:
+
{t("about_us.legal_info.title")}

- Terms & Conditions:{" "} + {t("about_us.legal_info.terms")}{" "} https://alphaday.com/terms
- Privacy Policy:{" "} + {t("about_us.legal_info.privacy")}{" "} https://alphaday.com/privacy

-
Additional Resources:
+
{t("about_us.additional_resources.title")}

- FAQs:{" "} + {t("about_us.additional_resources.faqs")}{" "} alphaday.com
- Feedback:{" "} + {t("about_us.additional_resources.feedback")}{" "} https://forms.gle/RbrrLGdFPAeuNJhk9

-

- Alphaday's mission is to bring you all the tools needed - to follow your favorite projects, stay up-to-date with the - latest narratives, and use your favorite dapps, all from the - comfort of one easy-to-use customizable dashboard. -

+

{t("about_us.mission")}

diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 1335fd2b..02a4e5dd 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -270,6 +270,34 @@ export const translationEN = { "You need to connect and verify your wallet to use this widget.", button: "Ask a question", }, + about_us: { + title: "About Us", + company_overview: { + title: "Company Overview:", + registered_name: "Registered Name: Alphabox Solutions Pte. Ltd.", + registration_number: "Registration Number: 202136261C", + registered_office: + "Registered Office: 45 North Canal Road #01-01 Lew Building Singapore", + }, + contact_info: { + title: "Contact Information:", + email: "Email Address: hello@alphaday.com", + xcom: "X.com: https://x.com/AlphadayHQ", + }, + legal_info: { + title: "Legal Information:", + terms: "Terms & Conditions: https://alphaday.com/terms", + privacy: "Privacy Policy: https://alphaday.com/privacy", + }, + additional_resources: { + title: "Additional Resources:", + faqs: "FAQs: alphaday.com", + feedback: "Feedback: https://forms.gle/RbrrLGdFPAeuNJhk9", + }, + mission: + "Alphaday's mission is to bring you all the tools needed to follow your favorite projects, stay up-to-date with the latest narratives, and use your favorite dapps, all from the comfort of one easy-to-use customizable dashboard.", + close_button: "Close", + }, }; export const translationJA: typeof translationEN = { @@ -547,4 +575,32 @@ export const translationJA: typeof translationEN = { "このウィジェットを使用するには、ウォレットを接続して確認する必要があります。", button: "質問する", }, + about_us: { + title: "会社概要", + company_overview: { + title: "会社情報:", + registered_name: "登録社名: Alphabox Solutions Pte. Ltd.", + registration_number: "登録番号: 202136261C", + registered_office: + "登録所在地: 45 North Canal Road #01-01 Lew Building Singapore", + }, + contact_info: { + title: "お問い合わせ先:", + email: "メールアドレス: hello@alphaday.com", + xcom: "X.com: https://x.com/AlphadayHQ", + }, + legal_info: { + title: "法的情報:", + terms: "利用規約: https://alphaday.com/terms", + privacy: "プライバシーポリシー: https://alphaday.com/privacy", + }, + additional_resources: { + title: "その他のリソース:", + faqs: "よくある質問: alphaday.com", + feedback: "フィードバック: https://forms.gle/RbrrLGdFPAeuNJhk9", + }, + mission: + "Alphadayは、お気に入りのプロジェクトをフォローし、最新の情報を常に把握し、使いやすいカスタマイズ可能なダッシュボードから好きなdappsを使用するために必要なすべてのツールを提供することを使命としています。", + close_button: "閉じる", + }, }; From ea47a8bcb6ed2660cfa59457135a408de226607e Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 15:57:25 +0100 Subject: [PATCH 23/51] calendar categories --- .../src/components/calendarCategories.ts | 37 +++++++++--------- packages/frontend/src/locales/translation.ts | 38 +++++++++++++++++++ 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/packages/frontend/src/components/calendarCategories.ts b/packages/frontend/src/components/calendarCategories.ts index 0bf2442b..7c210bbd 100644 --- a/packages/frontend/src/components/calendarCategories.ts +++ b/packages/frontend/src/components/calendarCategories.ts @@ -1,96 +1,97 @@ +import i18next from "i18next"; import { TEventCategory } from "./types"; export const typeOptions: { value: string; name: string; color: string }[] = [ { value: "Co", - name: "Conferences", + name: i18next.t("calendar.event_types.conferences"), color: "rgb(185, 225, 135)", }, { value: "MU", - name: "Meetups", + name: i18next.t("calendar.event_types.meetups"), color: "rgb(117, 71, 247)", }, { value: "Hk", - name: "Hackathons", + name: i18next.t("calendar.event_types.hackathons"), color: "rgb(162, 117, 84)", }, { value: "PR", - name: "Product Releases", + name: i18next.t("calendar.event_types.product_releases"), color: "rgb(249, 132, 104)", }, { value: "DC", - name: "Dev Calls", + name: i18next.t("calendar.event_types.developer_conferences"), color: "rgb(224, 135, 135)", }, { value: "ICO", - name: "Initial Coin Offerings", + name: i18next.t("calendar.event_types.icos"), color: "rgb(144, 190, 109)", }, { value: "IDO", - name: "Initial Dex Offerings", + name: i18next.t("calendar.event_types.idos"), color: "rgb(67, 170, 139)", }, { value: "DV", - name: "DAO Votes", + name: i18next.t("calendar.event_types.dev_updates"), color: "rgb(77, 144, 142)", }, { value: "EE", - name: "Economic Events", + name: i18next.t("calendar.event_types.exchange_events"), color: "rgb(87, 117, 144)", }, { value: "CC", - name: "Community Calls", + name: i18next.t("calendar.event_types.community_calls"), color: "rgb(39, 125, 161)", }, { value: "SF", - name: "Soft Forks", + name: i18next.t("calendar.event_types.soft_forks"), color: "rgb(253, 153, 153)", }, { value: "HF", - name: "Hard Forks", + name: i18next.t("calendar.event_types.hard_forks"), color: "rgb(198, 179, 14)", }, { value: "EDU", - name: "Education & Learning", + name: i18next.t("calendar.event_types.education"), color: "rgb(71, 127, 247)", }, { value: "INT", - name: "Interviews", + name: i18next.t("calendar.event_types.interviews"), color: "rgb(17, 157, 164)", }, { value: "PY", - name: "Partys", + name: i18next.t("calendar.event_types.partnerships"), color: "rgb(216, 227, 118)", }, { value: "WK", - name: "Workshops", + name: i18next.t("calendar.event_types.workshops"), color: "rgb(126, 74, 15)", }, { value: "Unfiltered", - name: "Unfiltered", + name: i18next.t("calendar.event_types.unfiltered"), color: "rgb(17, 78, 198)", }, ]; export const defaultEventCategory: TEventCategory = { value: "Unfiltered", - label: "Unfiltered", + label: i18next.t("calendar.event_types.unfiltered"), category: "Unfiltered", color: "rgb(17, 78, 198)", }; diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 02a4e5dd..9d7cb982 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -159,6 +159,25 @@ export const translationEN = { speakers: "Speakers", more_details: "More Details", noEvents: "No upcoming events found", + event_types: { + conferences: "Conferences", + meetups: "Meetups", + hackathons: "Hackathons", + product_releases: "Product Releases", + dev_calls: "Dev Calls", + ico: "Initial Coin Offerings", + ido: "Initial Dex Offerings", + dao_votes: "DAO Votes", + economic_events: "Economic Events", + community_calls: "Community Calls", + soft_forks: "Soft Forks", + hard_forks: "Hard Forks", + education: "Education & Learning", + interviews: "Interviews", + parties: "Parties", + workshops: "Workshops", + unfiltered: "Unfiltered", + }, }, others: { tag_options: { @@ -461,6 +480,25 @@ export const translationJA: typeof translationEN = { speakers: "スピーカー", more_details: "詳細", noEvents: "近日開催されるイベントはありませ", + event_types: { + conferences: "カンファレンス", + meetups: "ミートアップ", + hackathons: "ハッカソン", + product_releases: "製品リリース", + dev_calls: "開発者ミーティング", + ico: "新規仮想通貨公開", + ido: "分散型取引所による新規公開", + dao_votes: "DAO投票", + economic_events: "経済イベント", + community_calls: "コミュニティミーティング", + soft_forks: "ソフトフォーク", + hard_forks: "ハードフォーク", + education: "教育・学習", + interviews: "インタビュー", + parties: "パーティー", + workshops: "ワークショップ", + unfiltered: "未分類", + }, }, others: { tag_options: { From 8723f0abbfdeb0f952fa78c7518b97a629a7ca5b Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 16:09:28 +0100 Subject: [PATCH 24/51] error page --- .../src/containers/error/ErrorContainer.tsx | 48 ++++++---- packages/frontend/src/locales/translation.ts | 96 +++++++++++++++++++ 2 files changed, 123 insertions(+), 21 deletions(-) diff --git a/packages/frontend/src/containers/error/ErrorContainer.tsx b/packages/frontend/src/containers/error/ErrorContainer.tsx index ba4c91a3..28797147 100644 --- a/packages/frontend/src/containers/error/ErrorContainer.tsx +++ b/packages/frontend/src/containers/error/ErrorContainer.tsx @@ -1,8 +1,11 @@ import React from "react"; +import i18next from "i18next"; import { useGetRemoteStatusQuery } from "src/api/services"; import { isNumber } from "src/api/utils/helpers"; import GeneralError from "src/components/error/GeneralError"; +const t = i18next.t.bind(i18next); + const getErrorMessage = ({ status, }: { @@ -12,12 +15,13 @@ const getErrorMessage = ({ return ( <>

- You're{" "} - offline + {t("error_page.offline.heading.text")}{" "} + + {t("error_page.offline.heading.highlight")} +

- Looks like you lost your connection. Please check it and try - again. + {t("error_page.offline.description")}

); @@ -27,25 +31,24 @@ const getErrorMessage = ({ return ( <>

- System{" "} + {t("error_page.503.heading.text")}{" "} - maintenance + {t("error_page.503.heading.highlight")}

- We are performing some scheduled maintenance at the moment. - We'll be back up shortly! Meanwhile, you can check our{" "} + {t("error_page.503.description1.text")}{" "} - twitter + {t("error_page.503.description1.link.text")} .

- And make sure to check back again later. + {t("error_page.503.description2")}

); @@ -55,11 +58,13 @@ const getErrorMessage = ({ return ( <>

- unauthorised{" "} - 403 + {t("error_page.403.heading.text")}{" "} + + {t("error_page.403.heading.highlight")} +

- You don't have permissions to access this page. + {t("error_page.403.description")}

); @@ -69,10 +74,12 @@ const getErrorMessage = ({ return ( <>

- 404 + + {t("error_page.404.heading.highlight")} +

- Sorry, the page you are looking for could not be found. + {t("error_page.404.description")}

); @@ -86,17 +93,16 @@ const getErrorMessage = ({ )}

- Something went wrong, we'll be back up shortly! Meanwhile, - you can check our{" "} + {t("error_page.default.description.text")}{" "} - twitter + {t("error_page.default.description.link.text")} {" "} - for updates. + {t("error_page.default.description.textAfterLink")}

); diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 9d7cb982..8ebeb5c0 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -317,6 +317,54 @@ export const translationEN = { "Alphaday's mission is to bring you all the tools needed to follow your favorite projects, stay up-to-date with the latest narratives, and use your favorite dapps, all from the comfort of one easy-to-use customizable dashboard.", close_button: "Close", }, + error_page: { + offline: { + heading: { + text: "You're", + highlight: "offline", + }, + description: + "Looks like you lost your connection. Please check it and try again.", + }, + "503": { + heading: { + text: "System", + highlight: "maintenance", + }, + description1: { + text: "We are performing some scheduled maintenance at the moment. We'll be back up shortly! Meanwhile, you can check our", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + }, + description2: "And make sure to check back again later.", + }, + "403": { + heading: { + text: "unauthorised", + highlight: "403", + }, + description: "You don't have permissions to access this page.", + }, + "404": { + heading: { + highlight: "404", + }, + description: + "Sorry, the page you are looking for could not be found.", + }, + default: { + description: { + text: "Something went wrong, we'll be back up shortly! Meanwhile, you can check our", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + textAfterLink: "for updates.", + }, + }, + }, }; export const translationJA: typeof translationEN = { @@ -641,4 +689,52 @@ export const translationJA: typeof translationEN = { "Alphadayは、お気に入りのプロジェクトをフォローし、最新の情報を常に把握し、使いやすいカスタマイズ可能なダッシュボードから好きなdappsを使用するために必要なすべてのツールを提供することを使命としています。", close_button: "閉じる", }, + error_page: { + offline: { + heading: { + text: "オフラインです", + highlight: "", + }, + description: + "接続が切れたようです。接続を確認して、もう一度お試しください。", + }, + "503": { + heading: { + text: "システム", + highlight: "メンテナンス", + }, + description1: { + text: "現在、定期メンテナンスを実施しています。すぐに戻ります!その間、", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + }, + description2: "をチェックしてください。", + }, + "403": { + heading: { + text: "未承認", + highlight: "403", + }, + description: "このページにアクセスする権限がありません。", + }, + "404": { + heading: { + highlight: "404", + }, + description: + "申し訳ありませんが、お探しのページが見つかりませんでした。", + }, + default: { + description: { + text: "何かが間違ってしまいました。すぐに戻ります!その間、", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + textAfterLink: "をチェックしてください。", + }, + }, + }, }; From 478c1542a522ee30804860f01bb4165a7a3cfd7b Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 16:17:38 +0100 Subject: [PATCH 25/51] wallet_view --- .../header/profile-dropdown/WalletViewButton.tsx | 9 +++++---- packages/frontend/src/locales/translation.ts | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/containers/header/profile-dropdown/WalletViewButton.tsx b/packages/frontend/src/containers/header/profile-dropdown/WalletViewButton.tsx index 259f3c74..f20bbc0a 100644 --- a/packages/frontend/src/containers/header/profile-dropdown/WalletViewButton.tsx +++ b/packages/frontend/src/containers/header/profile-dropdown/WalletViewButton.tsx @@ -1,5 +1,6 @@ import { FC } from "react"; import { Button, Spinner, twMerge } from "@alphaday/ui-kit"; +import i18next from "i18next"; import { EWalletViewState } from "src/api/types"; import { getWalletViewStateMessages, @@ -17,14 +18,14 @@ interface IWalletViewButton { const viewButtonChild: { [key in EWalletViewState]: JSX.Element } = { [EWalletViewState.Ready]: ( - View wallet board + {i18next.t("wallet_view.view_wallet_board")} ), [EWalletViewState.Fetching]: ( <> - Creating wallet board + {i18next.t("wallet_view.creating_wallet_board")} ), @@ -35,7 +36,7 @@ const viewButtonChild: { [key in EWalletViewState]: JSX.Element } = { <> - Create wallet board + {i18next.t("wallet_view.create_wallet_board")} ), @@ -43,7 +44,7 @@ const viewButtonChild: { [key in EWalletViewState]: JSX.Element } = { <> - Create wallet board + {i18next.t("wallet_view.create_wallet_board")} ), diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 8ebeb5c0..13603d2d 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -365,6 +365,11 @@ export const translationEN = { }, }, }, + wallet_view: { + create_wallet_board: "Create Wallet Board", + view_wallet_board: "View Wallet Board", + creating_wallet_board: "Creating Wallet Board", + }, }; export const translationJA: typeof translationEN = { @@ -737,4 +742,9 @@ export const translationJA: typeof translationEN = { }, }, }, + wallet_view: { + create_wallet_board: "ウォレットボードを作成", + view_wallet_board: "ウォレットボードを表示", + creating_wallet_board: "ウォレットボードを作成中", + }, }; From 3963194d3737d0d5850af486be01fdac70730969 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 22 Nov 2024 16:33:59 +0100 Subject: [PATCH 26/51] terns of service --- .../src/containers/uniswap/termsOfService.tsx | 10 +++++---- packages/frontend/src/locales/translation.ts | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/containers/uniswap/termsOfService.tsx b/packages/frontend/src/containers/uniswap/termsOfService.tsx index fcd7d12a..451108de 100644 --- a/packages/frontend/src/containers/uniswap/termsOfService.tsx +++ b/packages/frontend/src/containers/uniswap/termsOfService.tsx @@ -1,11 +1,13 @@ +import i18next from "i18next"; + export const termsOfService = ` -#### Legal Disclaimer +#### ${i18next.t("terms_of_service.titleOne")} -Alphaday is not responsible for the operations or performance of third-party platforms and widgets, including Uniswap. The Uniswap Swap Widget is provided as a convenience for our users. Alphaday does not control or manage transactions made through Uniswap, and we are not responsible for any losses or damages incurred as a result of using the Uniswap Swap Widget. Users are encouraged to do their own research and exercise caution when trading cryptocurrencies. By using the Uniswap Swap Widget, you agree to Uniswap Lab's [__Terms of Service__](https://uniswap.org/terms-of-service) and [__Privacy Policy__](https://uniswap.org/privacy-policy). +${i18next.t("terms_of_service.text_one")} [__${i18next.t("terms_of_service.text_two")}__](https://uniswap.org/terms-of-service) ${i18next.t("terms_of_service.text_three")} [__${i18next.t("terms_of_service.text_four")}__](https://uniswap.org/privacy-policy). -#### Risk Disclosure +#### ${i18next.t("terms_of_service.titleTwo")} -Cryptocurrency trading involves significant risk and may result in the loss of your invested capital. You should not invest more than you can afford to lose and should ensure that you fully understand the risks involved. Price volatility and the global nature of the cryptocurrency market may lead to significant losses. Alphaday does not provide any investment advice or recommendations regarding the suitability of any cryptocurrency transactions. All trading decisions are made by users and not Alphaday. Please consult with a financial advisor before making any trading decisions. +${i18next.t("terms_of_service.text_five")} `; export default termsOfService; diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 13603d2d..26194890 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -370,6 +370,17 @@ export const translationEN = { view_wallet_board: "View Wallet Board", creating_wallet_board: "Creating Wallet Board", }, + terms_of_service: { + titleOne: "Legal Disclaimer", + text_one: + "Alphaday is not responsible for the operations or performance of third-party platforms and widgets, including Uniswap. The Uniswap Swap Widget is provided as a convenience for our users. Alphaday does not control or manage transactions made through Uniswap, and we are not responsible for any losses or damages incurred as a result of using the Uniswap Swap Widget. Users are encouraged to do their own research and exercise caution when trading cryptocurrencies. By using the Uniswap Swap Widget, you agree to Uniswap Lab's", + text_two: "Terms of Service", + text_three: "and", + text_four: "Privacy Policy", + titleTwo: "Risk Disclosure", + text_five: + "Cryptocurrency trading involves significant risk and may result in the loss of your invested capital. You should not invest more than you can afford to lose and should ensure that you fully understand the risks involved. Price volatility and the global nature of the cryptocurrency market may lead to significant losses. Alphaday does not provide any investment advice or recommendations regarding the suitability of any cryptocurrency transactions. All trading decisions are made by users and not Alphaday. Please consult with a financial advisor before making any trading decisions.", + }, }; export const translationJA: typeof translationEN = { @@ -747,4 +758,15 @@ export const translationJA: typeof translationEN = { view_wallet_board: "ウォレットボードを表示", creating_wallet_board: "ウォレットボードを作成中", }, + terms_of_service: { + titleOne: "法的免責事項", + text_one: + "Alphadayは、Uniswapを含むサードパーティプラットフォームやウィジェットの操作やパフォーマンスについて責任を負いません。Uniswapスワップウィジェットは、ユーザーの便宜のために提供されています。AlphadayはUniswapを介した取引を制御または管理せず、Uniswap Swapウィジェットを使用することによって生じた損失や損害について責任を負いません。ユーザーは、暗号通貨の取引を行う際には自己の調査を行い、注意を払うことが推奨されます。Uniswap Swapウィジェットを使用することで、Uniswap Labの", + text_two: "利用規約", + text_three: "および", + text_four: "プライバシーポリシー", + titleTwo: "リスク開示", + text_five: + "暗号通貨の取引には大きなリスクが伴い、投資した資本を失う可能性があります。失っても支障のない範囲でのみ投資を行い、関連するリスクを十分に理解していることを確認してください。価格の変動性や暗号通貨市場のグローバルな性質により、大きな損失が発生する可能性があります。Alphadayは、暗号通貨取引の適合性に関する投資アドバイスや推奨を提供していません。すべての取引の決定はユーザーによって行われ、Alphadayは関与しません。取引の決定を行う前に、金融アドバイザーに相談してください。", + }, }; From f7fbcc3a2c79155661cbf62e6e2e90b135f0911e Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 25 Nov 2024 16:26:45 +0100 Subject: [PATCH 27/51] add mroe translations --- packages/frontend/src/components/calendar/CalendarMonth.tsx | 6 +++++- packages/frontend/src/locales/translation.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/calendar/CalendarMonth.tsx b/packages/frontend/src/components/calendar/CalendarMonth.tsx index 8aa7d43f..f6333452 100644 --- a/packages/frontend/src/components/calendar/CalendarMonth.tsx +++ b/packages/frontend/src/components/calendar/CalendarMonth.tsx @@ -6,6 +6,7 @@ import { CalendarMonth as CalMonth, twMerge, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { TEvent } from "src/api/types"; import { getEventCategoryByType } from "src/api/utils/calendarUtils"; import { ReactComponent as ArrowUpSVG } from "src/assets/icons/arrow-up.svg"; @@ -41,6 +42,7 @@ const CalendarMonth: FC< onDatesSet, widgetHash, }) => { + const { t } = useTranslation(); const [isAlphaModalOpen, setisAlphaModalOpen] = useState(false); const [showAllLegends, setShowAllLegends] = useState(false); @@ -131,7 +133,9 @@ const CalendarMonth: FC< className="flex m-[3px_5.5px_3px_0] p-[0_3.5px_0.5px_1px] min-w-max items-center cursor-pointer rounded-sm hover:text-primary text-accentVariant100" onClick={() => setShowAllLegends((show) => !show)} > - {showAllLegends ? "less" : "more"}{" "} + {showAllLegends + ? t("navigation.general.less") + : t("navigation.general.more")}{" "} Date: Mon, 25 Nov 2024 16:45:50 +0100 Subject: [PATCH 28/51] add migration --- packages/frontend/src/api/store/migrations.ts | 19 ++++++++++++++++++- packages/frontend/src/api/store/slices/ui.ts | 6 ++++++ packages/frontend/src/config/config.ts | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/api/store/migrations.ts b/packages/frontend/src/api/store/migrations.ts index 851fe04c..262fd53c 100644 --- a/packages/frontend/src/api/store/migrations.ts +++ b/packages/frontend/src/api/store/migrations.ts @@ -38,7 +38,13 @@ type PersistedRootState = (PersistedState & RootState) | undefined; * 102: (s: RootStateV101) => PersistedRootState */ -type RootStateV106 = PersistedRootState; +type RootStateV107 = PersistedRootState; +type RootStateV106 = + | (PersistedState & + Omit & { + ui: Omit; + }) + | undefined; type RootStateV105 = | (PersistedState & @@ -111,6 +117,7 @@ type TMigrations = MigrationManifest & { 104: (s: RootStateV103) => RootStateV104; 105: (s: RootStateV104) => RootStateV105; 106: (s: RootStateV105) => RootStateV106; + 107: (s: RootStateV106) => RootStateV107; }; /** @@ -280,6 +287,16 @@ const migrations: TMigrations = { }, }; }, + 107: (s: RootStateV106): RootStateV107 => { + if (!s) return undefined; + return { + ...s, + ui: { + ...s.ui, + showLanguageModal: false, + }, + }; + }, }; export default migrations; diff --git a/packages/frontend/src/api/store/slices/ui.ts b/packages/frontend/src/api/store/slices/ui.ts index 6003917f..158d921d 100644 --- a/packages/frontend/src/api/store/slices/ui.ts +++ b/packages/frontend/src/api/store/slices/ui.ts @@ -11,6 +11,7 @@ export interface IUIState { showWidgetLib: boolean; showBalance: boolean; showAboutModal: boolean; + showLanguageModal: boolean; tutorial: ITutorialState; cookieChoice: ECookieChoice | undefined; mobile: { @@ -26,6 +27,7 @@ const initialState: IUIState = { theme: "dark", showWidgetLib: false, showAboutModal: false, + showLanguageModal: false, showBalance: true, tutorial: { showTutorial: undefined, currentTutorialTip: undefined }, cookieChoice: undefined, @@ -58,6 +60,9 @@ const uiSlice = createSlice({ toggleAboutModal(draft) { draft.showAboutModal = !draft.showAboutModal; }, + toggleLanguageModal(draft) { + draft.showLanguageModal = !draft.showLanguageModal; + }, toggleWidgetsNavOpen(draft) { draft.mobile.widgetsNavOpen = !draft.mobile.widgetsNavOpen; }, @@ -105,6 +110,7 @@ export const { toggleShowWidgetLib, toggleShowBalance, toggleAboutModal, + toggleLanguageModal, toggleWidgetsNavOpen, setStoreShowTutorial, setCurrentTutorialTip, diff --git a/packages/frontend/src/config/config.ts b/packages/frontend/src/config/config.ts index cf57d53e..fd42d442 100644 --- a/packages/frontend/src/config/config.ts +++ b/packages/frontend/src/config/config.ts @@ -104,7 +104,7 @@ const CONFIG = { APP: { VERSION: import.meta.env.VITE_VERSION || "", STORAGE_KEY: "alphaday", - STORAGE_VERSION: 106, + STORAGE_VERSION: 107, COMMIT: import.meta.env.VITE_COMMIT, COMMIT_TIMESTAMP: import.meta.env.VITE_COMMIT_TS || "", X_APP_ID: import.meta.env.VITE_X_APP_ID || "", From 387822fa823e050db91133ee44d5035aa6227bb4 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 25 Nov 2024 17:15:25 +0100 Subject: [PATCH 29/51] clean up trnsl --- packages/frontend/src/containers/base/BaseContainerMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/containers/base/BaseContainerMenu.tsx b/packages/frontend/src/containers/base/BaseContainerMenu.tsx index a24c29dd..10e7b8b8 100644 --- a/packages/frontend/src/containers/base/BaseContainerMenu.tsx +++ b/packages/frontend/src/containers/base/BaseContainerMenu.tsx @@ -156,7 +156,7 @@ const BaseContainerMenu: FC = ({ />
{isWidgetOptions - ? t("navigation.close_options") + ? t("widget.close_options") : t("widget.options")}
From ddfa379b04241402e05c6ba72d7f0c9c0169fbeb Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 25 Nov 2024 19:21:04 +0100 Subject: [PATCH 30/51] Add language switching --- packages/frontend/src/App.tsx | 2 + .../src/api/hooks/usePreferredLanguage.ts | 14 +++ packages/frontend/src/api/store/migrations.ts | 4 +- packages/frontend/src/api/store/slices/ui.ts | 13 +++ packages/frontend/src/api/types/language.ts | 6 ++ .../frontend/src/components/LanguageModal.tsx | 95 +++++++++++++++++++ .../src/containers/LanguageModalContainer.tsx | 31 ++++++ .../ProfileDropdownContainer.tsx | 4 +- .../ProfileDropdownWrapper.tsx | 8 ++ packages/frontend/src/locales/translation.ts | 10 ++ packages/frontend/src/pages/index.tsx | 2 + 11 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 packages/frontend/src/api/hooks/usePreferredLanguage.ts create mode 100644 packages/frontend/src/api/types/language.ts create mode 100644 packages/frontend/src/components/LanguageModal.tsx create mode 100644 packages/frontend/src/containers/LanguageModalContainer.tsx diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index 4aa9cc90..bc814ee5 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -12,6 +12,7 @@ import { useViewRoute, useGaTracker, } from "./api/hooks"; +import { usePreferredLanguage } from "./api/hooks/usePreferredLanguage"; import { useGetRemoteStatusQuery } from "./api/services"; import { useAppDispatch } from "./api/store/hooks"; import walletConnectProvider from "./api/store/providers/wallet-connect-provider"; @@ -31,6 +32,7 @@ const goToLandingPage = () => { const AppRoutes = () => { useGaTracker(); + usePreferredLanguage(); const dispatch = useAppDispatch(); const { error } = useGetRemoteStatusQuery(undefined, { diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts new file mode 100644 index 00000000..6c72983d --- /dev/null +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -0,0 +1,14 @@ +import i18next from "i18next"; +import { useAppSelector } from "../store/hooks"; +import { Logger } from "../utils/logging"; + +export const usePreferredLanguage = () => { + const selectedCode = useAppSelector( + (state) => state.ui.selectedLanguageCode + ); + if (selectedCode) { + i18next.changeLanguage(selectedCode).catch((e) => { + Logger.error("usePreferredLanguage::Error changing language::", e); + }); + } +}; diff --git a/packages/frontend/src/api/store/migrations.ts b/packages/frontend/src/api/store/migrations.ts index 262fd53c..81720cf0 100644 --- a/packages/frontend/src/api/store/migrations.ts +++ b/packages/frontend/src/api/store/migrations.ts @@ -9,6 +9,7 @@ import { TUserView, WalletConnectionState, } from "../types"; +import { EnumLanguageCode } from "../types/language"; import { Logger } from "../utils/logging"; import { RootState } from "./reducer"; import { IUIState } from "./slices/ui"; @@ -42,7 +43,7 @@ type RootStateV107 = PersistedRootState; type RootStateV106 = | (PersistedState & Omit & { - ui: Omit; + ui: Omit; }) | undefined; @@ -293,6 +294,7 @@ const migrations: TMigrations = { ...s, ui: { ...s.ui, + selectedLanguageCode: EnumLanguageCode.EN, showLanguageModal: false, }, }; diff --git a/packages/frontend/src/api/store/slices/ui.ts b/packages/frontend/src/api/store/slices/ui.ts index 158d921d..95758744 100644 --- a/packages/frontend/src/api/store/slices/ui.ts +++ b/packages/frontend/src/api/store/slices/ui.ts @@ -1,5 +1,6 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { ECookieChoice, TTutorialTip } from "src/api/types"; +import { EnumLanguageCode } from "src/api/types/language"; export type TTheme = "dark"; export interface ITutorialState { @@ -12,6 +13,7 @@ export interface IUIState { showBalance: boolean; showAboutModal: boolean; showLanguageModal: boolean; + selectedLanguageCode: EnumLanguageCode; tutorial: ITutorialState; cookieChoice: ECookieChoice | undefined; mobile: { @@ -28,6 +30,7 @@ const initialState: IUIState = { showWidgetLib: false, showAboutModal: false, showLanguageModal: false, + selectedLanguageCode: EnumLanguageCode.EN, showBalance: true, tutorial: { showTutorial: undefined, currentTutorialTip: undefined }, cookieChoice: undefined, @@ -66,6 +69,15 @@ const uiSlice = createSlice({ toggleWidgetsNavOpen(draft) { draft.mobile.widgetsNavOpen = !draft.mobile.widgetsNavOpen; }, + setSelectedLanguageCode( + draft, + action: PayloadAction<{ code: EnumLanguageCode }> + ) { + const { + payload: { code }, + } = action; + draft.selectedLanguageCode = code; + }, setStoreShowTutorial(draft, action: PayloadAction<{ show: boolean }>) { const { payload: { show }, @@ -112,6 +124,7 @@ export const { toggleAboutModal, toggleLanguageModal, toggleWidgetsNavOpen, + setSelectedLanguageCode, setStoreShowTutorial, setCurrentTutorialTip, setCookieChoice, diff --git a/packages/frontend/src/api/types/language.ts b/packages/frontend/src/api/types/language.ts new file mode 100644 index 00000000..f9b61f79 --- /dev/null +++ b/packages/frontend/src/api/types/language.ts @@ -0,0 +1,6 @@ +export enum EnumLanguageCode { + EN = "en", + FR = "fr", + ES = "es", + JA = "ja", +} diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx new file mode 100644 index 00000000..c4b739f0 --- /dev/null +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -0,0 +1,95 @@ +import { + Button, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalTitle, + twMerge, +} from "@alphaday/ui-kit"; +import i18next from "i18next"; +import { useTranslation } from "react-i18next"; +import { EnumLanguageCode } from "src/api/types/language"; +import { Logger } from "src/api/utils/logging"; +import { ReactComponent as CheckedSVG } from "src/assets/icons/checkmark.svg"; + +interface IProps { + onSetLanguageCode: (code: EnumLanguageCode) => void; + selectedCode: string; + showModal: boolean; + onClose?: () => void; +} + +const languages = [ + { code: EnumLanguageCode.EN, name: "English", icon: "🏴󠁧󠁢󠁥󠁮󠁧󠁿" }, + { code: EnumLanguageCode.FR, name: "Français", icon: "🇫🇷" }, + { code: EnumLanguageCode.ES, name: "Español", icon: "🇪🇸" }, + { code: EnumLanguageCode.JA, name: "日本語", icon: "🇯🇵" }, +]; + +export const LanguageModal: React.FC = ({ + onSetLanguageCode, + selectedCode, + showModal, + onClose, +}) => { + const { t } = useTranslation(); + + const handleLanguageSelect = async (code: EnumLanguageCode) => { + try { + await i18next.changeLanguage(code); + onSetLanguageCode(code); + onClose?.(); + } catch (error) { + Logger.error( + "handleLanguageSelect::Error changing language::", + error + ); + } + }; + return ( + + + {t("language.title")} + + + + {languages.map(({ code, name, icon }) => ( +
+ + + + +
+ ))} +
+ + + +
+ ); +}; diff --git a/packages/frontend/src/containers/LanguageModalContainer.tsx b/packages/frontend/src/containers/LanguageModalContainer.tsx new file mode 100644 index 00000000..1451bfe0 --- /dev/null +++ b/packages/frontend/src/containers/LanguageModalContainer.tsx @@ -0,0 +1,31 @@ +import { setSelectedLanguageCode, toggleLanguageModal } from "src/api/store"; +import { useAppDispatch, useAppSelector } from "src/api/store/hooks"; +import { EnumLanguageCode } from "src/api/types/language"; +import { LanguageModal } from "src/components/LanguageModal"; + +export const LanguageModalContainer = () => { + const dispatch = useAppDispatch(); + const showModal = useAppSelector((state) => state.ui.showLanguageModal); + const selectedCode = useAppSelector( + (state) => state.ui.selectedLanguageCode + ); + const toggleModal = () => dispatch(toggleLanguageModal()); + const handleSetLanguageCode = (code: EnumLanguageCode) => { + dispatch(setSelectedLanguageCode({ code })); + }; + + const onClose = () => { + if (showModal) { + toggleModal(); + } + }; + + return ( + + ); +}; diff --git a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx index b92458c1..912e2fb7 100644 --- a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx +++ b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; import { useAccount } from "src/api/hooks"; import { useAuth } from "src/api/hooks/useAuth"; import { useTutorial } from "src/api/hooks/useTutorial"; -import { toggleAboutModal } from "src/api/store"; +import { toggleAboutModal, toggleLanguageModal } from "src/api/store"; import { useAppDispatch } from "src/api/store/hooks"; import { ETutorialTipId } from "src/api/types"; import ProfileDropdownWrapper from "./ProfileDropdownWrapper"; @@ -19,11 +19,13 @@ const ProfileDropdownContainer: FC = () => { } = useTutorial(); const toggleAboutUsModal = () => dispatch(toggleAboutModal()); + const onToggleLanguageModal = () => dispatch(toggleLanguageModal()); return ( MaybeAsync; onSignUpSignIn: () => MaybeAsync; + onToggleLanguageModal: () => void; isAuthenticated: boolean; onShowTutorial: (s: boolean) => void; showTutorial: boolean | undefined; @@ -37,6 +38,7 @@ const ProfileDropdownWrapper: React.FC = ({ onSignOut, onSignUpSignIn, onShowTutorial, + onToggleLanguageModal, showTutorial, onShowAboutUsModal, isAuthenticated, @@ -120,6 +122,12 @@ const ProfileDropdownWrapper: React.FC = ({ + + + {t("navigation.menu.language")} + + + {t("navigation.menu.tutorial")}{" "} + ); } From 9af64ca8afcc3defbab8e887f2ceff14625ed390 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 25 Nov 2024 19:33:41 +0100 Subject: [PATCH 31/51] clean up --- .../frontend/src/components/LanguageModal.tsx | 22 ++++++++++--------- yarn.lock | 6 ++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index c4b739f0..b45a339c 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -36,16 +36,18 @@ export const LanguageModal: React.FC = ({ const { t } = useTranslation(); const handleLanguageSelect = async (code: EnumLanguageCode) => { - try { - await i18next.changeLanguage(code); - onSetLanguageCode(code); - onClose?.(); - } catch (error) { - Logger.error( - "handleLanguageSelect::Error changing language::", - error - ); - } + await i18next + .changeLanguage(code) + .then(() => { + onSetLanguageCode(code); + onClose?.(); + }) + .catch((e) => { + Logger.error( + "handleLanguageSelect::Error changing language::", + e + ); + }); }; return ( diff --git a/yarn.lock b/yarn.lock index 6dac9780..1f10ba15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10253,14 +10253,14 @@ husky@8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -i18next-browser-languagedetector@^8.0.0: +i18next-browser-languagedetector@8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz#b6fdd9b43af67c47f2c26c9ba27710a1eaf31e2f" integrity sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw== dependencies: "@babel/runtime" "^7.23.2" -i18next@^23.16.5: +i18next@23.16.5: version "23.16.5" resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.5.tgz#53d48ae9f985fd73fc1fcb96e6c7d90ababf0831" integrity sha512-KTlhE3EP9x6pPTAW7dy0WKIhoCpfOGhRQlO+jttQLgzVaoOjWwBWramu7Pp0i+8wDNduuzXfe3kkVbzrKyrbTA== @@ -13487,7 +13487,7 @@ react-hot-toast@2.4.1: dependencies: goober "^2.1.10" -react-i18next@^15.1.1: +react-i18next@15.1.1: version "15.1.1" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.1.tgz#30bc76b39ded6ee37f1457677e46e6d6f11d9f64" integrity sha512-R/Vg9wIli2P3FfeI8o1eNJUJue5LWpFsQePCHdQDmX0Co3zkr6kdT8gAseb/yGeWbNz1Txc4bKDQuZYsC0kQfw== From 0193b49051c7e11f4942b613159a01e9355c7543 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 25 Nov 2024 19:38:23 +0100 Subject: [PATCH 32/51] clean up --- packages/frontend/src/components/LanguageModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index b45a339c..2c09983b 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -35,8 +35,8 @@ export const LanguageModal: React.FC = ({ }) => { const { t } = useTranslation(); - const handleLanguageSelect = async (code: EnumLanguageCode) => { - await i18next + const handleLanguageSelect = (code: EnumLanguageCode) => { + i18next .changeLanguage(code) .then(() => { onSetLanguageCode(code); From 28ed483a31bf6be2dcc65fb2205962833e0652ba Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 27 Nov 2024 11:00:55 +0100 Subject: [PATCH 33/51] add spanish and french --- packages/frontend/src/i18n.ts | 13 +- packages/frontend/src/locales/translation.ts | 793 +++++++++++++++++++ 2 files changed, 805 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index bbf9a800..ace2103c 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -2,7 +2,12 @@ import i18n from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import { initReactI18next } from "react-i18next"; import { Logger } from "./api/utils/logging"; -import { translationEN, translationJA } from "./locales/translation"; +import { + translationEN, + translationES, + translationFR, + translationJA, +} from "./locales/translation"; const resources = { en: { @@ -11,6 +16,12 @@ const resources = { ja: { translation: translationJA, }, + es: { + translation: translationES, + }, + fr: { + translation: translationFR, + } }; i18n.use(LanguageDetector) diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 302a340d..d6456bee 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -780,3 +780,796 @@ export const translationJA: typeof translationEN = { close_button: "閉じる", }, }; + +export const translationES: typeof translationEN = { + navigation: { + searchBarPlaceholder: "Buscar activos, proyectos, eventos, etc.", + boards: "Tableros", + openBoardsLibrary: "Abrir biblioteca de tableros", + widgets: "Widgets", + sortBy: "Ordenar por", + menu: { + sign_in: "Iniciar sesión", + sign_out: "Cerrar sesión", + sign_up: "Registrarse", + tutorial: "Tutorial", + language: "Idioma", + about_us: "Sobre nosotros", + version: "Versión", + commit: "Commit", + }, + boards_library: { + title: "Biblioteca de tableros", + description: + "Cambia entre tableros para optimizar tu flujo de trabajo y ancla los más utilizados.", + custom_boards_title: "Tableros personalizados", + custom_boards_description_with_auth: + "Crea un tablero en blanco y agrega widgets", + custom_boards_description: + "Conecta tu cartera para autenticarte y crear nuevos tableros personalizados", + }, + widgets_library: { + title: "Biblioteca de widgets", + searchBarPlaceholder: "Buscar widgets", + allWidgets: "Todos los widgets", + }, + general: { + all: "Todos", + general: "General", + nfts: "NFT", + daos: "DAO", + layer2: "Capa 2", + defi: "DeFi", + trading: "Trading", + popular: "Popular", + name: "Nombre", + new: "Nuevo", + feed: "Feed", + trending: "Tendencias", + readLater: "Leer después", + readMore: "Leer más", + bookmarks: "Marcadores", + timeRange: "Rango de tiempo", + media: "Medios", + chains: "Cadenas", + protocols: "Protocolos", + less: "Menos", + more: "Más", + }, + }, + widget: { + options: "Opciones", + close_options: "Cerrar opciones", + expand: "Expandir", + maximize: "Maximizar", + minimize: "Minimizar", + screenshot: "Captura de pantalla", + remove_widget: "Eliminar widget", + }, + tabs: { + news: "Noticias", + portfolio: "Portafolio", + calendar: "Calendario", + feed: "Feed", + trending: "Tendencias", + read_later: "Leer después", + }, + buttons: { + connect_wallet: "Conectar cartera", + verify_wallet: "Verificar cartera", + add_wallet: "Añadir nueva cartera", + disconnect_wallet: "Desconectar cartera", + enter_address: "Introducir dirección", + save: "Guardar", + notNow: "Ahora no", + next: "Siguiente", + }, + portfolio: { + addAWallet: "Añadir dirección de cartera", + inputPlaceholder: "Introduce una dirección de Ethereum o ENS", + totalBalance: "Saldo total", + allWallets: "Todas las carteras", + asset: "Activo", + assets: "Activos", + nfts: "NFTs", + balance: "Saldo", + price: "Precio", + value: "Valor", + modals: { + title: "Conectar cartera", + soon: "(próximamente)", + metamask: "MetaMask", + selectingMethod: { + title: "Seleccionar proveedor de cartera", + }, + prompted: { + title: "Verificar cartera", + content: + "Cartera conectada con éxito. Para guardar tableros personalizados, firma un mensaje de texto e inicia sesión en Alphaday.", + }, + connectionError: { + title: "Error de conexión de cartera", + content: + "Hubo un error al conectarse al proveedor de la cartera. Asegúrate de que tu cartera esté configurada correctamente.", + }, + verificationError: { + title: "Error de verificación de cartera", + content: + "La autenticación ha fallado. ¿La cartera está desbloqueada? ¿Has cambiado de cuenta?", + }, + genericError: { + title: "Error inesperado", + content: + "Ups! Ha habido un problema. Por favor, inténtalo de nuevo más tarde.", + }, + }, + }, + tutorials: { + switchView_title: "Cambiar entre tableros", + switchView_text: + "Optimiza tu flujo de trabajo utilizando diferentes tableros con varios widgets o creando los tuyos propios.", + walletView_title: "Crear tablero de cartera", + walletView_text: + "Rastrea toda la información sobre los activos de tu cartera en Alphaday.", + useSeachBar_title: "Barra de búsqueda", + useSeachBar_text: + "Busca tus tokens, proyectos o temas favoritos para filtrar el contenido dentro de los widgets.", + reArrangeWidget_title: "Reorganizar widgets", + reArrangeWidget_text: + "Arrastra los widgets usando la barra superior para cambiar su posición o haz clic una vez para minimizarlos.", + useWidgetLib_title: "Biblioteca de widgets", + useWidgetLib_text: + "La biblioteca de widgets tiene una gran variedad de widgets útiles para que elijas.", + comeBack_text: + "Puedes volver al tutorial en cualquier momento desde el menú de usuario.", + }, + market: { + title: "Mercado", + line: "Línea", + candlestick: "Velas", + no_coins_selected: "No hay monedas seleccionadas para este tag", + // eslint-disable-next-line no-template-curly-in-string + history_error: "Historial de ${selectedChartRange} de esta moneda", + market_cap: "Capitalización de mercado", + volume_24h: "Volumen en 24h", + }, + podcasts: { + channels: "Canales", + selected_channels: "Canales seleccionados", + all_channels: "Todos los canales", + channels_input_placeholder: "Buscar canales", + }, + calendar: { + organizers: "Organizadores", + speakers: "Ponentes", + more_details: "Más detalles", + noEvents: "No hay eventos próximos", + event_types: { + conferences: "Conferencias", + meetups: "Encuentros", + hackathons: "Hackathones", + product_releases: "Lanzamientos de productos", + dev_calls: "Llamadas de desarrolladores", + ico: "Oferta inicial de criptomonedas", + ido: "Oferta inicial descentralizada", + dao_votes: "Votaciones de DAO", + economic_events: "Eventos económicos", + community_calls: "Llamadas comunitarias", + soft_forks: "Soft forks", + hard_forks: "Hard forks", + education: "Educación", + interviews: "Entrevistas", + parties: "Fiestas", + workshops: "Talleres", + unfiltered: "Sin filtrar", + }, + }, + others: { + tag_options: { + auth: "ethereum, bitcoin, etc.", + unAuth: "Inicia sesión para anclar monedas, etc.", + }, + change: "Cambio", + name: "Nombre", + your_nfts: "Tus NFTs", + est_value: "Valor estimado", + tvl: "TVL", + no_items_found: "No se encontraron elementos", + accept: "Aceptar", + decline: "Rechazar", + briefing_for: "Resumen para", + cookie: { + text: "Utilizamos cookies necesarias para el funcionamiento de Alphaday. Nos gustaría usar otras cookies para mejorar tu visita, personalizarla y analizar el rendimiento del sitio web, pero solo si las aceptas.", + acceptAll: "Aceptar todo", + acceptEssential: "Aceptar solo esenciales", + }, + }, + verasity: { + token_name: "Nombre del token", + token_ticker: "Ticker del token", + sm_address: "Dirección del contrato inteligente", + total_supply: "Suministro total", + max_circle_supply: "Suministro máximo en circulación", + circle_supply: "Suministro en circulación", + }, + messages: { + error: { + title: "Error", + notFound: "La página solicitada no se ha encontrado.", + generic: "Ha ocurrido un error procesando tu solicitud.", + forbidden: "No tienes permiso para acceder a esta página.", + unauthorized: "No tienes permiso para acceder a esta página.", + notAuthenticated: + "Por favor, conecta y verifica tu cartera para continuar", + maxViews: "Has alcanzado el número máximo de tableros creados", + maxWidgets: + "Has superado el número de widgets que se pueden añadir a un tablero", + maxViewWidgets: + "Has superado el número permitido de este widget en el tablero", + requestFailed: + // eslint-disable-next-line no-template-curly-in-string + "Error al obtener ${term}. Inténtalo de nuevo más tarde", + boardHasNoRequiredWidget: + // eslint-disable-next-line no-template-curly-in-string + "Este tablero ${boardName} requiere el widget ${SlugToWidgetNameMap[widget_template]}. Debes añadir el widget ${SlugToWidgetNameMap[widget_template]} a este tablero y actualizar la página para acceder a esta ruta.", + back_to_home: "Volver al inicio", + no_nfts_found: + "No se encontraron NFTs para la cartera especificada.", + no_video: "No se ha seleccionado ningún video", + something_wrong: "Algo ha salido mal.", + }, + success: { + title: "Éxito", + generic: "Tu solicitud se ha procesado correctamente.", + }, + queries: { + noResults: "No se encontraron resultados", + // eslint-disable-next-line no-template-curly-in-string + noMatchFound: "No se encontró ${item}", + }, + portfolio: { + signUp: "Regístrate para guardar tu portafolio", + connectWallet: "Conecta primero tu cartera para registrarte", + verifyWallet: + "Firma un mensaje sin comisiones para iniciar sesión en Alphaday y confirmar la propiedad y guardar la configuración.", + }, + callToAction: { + // eslint-disable-next-line no-template-curly-in-string + signUpToBookmark: "Regístrate para marcar este ${item}", + }, + }, + countdown: { + labels: { + days: "días", + hours: "horas", + minutes: "minutos", + seconds: "segundos", + }, + }, + datelocale: { + future: "después", + past: "antes", + s: "segundo", + m: "minuto", + mm: "minutos", + h: "hora", + hh: "horas", + d: "día", + dd: "días", + w: "semana", + M: "mes", + MM: "meses", + y: "año", + yy: "años", + ytd: "año hasta la fecha", + }, + gas: { + title: "Precio del gas", + fast: "Rápido", + standard: "Estándar", + slow: "Lento", + beacon_chain_data: "Datos de cadena de señalización", + }, + qna: { + intro: "Este widget es una interfaz para los datos agregados de criptomonedas de Alphaday. Puedes introducir cualquier consulta en lenguaje natural, como '¿Qué proyecto tiene el mayor TVL?'", + highlight: + "Para usar este widget, necesitas conectar y verificar tu cartera.", + button: "Hacer pregunta", + }, + about_us: { + title: "Sobre nosotros", + company_overview: { + title: "Información de la empresa:", + registered_name: "Nombre registrado: Alphabox Solutions Pte. Ltd.", + registration_number: "Número de registro: 202136261C", + registered_office: + "Domicilio social: 45 North Canal Road #01-01 Lew Building Singapore", + }, + contact_info: { + title: "Información de contacto:", + email: "Correo electrónico: hello@alphaday.com", + xcom: "X.com: https://x.com/AlphadayHQ", + }, + legal_info: { + title: "Información legal:", + terms: "Términos de servicio: https://alphaday.com/terms", + privacy: "Política de privacidad: https://alphaday.com/privacy", + }, + additional_resources: { + title: "Recursos adicionales:", + faqs: "Preguntas frecuentes: alphaday.com", + feedback: "Feedback: https://forms.gle/RbrrLGdFPAeuNJhk9", + }, + mission: + "La misión de Alphaday es proporcionar todas las herramientas necesarias para seguir tus proyectos favoritos, mantenerte al día con la información más reciente y utilizar tus dapps favoritas desde un panel de control personalizable y fácil de usar.", + close_button: "Cerrar", + }, + error_page: { + offline: { + heading: { + text: "Estás", + highlight: "desconectado", + }, + description: + "Parece que has perdido tu conexión. Por favor, revísala e inténtalo de nuevo.", + }, + "503": { + heading: { + text: "Sistema en", + highlight: "mantenimiento", + }, + description1: { + text: "Estamos realizando un mantenimiento programado. ¡Volveremos pronto! Mientras tanto, puedes revisar nuestro", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + }, + description2: "Asegúrate de volver a comprobar más tarde.", + }, + "403": { + heading: { + text: "No autorizado", + highlight: "403", + }, + description: "No tienes permiso para acceder a esta página.", + }, + "404": { + heading: { + highlight: "404", + }, + description: + "Lo sentimos, la página que buscas no se pudo encontrar.", + }, + default: { + description: { + text: "Algo salió mal, ¡volveremos pronto! Mientras tanto, puedes revisar nuestro", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + textAfterLink: "para actualizaciones.", + }, + }, + }, + + wallet_view: { + create_wallet_board: "Crear Tablero de Billetera", + view_wallet_board: "Ver Tablero de Billetera", + creating_wallet_board: "Creando Tablero de Billetera", + }, + terms_of_service: { + titleOne: "Aviso Legal", + text_one: + "Alphaday no es responsable de las operaciones o el rendimiento de plataformas y widgets de terceros, incluido Uniswap. El Widget de Intercambio de Uniswap se proporciona como una conveniencia para nuestros usuarios. Alphaday no controla ni gestiona las transacciones realizadas a través de Uniswap, y no somos responsables de ninguna pérdida o daño incurrido como resultado del uso del Widget de Intercambio de Uniswap. Se alienta a los usuarios a realizar su propia investigación y ejercer precaución al comerciar con criptomonedas. Al usar el Widget de Intercambio de Uniswap, usted acepta los", + text_two: "Términos de Servicio", + text_three: "y", + text_four: "Política de Privacidad", + titleTwo: "Divulgación de Riesgos", + text_five: + "El comercio de criptomonedas implica un riesgo significativo y puede resultar en la pérdida de su capital invertido. No debe invertir más de lo que puede permitirse perder y debe asegurarse de comprender completamente los riesgos involucrados. La volatilidad de los precios y la naturaleza global del mercado de criptomonedas pueden conducir a pérdidas significativas. Alphaday no proporciona ningún consejo de inversión o recomendaciones sobre la idoneidad de cualquier transacción de criptomonedas. Todas las decisiones comerciales son tomadas por los usuarios y no por Alphaday. Por favor, consulte con un asesor financiero antes de tomar cualquier decisión comercial.", + }, + language: { + title: "Seleccionar Idioma", + close_button: "Cerrar", + }, +}; + +export const translationFR: typeof translationEN = { + navigation: { + searchBarPlaceholder: + "Rechercher des actifs, projets, événements, etc.", + boards: "Tableaux", + openBoardsLibrary: "Ouvrir la bibliothèque de tableaux", + widgets: "Widgets", + sortBy: "Trier par", + menu: { + sign_in: "Se connecter", + sign_out: "Se déconnecter", + sign_up: "S'inscrire", + tutorial: "Tutoriel", + language: "Langue", + about_us: "À propos de nous", + version: "Version", + commit: "Commit", + }, + boards_library: { + title: "BIBLIOTHÈQUE DE TABLEAUX", + description: + "Basculez entre les tableaux pour optimiser votre flux de travail et épinglez ceux que vous utilisez le plus souvent.", + custom_boards_title: "Tableaux personnalisés", + custom_boards_description_with_auth: + "Créez un tableau vide et ajoutez des widgets", + custom_boards_description: + "Connectez et vérifiez votre portefeuille pour créer de nouveaux tableaux et voir vos tableaux personnalisés", + }, + widgets_library: { + title: "Bibliothèque de Widgets", + searchBarPlaceholder: "Rechercher des widgets", + allWidgets: "Tous les Widgets", + }, + general: { + all: "Tous", + general: "Général", + nfts: "NFTs", + daos: "DAOs", + layer2: "Layer 2", + defi: "DeFi", + trading: "Trading", + popular: "Populaire", + name: "(A-Z)", + new: "Nouveau", + feed: "Fil d'actualité", + trending: "Tendance", + readLater: "Lire plus tard", + readMore: "Lire plus", + bookmarks: "Favoris", + timeRange: "Plage de temps", + media: "Médias", + chains: "Chaînes", + protocols: "Protocoles", + less: "Moins", + more: "Plus", + }, + }, + widget: { + options: "Options", + close_options: "Fermer les options", + expand: "Étendre", + maximize: "Maximiser", + minimize: "Minimiser", + screenshot: "Capture d'écran", + remove_widget: "Supprimer le widget", + }, + tabs: { + news: "ACTUALITÉS", + portfolio: "PORTFOLIO", + calendar: "CALENDRIER", + feed: "Fil d'actualité", + trending: "Tendance", + read_later: "Lire plus tard", + }, + buttons: { + connect_wallet: "Connecter le portefeuille", + verify_wallet: "Vérifier le portefeuille", + add_wallet: "Ajouter un nouveau portefeuille", + disconnect_wallet: "Déconnecter le portefeuille", + enter_address: "Entrer une adresse", + save: "Enregistrer", + notNow: "Pas maintenant", + next: "Suivant", + }, + portfolio: { + addAWallet: "Ajouter une adresse de portefeuille", + inputPlaceholder: "Entrer une adresse Ethereum ou ENS", + totalBalance: "Solde total", + allWallets: "Tous les portefeuilles", + asset: "Actif", + assets: "Actifs", + nfts: "NFTs", + balance: "Solde", + price: "Prix", + value: "Valeur", + modals: { + title: "Connexion au portefeuille", + soon: "(bientôt)", + metamask: "Metamask", + selectingMethod: { + title: "Choisissez un fournisseur de portefeuille", + }, + prompted: { + title: "Vérifier le portefeuille", + content: + "Votre portefeuille a été connecté avec succès. Pour enregistrer vos tableaux personnalisés, veuillez vous connecter à Alphaday en signant un message texte.", + }, + connectionError: { + title: "Erreur de connexion au portefeuille", + content: + "Une erreur s'est produite lors de la tentative de connexion à votre fournisseur de portefeuille. Assurez-vous que votre portefeuille est correctement configuré.", + }, + verificationError: { + title: "Erreur de vérification du portefeuille", + content: + "L'authentification a échoué. Votre portefeuille est-il déverrouillé ? Avez-vous changé de compte ?", + }, + genericError: { + title: "Erreur inattendue", + content: + "Oups ! Une erreur s'est produite. Veuillez réessayer plus tard.", + }, + }, + }, + tutorials: { + switchView_title: "Changer de tableau", + switchView_text: + "Optimisez votre flux de travail en utilisant différents tableaux organisés avec divers widgets, ou créez le vôtre.", + walletView_title: "Créer un tableau de portefeuille", + walletView_text: + "Suivez toutes les informations sur Alphaday concernant les actifs de votre portefeuille.", + useSeachBar_title: "Barre de recherche", + useSeachBar_text: + "Recherchez vos jetons, projets ou sujets préférés pour filtrer le contenu des widgets.", + reArrangeWidget_title: "Réorganiser les widgets", + reArrangeWidget_text: + "Cliquez et faites glisser les widgets par la barre supérieure pour changer leur position dans le tableau de bord, ou cliquez une fois pour les réduire.", + useWidgetLib_title: "Bibliothèque de widgets", + useWidgetLib_text: + "Il y a des dizaines de widgets utiles disponibles pour vous dans la bibliothèque de widgets à choisir.", + comeBack_text: + "Revenez à l'introduction à tout moment dans le menu utilisateur.", + }, + market: { + title: "Marché", + line: "Ligne", + candlestick: "Bougies", + no_coins_selected: "Aucune monnaie sélectionnée pour ce tag", + // eslint-disable-next-line no-template-curly-in-string + history_error: "Historique de ${selectedChartRange} de cette monnaie", + market_cap: "Capitalisation boursière", + volume_24h: "Volume sur 24h", + }, + podcasts: { + channels: "Canaux", + selected_channels: "Canaux sélectionnés", + all_channels: "Tous les canaux", + channels_input_placeholder: "Rechercher des canaux", + }, + calendar: { + organizers: "Organisateurs", + speakers: "Intervenants", + more_details: "Plus de détails", + noEvents: "Aucun événement à venir", + event_types: { + conferences: "Conférences", + meetups: "Rencontres", + hackathons: "Hackathons", + product_releases: "Lancements de produits", + dev_calls: "Appels de développeurs", + ico: "Offre initiale de pièces", + ido: "Offre initiale décentralisée", + dao_votes: "Votes de DAO", + economic_events: "Événements économiques", + community_calls: "Appels communautaires", + soft_forks: "Soft forks", + hard_forks: "Hard forks", + education: "Éducation", + interviews: "Interviews", + parties: "Fêtes", + workshops: "Ateliers", + unfiltered: "Non filtré", + }, + }, + others: { + tag_options: { + auth: "ethereum, bitcoin, etc.", + unAuth: "Connectez-vous pour épingler des monnaies, etc.", + }, + change: "Modifier", + name: "Nom", + your_nfts: "Vos NFTs", + est_value: "Valeur estimée", + tvl: "TVL", + no_items_found: "Aucun élément trouvé", + accept: "Accepter", + decline: "Refuser", + briefing_for: "Résumé pour", + cookie: { + text: "Nous utilisons des cookies nécessaires pour le fonctionnement d'Alphaday. Nous aimerions utiliser d'autres cookies pour améliorer votre visite, la personnaliser et analyser la performance du site web, mais uniquement si vous les acceptez.", + acceptAll: "Tout accepter", + acceptEssential: "Accepter uniquement l'essentiel", + }, + }, + verasity: { + token_name: "Nom du jeton", + token_ticker: "Symbole du jeton", + sm_address: "Adresse du contrat intelligent", + total_supply: "Offre totale", + max_circle_supply: "Offre maximale en circulation", + circle_supply: "Offre en circulation", + }, + messages: { + error: { + title: "Erreur", + notFound: "La page demandée est introuvable.", + generic: + "Une erreur est survenue lors du traitement de votre demande.", + forbidden: "Vous n'avez pas la permission d'accéder à cette page.", + unauthorized: "Vous n'êtes pas autorisé à accéder à cette page.", + notAuthenticated: + "Veuillez connecter et vérifier votre portefeuille pour continuer", + maxViews: "Vous avez atteint le nombre maximal de tableaux créés", + maxWidgets: + "Vous avez dépassé le nombre de widgets pouvant être ajoutés à un tableau", + maxViewWidgets: + "Vous avez dépassé le nombre autorisé de ce widget sur le tableau", + requestFailed: + // eslint-disable-next-line no-template-curly-in-string + "Erreur lors de la récupération de ${term}. Veuillez réessayer plus tard", + boardHasNoRequiredWidget: + // eslint-disable-next-line no-template-curly-in-string + "Ce tableau ${boardName} nécessite le widget ${SlugToWidgetNameMap[widget_template]}. Vous devez ajouter le widget ${SlugToWidgetNameMap[widget_template]} à ce tableau et actualiser la page pour accéder à cette route.", + back_to_home: "Retour à l'accueil", + no_nfts_found: "Aucun NFT trouvé pour le portefeuille spécifié.", + no_video: "Aucune vidéo sélectionnée", + something_wrong: "Quelque chose s'est mal passé.", + }, + success: { + title: "Succès", + generic: "Votre demande a été traitée avec succès.", + }, + queries: { + noResults: "Aucun résultat trouvé", + // eslint-disable-next-line no-template-curly-in-string + noMatchFound: "Aucun ${item} correspondant trouvé.", + }, + portfolio: { + signUp: "Inscrivez-vous pour sauvegarder votre portefeuille", + connectWallet: + "Connectez d'abord votre portefeuille pour vous inscrire", + verifyWallet: + "Signez un message sans frais pour vous connecter à Alphaday, confirmer la propriété et sauvegarder la configuration.", + }, + callToAction: { + signUpToBookmark: + // eslint-disable-next-line no-template-curly-in-string + "Inscrivez-vous pour ajouter ce ${item} aux favoris", + }, + }, + countdown: { + labels: { + days: "jours", + hours: "heures", + minutes: "minutes", + seconds: "secondes", + }, + }, + datelocale: { + future: "après", + past: "avant", + s: "seconde", + m: "minute", + mm: "minutes", + h: "heure", + hh: "heures", + d: "jour", + dd: "jours", + w: "semaine", + M: "mois", + MM: "mois", + y: "an", + yy: "ans", + ytd: "année à ce jour", + }, + gas: { + title: "Prix du gaz", + fast: "Rapide", + standard: "Standard", + slow: "Lent", + beacon_chain_data: "Données de la chaîne de balises", + }, + qna: { + intro: "Ce widget est une interface pour les données agrégées sur les crypto-monnaies d'Alphaday. Vous pouvez poser n'importe quelle question en langage naturel, comme 'Quel projet a le plus grand TVL ?'", + highlight: + "Pour utiliser ce widget, vous devez connecter et vérifier votre portefeuille.", + button: "Poser une question", + }, + about_us: { + title: "À propos de nous", + company_overview: { + title: "Informations sur l'entreprise :", + registered_name: "Nom enregistré : Alphabox Solutions Pte. Ltd.", + registration_number: "Numéro d'enregistrement : 202136261C", + registered_office: + "Siège social : 45 North Canal Road #01-01 Lew Building Singapour", + }, + contact_info: { + title: "Informations de contact :", + email: "E-mail : hello@alphaday.com", + xcom: "X.com : https://x.com/AlphadayHQ", + }, + legal_info: { + title: "Informations juridiques :", + terms: "Conditions d'utilisation : https://alphaday.com/terms", + privacy: + "Politique de confidentialité : https://alphaday.com/privacy", + }, + additional_resources: { + title: "Ressources supplémentaires :", + faqs: "FAQ : alphaday.com", + feedback: + "Retour d'expérience : https://forms.gle/RbrrLGdFPAeuNJhk9", + }, + mission: + "La mission d'Alphaday est de fournir tous les outils nécessaires pour suivre vos projets préférés, rester à jour avec les dernières informations et utiliser vos dapps préférées depuis un tableau de bord personnalisable et facile à utiliser.", + close_button: "Fermer", + }, + error_page: { + offline: { + heading: { + text: "Vous êtes", + highlight: "hors ligne", + }, + description: + "Il semble que vous ayez perdu votre connexion. Veuillez la vérifier et réessayer.", + }, + "503": { + heading: { + text: "Système en", + highlight: "maintenance", + }, + description1: { + text: "Nous effectuons actuellement une maintenance programmée. Nous serons de retour sous peu ! En attendant, vous pouvez consulter notre", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + }, + description2: "Et assurez-vous de revenir vérifier plus tard.", + }, + "403": { + heading: { + text: "Non autorisé", + highlight: "403", + }, + description: + "Vous n'avez pas les autorisations pour accéder à cette page.", + }, + "404": { + heading: { + highlight: "404", + }, + description: "Désolé, la page que vous recherchez est introuvable.", + }, + default: { + description: { + text: "Quelque chose s'est mal passé, nous serons de retour sous peu ! En attendant, vous pouvez consulter notre", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + textAfterLink: "pour les mises à jour.", + }, + }, + }, + + wallet_view: { + create_wallet_board: "Créer un Tableau de Portefeuille", + view_wallet_board: "Voir le Tableau de Portefeuille", + creating_wallet_board: "Création du Tableau de Portefeuille", + }, + terms_of_service: { + titleOne: "Avis Juridique", + text_one: + "Alphaday n'est pas responsable des opérations ou des performances des plateformes et widgets tiers, y compris Uniswap. Le Widget d'Échange Uniswap est fourni pour la commodité de nos utilisateurs. Alphaday ne contrôle ni ne gère les transactions effectuées via Uniswap, et nous ne sommes pas responsables des pertes ou dommages encourus suite à l'utilisation du Widget d'Échange Uniswap. Les utilisateurs sont encouragés à faire leurs propres recherches et à faire preuve de prudence lors des échanges de cryptomonnaies. En utilisant le Widget d'Échange Uniswap, vous acceptez les", + text_two: "Conditions d'Utilisation", + text_three: "et la", + text_four: "Politique de Confidentialité", + titleTwo: "Divulgation des Risques", + text_five: + "Le trading de cryptomonnaies comporte des risques importants et peut entraîner la perte de votre capital investi. Vous ne devez pas investir plus que ce que vous pouvez vous permettre de perdre et vous devez vous assurer de bien comprendre les risques encourus. La volatilité des prix et la nature mondiale du marché des cryptomonnaies peuvent entraîner des pertes importantes. Alphaday ne fournit aucun conseil d'investissement ni recommandation concernant la pertinence des transactions de cryptomonnaies. Toutes les décisions de trading sont prises par les utilisateurs et non par Alphaday. Veuillez consulter un conseiller financier avant de prendre toute décision de trading.", + }, + language: { + title: "Sélectionner la Langue", + close_button: "Fermer", + }, +}; From 53fd1143e028637452f0f6d24d701f2b4d6f0d1f Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 27 Nov 2024 14:32:50 +0100 Subject: [PATCH 34/51] update date locale --- packages/frontend/src/locales/translation.ts | 47 ++++++++++---------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index d6456bee..684d61c5 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -1047,22 +1047,23 @@ export const translationES: typeof translationEN = { }, }, datelocale: { - future: "después", - past: "antes", - s: "segundo", - m: "minuto", - mm: "minutos", - h: "hora", - hh: "horas", - d: "día", - dd: "días", - w: "semana", + future: "en %s", + past: " hace", + s: "s", + m: "min", + mm: "min", + h: "h", + hh: "h", + d: "d", + dd: "d", + w: "sem", M: "mes", - MM: "meses", + MM: "mes", y: "año", - yy: "años", ytd: "año hasta la fecha", + yy: "años", }, + gas: { title: "Precio del gas", fast: "Rápido", @@ -1444,21 +1445,21 @@ export const translationFR: typeof translationEN = { }, }, datelocale: { - future: "après", - past: "avant", - s: "seconde", - m: "minute", - mm: "minutes", - h: "heure", - hh: "heures", - d: "jour", - dd: "jours", - w: "semaine", + future: "dans %s", + past: " il y a", + s: "s", + m: "min", + mm: "min", + h: "h", + hh: "h", + d: "j", + dd: "j", + w: "sem", M: "mois", MM: "mois", y: "an", - yy: "ans", ytd: "année à ce jour", + yy: "ans", }, gas: { title: "Prix du gaz", From 9e092b795451be795b5565b5838314adbca30d3a Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 27 Nov 2024 19:55:46 +0100 Subject: [PATCH 35/51] date time translation --- packages/frontend/package.json | 1 + .../src/api/hooks/usePreferredLanguage.ts | 2 + .../src/api/services/tvl/tvlEndpoints.ts | 2 +- .../src/api/store/slices/views.test.ts | 2 +- packages/frontend/src/api/types/market.ts | 19 +++---- .../frontend/src/api/utils/calendarUtils.ts | 2 +- .../src/api/utils/customDataUtils.tsx | 2 +- packages/frontend/src/api/utils/dateUtils.ts | 2 +- packages/frontend/src/api/utils/viewUtils.ts | 2 +- .../src/components/calendar/CalendarList.tsx | 3 + .../src/components/calendar/CalendarMonth.tsx | 3 +- .../event-details/EventDetails.tsx | 2 +- .../components/calendar/calendarHelpers.ts | 2 +- .../components/countdown/CountdownModule.tsx | 2 +- .../components/discord/DiscordFeedItem.tsx | 2 +- .../dynamic-modules/agenda/AgendaItem.tsx | 2 +- .../dynamic-modules/roadmap/RoadmapItem.tsx | 2 +- .../src/components/feeds/LensFeedItem.tsx | 2 +- .../components/market/CandlestickChart.tsx | 2 +- .../src/components/market/DateRangeBar.tsx | 12 ++-- .../src/components/market/LineChart.tsx | 2 +- .../components/portfolio/PortfolioModule.tsx | 2 + .../src/components/summary/SummaryModule.tsx | 2 +- .../src/components/tvl/ProjectChart.tsx | 2 +- .../containers/calendar/CalendarContainer.tsx | 2 +- .../countdown/CountdownContainer.tsx | 2 +- .../src/containers/items/ItemsContainer.tsx | 2 +- .../containers/podcast/PodcastContainer.tsx | 2 +- .../src/containers/video/VideoContainer.tsx | 2 +- packages/frontend/src/i18n.ts | 2 +- packages/frontend/src/locales/translation.ts | 57 +++++++++---------- .../src/mobile-components/feed/EventCard.tsx | 2 +- .../src/mobile-components/feed/LineChart.tsx | 2 +- .../portfolio/AddHolding.tsx | 2 +- packages/ui-kit/package.json | 1 + .../src/components/calendar/CalendarList.tsx | 5 +- .../src/components/calendar/CalendarMonth.tsx | 5 +- .../ui-kit/src/components/charts/mockData.tsx | 2 +- .../components/tooltip/CalendarTooltip.tsx | 2 +- packages/ui-kit/src/utils/calendarUtils.ts | 13 +++++ packages/ui-kit/src/utils/dateUtils.ts | 4 +- yarn.lock | 8 +-- 42 files changed, 111 insertions(+), 80 deletions(-) create mode 100644 packages/ui-kit/src/utils/calendarUtils.ts diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 46860ccf..0df400d8 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -47,6 +47,7 @@ "ionicons": "7.3.0", "md5": "2.3.0", "moment": "2.30.1", + "moment-with-locales-es6": "^1.0.1", "query-string": "9.1.1", "react": "18.2.0", "react-beautiful-dnd": "13.1.1", diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts index 6c72983d..f01137f1 100644 --- a/packages/frontend/src/api/hooks/usePreferredLanguage.ts +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -1,4 +1,5 @@ import i18next from "i18next"; +import moment from "moment-with-locales-es6"; import { useAppSelector } from "../store/hooks"; import { Logger } from "../utils/logging"; @@ -10,5 +11,6 @@ export const usePreferredLanguage = () => { i18next.changeLanguage(selectedCode).catch((e) => { Logger.error("usePreferredLanguage::Error changing language::", e); }); + moment.locale(selectedCode); } }; diff --git a/packages/frontend/src/api/services/tvl/tvlEndpoints.ts b/packages/frontend/src/api/services/tvl/tvlEndpoints.ts index 74959406..b20f7cd0 100644 --- a/packages/frontend/src/api/services/tvl/tvlEndpoints.ts +++ b/packages/frontend/src/api/services/tvl/tvlEndpoints.ts @@ -1,4 +1,4 @@ -import moment from "moment"; +import moment from "moment-with-locales-es6"; import queryString from "query-string"; import { TProjectTvlHistory, TTvlHistory } from "src/api/types"; import { isEmptyObj } from "src/api/utils/helpers"; diff --git a/packages/frontend/src/api/store/slices/views.test.ts b/packages/frontend/src/api/store/slices/views.test.ts index e34372ff..917a93c4 100644 --- a/packages/frontend/src/api/store/slices/views.test.ts +++ b/packages/frontend/src/api/store/slices/views.test.ts @@ -1,5 +1,5 @@ import "src/mocks/libraryMocks"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { ETag, TCachedView, TSubscribedView } from "src/api/types"; import { customTableModuleDataMock } from "src/mocks/tables"; import { diff --git a/packages/frontend/src/api/types/market.ts b/packages/frontend/src/api/types/market.ts index 5630fbe0..326ab68a 100644 --- a/packages/frontend/src/api/types/market.ts +++ b/packages/frontend/src/api/types/market.ts @@ -1,4 +1,3 @@ -import i18next from "i18next"; import { TCoin } from "./primitives"; export type TAssetPrice = { @@ -39,14 +38,14 @@ export type TCoinMarketHistory = { }; export const CHART_RANGE_OPTIONS = { - oneDay: `1${i18next.t("datelocale.d")}`, - oneWeek: `1${i18next.t("datelocale.w")}`, - oneMonth: `1${i18next.t("datelocale.M")}`, - threeMonths: `3${i18next.t("datelocale.M")}`, - yearToDate: i18next.t("datelocale.ytd"), - oneYear: `1${i18next.t("datelocale.y")}`, - threeYear: `3${i18next.t("datelocale.y")}`, - all: i18next.t("navigation.general.all"), + oneDay: { value: "1D", translationKey: `datelocale.d`, prefix: "1" }, + oneWeek: { value: "1W", translationKey: `datelocale.w`, prefix: "1" }, + oneMonth: { value: "1M", translationKey: `datelocale.M`, prefix: "1" }, + threeMonths: { value: "3M", translationKey: `datelocale.M`, prefix: "3" }, + yearToDate: { value: "YTD", translationKey: "datelocale.ytd", prefix: "" }, + oneYear: { value: "1Y", translationKey: `datelocale.y`, prefix: "1" }, + threeYear: { value: "3Y", translationKey: `datelocale.y`, prefix: "3" }, + all: { value: "ALL", translationKey: "navigation.general.all", prefix: "" }, } as const; type TRangeKeys = keyof typeof CHART_RANGE_OPTIONS; -export type TChartRange = (typeof CHART_RANGE_OPTIONS)[TRangeKeys]; +export type TChartRange = (typeof CHART_RANGE_OPTIONS)[TRangeKeys]["value"]; diff --git a/packages/frontend/src/api/utils/calendarUtils.ts b/packages/frontend/src/api/utils/calendarUtils.ts index 44353090..15b44bd5 100644 --- a/packages/frontend/src/api/utils/calendarUtils.ts +++ b/packages/frontend/src/api/utils/calendarUtils.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ import chroma from "chroma-js"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TRemoteEvent, TRemoteEventDetails } from "src/api/services"; import { TEvent, TEventDetails } from "src/api/types"; import { diff --git a/packages/frontend/src/api/utils/customDataUtils.tsx b/packages/frontend/src/api/utils/customDataUtils.tsx index 8dbb086b..559b492b 100644 --- a/packages/frontend/src/api/utils/customDataUtils.tsx +++ b/packages/frontend/src/api/utils/customDataUtils.tsx @@ -1,4 +1,4 @@ -import moment from "moment"; +import moment from "moment-with-locales-es6"; import ReactMarkdown from "react-markdown"; import remarkBreaks from "remark-breaks"; import { diff --git a/packages/frontend/src/api/utils/dateUtils.ts b/packages/frontend/src/api/utils/dateUtils.ts index 7ce7f593..0bd34877 100644 --- a/packages/frontend/src/api/utils/dateUtils.ts +++ b/packages/frontend/src/api/utils/dateUtils.ts @@ -1,5 +1,5 @@ import i18next from "i18next"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; /** * returns a text that represents the given datetime * relative to now. diff --git a/packages/frontend/src/api/utils/viewUtils.ts b/packages/frontend/src/api/utils/viewUtils.ts index 95d515f7..56a41066 100644 --- a/packages/frontend/src/api/utils/viewUtils.ts +++ b/packages/frontend/src/api/utils/viewUtils.ts @@ -1,4 +1,4 @@ -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TRemoteUserView, TRemoteUserViewMeta, diff --git a/packages/frontend/src/components/calendar/CalendarList.tsx b/packages/frontend/src/components/calendar/CalendarList.tsx index 28dd2b74..721799e4 100644 --- a/packages/frontend/src/components/calendar/CalendarList.tsx +++ b/packages/frontend/src/components/calendar/CalendarList.tsx @@ -5,6 +5,7 @@ import { ScrollBar, Switch, } from "@alphaday/ui-kit"; +import { useTranslation } from "react-i18next"; import { getEventCategoryByColor } from "src/api/utils/calendarUtils"; import CONFIG from "src/config"; import { calendarMessages } from "src/globalMessages"; @@ -29,6 +30,7 @@ const CalendarList: FC = ({ widgetHeight, isFetchingEvents, }) => { + const { i18n } = useTranslation(); const scrollRef = useRef(); return ( @@ -65,6 +67,7 @@ const CalendarList: FC = ({ } > eventClickHandler(e, events, onClickEvent) } diff --git a/packages/frontend/src/components/calendar/CalendarMonth.tsx b/packages/frontend/src/components/calendar/CalendarMonth.tsx index f6333452..525076a7 100644 --- a/packages/frontend/src/components/calendar/CalendarMonth.tsx +++ b/packages/frontend/src/components/calendar/CalendarMonth.tsx @@ -42,7 +42,7 @@ const CalendarMonth: FC< onDatesSet, widgetHash, }) => { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const [isAlphaModalOpen, setisAlphaModalOpen] = useState(false); const [showAllLegends, setShowAllLegends] = useState(false); @@ -90,6 +90,7 @@ const CalendarMonth: FC<
)} = memo(function DateRangeBar({ onSelectChartRange, selectedChartType, }) { + const { t } = useTranslation(); return (
{Object.values(CHART_RANGE_OPTIONS).map((option) => ( - + onSelectChartRange(option)} + open={selectedChartRange === option.value} + onClick={() => onSelectChartRange(option.value)} variant="extraSmall" + className="capitalize" disabled={ /** * Disable 3Y and YTD for candlestick chart. @@ -34,7 +37,8 @@ const DateRangeBar: FC = memo(function DateRangeBar({ ].find((e) => e === option) } > - {option} + {`${option.prefix}${t(option.translationKey)}`} + {/* {option.value} */} ))} diff --git a/packages/frontend/src/components/market/LineChart.tsx b/packages/frontend/src/components/market/LineChart.tsx index 7670df0b..cf03aa9e 100644 --- a/packages/frontend/src/components/market/LineChart.tsx +++ b/packages/frontend/src/components/market/LineChart.tsx @@ -1,6 +1,6 @@ import { FC, memo, useState } from "react"; import { ApexAreaChart, Spinner, themeColors } from "@alphaday/ui-kit"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TChartRange } from "src/api/types"; import { ENumberStyle, formatNumber } from "src/api/utils/format"; import { minVal } from "src/api/utils/helpers"; diff --git a/packages/frontend/src/components/portfolio/PortfolioModule.tsx b/packages/frontend/src/components/portfolio/PortfolioModule.tsx index 579622e7..18b7aea9 100644 --- a/packages/frontend/src/components/portfolio/PortfolioModule.tsx +++ b/packages/frontend/src/components/portfolio/PortfolioModule.tsx @@ -179,6 +179,7 @@ const Portfolio: FC = ({ variant="primaryXL" title="Connect your Wallet" onClick={onConnectWallet} + className=" max-w-[49%]" > {t("buttons.connect_wallet")} @@ -186,6 +187,7 @@ const Portfolio: FC = ({ variant="secondaryXL" title="Enter a wallet address" onClick={handleShowEnterAddress} + className=" max-w-[49%]" > {t("buttons.enter_address")} diff --git a/packages/frontend/src/components/summary/SummaryModule.tsx b/packages/frontend/src/components/summary/SummaryModule.tsx index 8124cd07..d642ddca 100644 --- a/packages/frontend/src/components/summary/SummaryModule.tsx +++ b/packages/frontend/src/components/summary/SummaryModule.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; import { ModuleLoader } from "@alphaday/ui-kit"; import DOMPurify from "dompurify"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { useTranslation } from "react-i18next"; import { TNewsSummary } from "src/api/types"; import CONFIG from "src/config/config"; diff --git a/packages/frontend/src/components/tvl/ProjectChart.tsx b/packages/frontend/src/components/tvl/ProjectChart.tsx index f87580d8..2fb62e5f 100644 --- a/packages/frontend/src/components/tvl/ProjectChart.tsx +++ b/packages/frontend/src/components/tvl/ProjectChart.tsx @@ -1,6 +1,6 @@ import { useMemo, FC } from "react"; import { ApexAreaChart, themeColors } from "@alphaday/ui-kit"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TTvlHistory } from "src/api/types"; import { minVal } from "src/api/utils/helpers"; diff --git a/packages/frontend/src/containers/calendar/CalendarContainer.tsx b/packages/frontend/src/containers/calendar/CalendarContainer.tsx index eb518898..c9502297 100644 --- a/packages/frontend/src/containers/calendar/CalendarContainer.tsx +++ b/packages/frontend/src/containers/calendar/CalendarContainer.tsx @@ -1,5 +1,5 @@ import { FC, useCallback, useMemo, useState, useEffect } from "react"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { useHistory, useParams } from "react-router-dom"; import { useWidgetHeight } from "src/api/hooks"; import { useSelectedDate } from "src/api/hooks/useSelectedDate"; diff --git a/packages/frontend/src/containers/countdown/CountdownContainer.tsx b/packages/frontend/src/containers/countdown/CountdownContainer.tsx index 21202445..d51a0071 100644 --- a/packages/frontend/src/containers/countdown/CountdownContainer.tsx +++ b/packages/frontend/src/containers/countdown/CountdownContainer.tsx @@ -1,5 +1,5 @@ import { FC, useMemo } from "react"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TCounterData } from "src/api/types"; import assert from "src/api/utils/assert"; import { Logger } from "src/api/utils/logging"; diff --git a/packages/frontend/src/containers/items/ItemsContainer.tsx b/packages/frontend/src/containers/items/ItemsContainer.tsx index a4e034f7..75dc7129 100644 --- a/packages/frontend/src/containers/items/ItemsContainer.tsx +++ b/packages/frontend/src/containers/items/ItemsContainer.tsx @@ -1,5 +1,5 @@ import { FC, useState, useEffect, useRef, useCallback } from "react"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { usePagination, useWidgetHeight } from "src/api/hooks"; import { TBaseTag, diff --git a/packages/frontend/src/containers/podcast/PodcastContainer.tsx b/packages/frontend/src/containers/podcast/PodcastContainer.tsx index 2fe917c9..5c4a0b44 100644 --- a/packages/frontend/src/containers/podcast/PodcastContainer.tsx +++ b/packages/frontend/src/containers/podcast/PodcastContainer.tsx @@ -1,5 +1,5 @@ import { FC, useEffect, useRef, useState } from "react"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { AudioPlayerProvider } from "react-use-audio-player"; import { useView, usePagination, useWidgetHeight } from "src/api/hooks"; import { TBaseTag } from "src/api/services"; diff --git a/packages/frontend/src/containers/video/VideoContainer.tsx b/packages/frontend/src/containers/video/VideoContainer.tsx index 499e463e..96b502f5 100644 --- a/packages/frontend/src/containers/video/VideoContainer.tsx +++ b/packages/frontend/src/containers/video/VideoContainer.tsx @@ -1,5 +1,5 @@ import { FC, useEffect, useMemo, useRef, useState } from "react"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { useView, usePagination, useWidgetHeight } from "src/api/hooks"; import { TBaseTag } from "src/api/services"; import { diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index ace2103c..9689b952 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -21,7 +21,7 @@ const resources = { }, fr: { translation: translationFR, - } + }, }; i18n.use(LanguageDetector) diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 684d61c5..17d43120 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -1048,22 +1048,21 @@ export const translationES: typeof translationEN = { }, datelocale: { future: "en %s", - past: " hace", - s: "s", - m: "min", - mm: "min", - h: "h", - hh: "h", - d: "d", - dd: "d", - w: "sem", - M: "mes", - MM: "mes", - y: "año", - ytd: "año hasta la fecha", - yy: "años", + past: "hace %s", + s: "s", // SEGUNDOS + m: "m", // MINUTO + mm: "m", // MINUTOS + h: "h", // HORA + hh: "h", // HORAS + d: "d", // DÍA + dd: "d", // DÍAS + w: "s", // SEMANA + M: "m", // MES + MM: "m", // MESES + y: "a", // AÑO + ytd: "aa", // AÑO A LA FECHA + yy: "a", // AÑOS }, - gas: { title: "Precio del gas", fast: "Rápido", @@ -1446,20 +1445,20 @@ export const translationFR: typeof translationEN = { }, datelocale: { future: "dans %s", - past: " il y a", - s: "s", - m: "min", - mm: "min", - h: "h", - hh: "h", - d: "j", - dd: "j", - w: "sem", - M: "mois", - MM: "mois", - y: "an", - ytd: "année à ce jour", - yy: "ans", + past: "il y a %s", + s: "s", // SECONDES + m: "m", // MINUTE + mm: "m", // MINUTES + h: "h", // HEURE + hh: "h", // HEURES + d: "j", // JOUR + dd: "j", // JOURS + w: "s", // SEMAINE + M: "mo", // MOIS + MM: "mo", // MOIS (PLURIEL) + y: "a", // ANNÉE + ytd: "aad", // ANNÉE À DATE + yy: "a", // ANNÉES }, gas: { title: "Prix du gaz", diff --git a/packages/frontend/src/mobile-components/feed/EventCard.tsx b/packages/frontend/src/mobile-components/feed/EventCard.tsx index 2a490e4b..64e0b0ff 100644 --- a/packages/frontend/src/mobile-components/feed/EventCard.tsx +++ b/packages/frontend/src/mobile-components/feed/EventCard.tsx @@ -1,7 +1,7 @@ import { FC } from "react"; import { twMerge } from "@alphaday/ui-kit"; import DOMPurify from "dompurify"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { TSuperfeedItem } from "src/api/types"; import { typeOptions } from "src/components/calendarCategories"; import { TagButton } from "src/mobile-components/button/buttons"; diff --git a/packages/frontend/src/mobile-components/feed/LineChart.tsx b/packages/frontend/src/mobile-components/feed/LineChart.tsx index 8faa39a4..fc84192c 100644 --- a/packages/frontend/src/mobile-components/feed/LineChart.tsx +++ b/packages/frontend/src/mobile-components/feed/LineChart.tsx @@ -1,6 +1,6 @@ import { FC, memo } from "react"; import { twMerge } from "@alphaday/ui-kit"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { ApexAreaChart } from "src/components/charts/apexchart"; import { Spinner } from "src/components/spinner/Spinner"; import { darkColors } from "src/globalStyles/colors"; diff --git a/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx b/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx index 2bce4af9..e67ba02a 100644 --- a/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx +++ b/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx @@ -1,6 +1,6 @@ import { FC } from "react"; import { FormInput, Pager, ScrollBar } from "@alphaday/ui-kit"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { useHistory } from "src/api/hooks"; import { TCoin, THolding } from "src/api/types"; diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index 93e64d3c..a15d417a 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -21,6 +21,7 @@ "@ionic/react": "7.6.1", "apexcharts": "3.48.0", "moment": "2.30.1", + "moment-with-locales-es6": "^1.0.1", "react": "18.2.0", "react-apexcharts": "1.4.1", "react-dom": "18.2.0", diff --git a/packages/ui-kit/src/components/calendar/CalendarList.tsx b/packages/ui-kit/src/components/calendar/CalendarList.tsx index 0ddf073d..625ddff5 100644 --- a/packages/ui-kit/src/components/calendar/CalendarList.tsx +++ b/packages/ui-kit/src/components/calendar/CalendarList.tsx @@ -5,7 +5,7 @@ import interactionPlugin from "@fullcalendar/interaction"; import listPlugin from "@fullcalendar/list"; import FullCalendar from "@fullcalendar/react"; import timeGridPlugin from "@fullcalendar/timegrid"; -import moment from "moment"; +import moment from "moment-with-locales-es6"; import { Spinner } from "../spinner/Spinner"; import { ICalendarBaseProps, @@ -41,6 +41,7 @@ const getValidCalendarDateRange = () => { }; interface ICalendarList extends ICalendarBaseProps { + locale: string; eventClickHandler: (e: EventClickArg) => void; handleHeaderTooltips: ( info: DatesSetArg, @@ -56,6 +57,7 @@ interface ICalendarList extends ICalendarBaseProps { } export const CalendarList: FC = ({ + locale, events, selectedEventDetails, onDatesSet, @@ -275,6 +277,7 @@ export const CalendarList: FC = ({ return (
{ }; interface ICalendarMonth extends ICalendarBaseProps { + locale: string; handleHeaderTooltips: ( info: DatesSetArg, widgetHash: string, @@ -116,6 +117,7 @@ interface ICalendarMonth extends ICalendarBaseProps { } export const CalendarMonth: FC = ({ + locale, events, onDatesSet, showFullSize, @@ -351,6 +353,7 @@ export const CalendarMonth: FC = ({ return ( { + const localesMap = { + ja: jaLocale, + es: esLocale, + fr: frLocale, + }; + + return Object.entries(localesMap).find(([key]) => key === localeCode)?.[1]; +}; diff --git a/packages/ui-kit/src/utils/dateUtils.ts b/packages/ui-kit/src/utils/dateUtils.ts index a1cb4165..6dfb546c 100644 --- a/packages/ui-kit/src/utils/dateUtils.ts +++ b/packages/ui-kit/src/utils/dateUtils.ts @@ -1,4 +1,4 @@ -import moment from "moment"; +import moment from "moment-with-locales-es6"; /** * returns a text that represents the given datetime * relative to now. @@ -6,7 +6,7 @@ import moment from "moment"; * @returns string */ export const computeDuration = (date: string | Date): string => { - moment.updateLocale("ja", { + moment.updateLocale("en", { relativeTime: { future: "in %s", // this shouldn't occur If it does there's an error. past: "%s ago", diff --git a/yarn.lock b/yarn.lock index 1f10ba15..7c3b01ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12083,10 +12083,10 @@ module-deps@^6.2.3: through2 "^2.0.0" xtend "^4.0.0" -moment@2.30.1, moment@^2.19.3: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== +moment@2.29.4, moment@^2.19.3: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== motion@10.16.2: version "10.16.2" From ad4b5fca775daac6daa7fda00d808a2a75f9abc2 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 2 Dec 2024 13:48:52 +0100 Subject: [PATCH 36/51] update england flag --- packages/frontend/src/components/LanguageModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index 2c09983b..c8db607d 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -21,7 +21,7 @@ interface IProps { } const languages = [ - { code: EnumLanguageCode.EN, name: "English", icon: "🏴󠁧󠁢󠁥󠁮󠁧󠁿" }, + { code: EnumLanguageCode.EN, name: "English", icon: "🇬🇧" }, { code: EnumLanguageCode.FR, name: "Français", icon: "🇫🇷" }, { code: EnumLanguageCode.ES, name: "Español", icon: "🇪🇸" }, { code: EnumLanguageCode.JA, name: "日本語", icon: "🇯🇵" }, From b84f173d582fbdfd293edb1c8bc24773af7a784c Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 3 Dec 2024 18:18:19 +0100 Subject: [PATCH 37/51] add turkish --- packages/frontend/src/api/types/language.ts | 1 + .../frontend/src/components/LanguageModal.tsx | 1 + packages/frontend/src/i18n.ts | 7 +- packages/frontend/src/locales/translation.ts | 394 ++++++++++++++++++ 4 files changed, 402 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/api/types/language.ts b/packages/frontend/src/api/types/language.ts index f9b61f79..f0fbf115 100644 --- a/packages/frontend/src/api/types/language.ts +++ b/packages/frontend/src/api/types/language.ts @@ -3,4 +3,5 @@ export enum EnumLanguageCode { FR = "fr", ES = "es", JA = "ja", + TR = "tr", } diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index c8db607d..fb35471d 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -25,6 +25,7 @@ const languages = [ { code: EnumLanguageCode.FR, name: "Français", icon: "🇫🇷" }, { code: EnumLanguageCode.ES, name: "Español", icon: "🇪🇸" }, { code: EnumLanguageCode.JA, name: "日本語", icon: "🇯🇵" }, + { code: EnumLanguageCode.TR, name: "Turkish", icon: "🇹🇷" }, ]; export const LanguageModal: React.FC = ({ diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index 9689b952..d3b81660 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -1,15 +1,17 @@ import i18n from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import { initReactI18next } from "react-i18next"; +import { EnumLanguageCode } from "./api/types/language"; import { Logger } from "./api/utils/logging"; import { translationEN, translationES, translationFR, translationJA, + translationTR, } from "./locales/translation"; -const resources = { +const resources: Record = { en: { translation: translationEN, }, @@ -22,6 +24,9 @@ const resources = { fr: { translation: translationFR, }, + tr: { + translation: translationTR, + }, }; i18n.use(LanguageDetector) diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 17d43120..5284e538 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -1573,3 +1573,397 @@ export const translationFR: typeof translationEN = { close_button: "Fermer", }, }; + +export const translationTR = { + navigation: { + searchBarPlaceholder: "Varlıklar, projeler, etkinlikler vb. için ara", + boards: "Panolar", + openBoardsLibrary: "Pano Kütüphanesini Aç", + widgets: "Araçlar", + sortBy: "Sırala", + menu: { + sign_in: "Giriş Yap", + sign_out: "Çıkış Yap", + sign_up: "Kaydol", + tutorial: "Eğitim", + language: "Dil", + about_us: "Hakkımızda", + version: "Sürüm", + commit: "Bağlantı", + }, + boards_library: { + title: "PANO KÜTÜPHANESİ", + description: + "İş akışınızı optimize etmek için panolar arasında geçiş yapın ve en sık kullandığınız panoları sabitleyin.", + custom_boards_title: "Özel Panolar", + custom_boards_description_with_auth: + "Boş bir pano oluşturun ve araçlar ekleyin", + custom_boards_description: + "Yeni panolar oluşturmak ve özel panolarınızı görmek için cüzdanınızı bağlayın ve doğrulayın", + }, + widgets_library: { + title: "Araç Kütüphanesi", + searchBarPlaceholder: "Araçları arayın", + allWidgets: "Tüm Araçlar", + }, + general: { + all: "Tümü", + general: "Genel", + nfts: "NFT'ler", + daos: "DAO'lar", + layer2: "Katman 2", + defi: "DeFi", + trading: "Ticaret", + popular: "Popüler", + name: "(A-Z)", + new: "Yeni", + feed: "Akış", + trending: "Trend", + readLater: "Daha Sonra Oku", + readMore: "Daha Fazla Oku", + bookmarks: "Yer İmleri", + timeRange: "Zaman Aralığı", + media: "Medya", + chains: "Zincirler", + protocols: "Protokoller", + less: "Daha Az", + more: "Daha Fazla", + }, + }, + widget: { + options: "Seçenekler", + close_options: "Seçenekleri Kapat", + expand: "Genişlet", + maximize: "Maksimize Et", + minimize: "Küçült", + screenshot: "Ekran Görüntüsü", + remove_widget: "Aracı Kaldır", + }, + tabs: { + news: "HABERLER", + portfolio: "PORTFÖY", + calendar: "TAKVİM", + feed: "Akış", + trending: "Trend", + read_later: "Daha Sonra Oku", + }, + buttons: { + connect_wallet: "Cüzdanı Bağla", + verify_wallet: "Cüzdanı Doğrula", + add_wallet: "Yeni Cüzdan Ekle", + disconnect_wallet: "Cüzdanı Bağlantıdan Kaldır", + enter_address: "Adres Girin", + save: "Kaydet", + notNow: "Şimdi Değil", + next: "İleri", + }, + portfolio: { + addAWallet: "Bir Cüzdan Adresi Ekle", + inputPlaceholder: "Bir Ethereum veya ENS adresi girin", + totalBalance: "Toplam Bakiye", + allWallets: "Tüm Cüzdanlar", + asset: "Varlık", + assets: "Varlıklar", + nfts: "NFT'ler", + balance: "Bakiye", + price: "Fiyat", + value: "Değer", + modals: { + title: "Cüzdan Bağlantısı", + soon: "(yakında)", + metamask: "Metamask", + selectingMethod: { + title: "Bir Cüzdan Sağlayıcı Seçin", + }, + prompted: { + title: "Cüzdanı Doğrula", + content: + "Cüzdanınız başarıyla bağlandı. Özelleştirilmiş panolarınızı kaydetmek için bir metin mesajı imzalayarak Alphaday'e giriş yapın.", + }, + connectionError: { + title: "Cüzdan Bağlantı Hatası", + content: + "Cüzdan sağlayıcınıza bağlanmaya çalışırken bir hata oluştu. Cüzdanınızın doğru şekilde ayarlandığından emin olun.", + }, + verificationError: { + title: "Cüzdan Doğrulama Hatası", + content: + "Kimlik doğrulama başarısız oldu. Cüzdanınız kilitli mi? Hesap değiştirdiniz mi?", + }, + genericError: { + title: "Beklenmeyen Hata", + content: + "Ups! Bir şeyler yanlış gitti. Lütfen daha sonra tekrar deneyin.", + }, + }, + }, + tutorials: { + switchView_title: "Panolar Arasında Geçiş Yap", + switchView_text: + "Farklı araçlarla düzenlenmiş panolar kullanarak iş akışınızı optimize edin veya kendi panonuzu oluşturun.", + walletView_title: "Bir Cüzdan Panosu Oluşturun", + walletView_text: + "Cüzdanınızdaki varlıklarla ilgili tüm bilgileri Alphaday üzerinde takip edin.", + useSeachBar_title: "Arama Çubuğu", + useSeachBar_text: + "Araçların içeriğini filtrelemek için favori tokenlarınızı, projelerinizi veya konularınızı arayın.", + reArrangeWidget_title: "Araçları Yeniden Düzenleyin", + reArrangeWidget_text: + "Araçları, kontrol panelinde konumlarını değiştirmek için üst çubuktan sürükleyip bırakın veya küçültmek için bir kez tıklayın.", + useWidgetLib_title: "Araç Kütüphanesi", + useWidgetLib_text: + "Araç Kütüphanesi'nde sizin için seçilebilecek onlarca faydalı araç bulunmaktadır.", + comeBack_text: + "Kullanıcı menüsünden istediğiniz zaman yeniden rehbere dönebilirsiniz.", + }, + market: { + title: "PİYASA", + line: "Çizgi", + candlestick: "Mum Grafiği", + no_coins_selected: "Seçilen etiketlere uygun coin bulunamadı", + history_error: + // eslint-disable-next-line no-template-curly-in-string + "${selectedChartRange} geçmişi bu coin için mevcut değil", + market_cap: "Piyasa Değeri", + volume_24h: "24 Saatlik Hacim", + }, + podcasts: { + channels: "Kanallar", + selected_channels: "Seçilen Kanallar", + all_channels: "Tüm Kanallar", + channels_input_placeholder: "Kanalları arayın", + }, + calendar: { + organizers: "Organizatörler", + speakers: "Konuşmacılar", + more_details: "Daha Fazla Detay", + noEvents: "Yaklaşan etkinlik bulunamadı", + event_types: { + conferences: "Konferanslar", + meetups: "Buluşmalar", + hackathons: "Hackathonlar", + product_releases: "Ürün Lansmanları", + dev_calls: "Geliştirici Çağrıları", + ico: "İlk Coin Teklifleri", + ido: "İlk Dex Teklifleri", + dao_votes: "DAO Oylamaları", + economic_events: "Ekonomik Etkinlikler", + community_calls: "Topluluk Çağrıları", + soft_forks: "Soft Forklar", + hard_forks: "Hard Forklar", + education: "Eğitim & Öğrenme", + interviews: "Röportajlar", + parties: "Partiler", + workshops: "Atölyeler", + unfiltered: "Filtresiz", + }, + }, + others: { + tag_options: { + auth: "ethereum, bitcoin, vb.", + unAuth: "Coinleri sabitlemek ve daha fazlası için kaydolun", + }, + change: "Değiştir", + name: "Ad", + your_nfts: "NFT'leriniz", + est_value: "Tahmini Değer", + tvl: "Toplam Kilitli Değer", + no_items_found: "Hiçbir öğe bulunamadı", + accept: "Kabul Et", + decline: "Reddet", + briefing_for: "Brifing için", + cookie: { + text: "Alphaday'in çalışması için temel çerezleri kullanıyoruz. Ziyaretinizi geliştirmek ve kişiselleştirmek ve web sitemizin performansını analiz etmek için diğer çerezleri kullanmak isteriz, ancak yalnızca kabul ederseniz.", + acceptAll: "Hepsini Kabul Et", + acceptEssential: "Sadece Gerekli Olanları Kabul Et", + }, + }, + verasity: { + token_name: "Token Adı", + token_ticker: "Token Simgesi", + sm_address: "Akıllı Sözleşme Adresi", + total_supply: "Toplam Arz", + max_circle_supply: "Maksimum Dolaşımdaki Arz", + circle_supply: "Dolaşımdaki Arz", + }, + messages: { + error: { + title: "Hata", + notFound: "Talep edilen sayfa bulunamadı.", + generic: "Talebiniz işlenirken bir hata oluştu.", + forbidden: "Bu sayfaya erişim izniniz yok.", + unauthorized: "Bu sayfaya erişim yetkiniz yok.", + notAuthenticated: + "Devam etmek için cüzdanınızı bağlayın ve doğrulayın.", + maxViews: "Maksimum izin verilen pano sayısını oluşturdunuz.", + maxWidgets: + "Panonuz izin verilen araç sayısından fazlasını içeriyor.", + maxViewWidgets: + "Bu panodaki bu araç türü için izin verilen sayıyı aştınız.", + requestFailed: + // eslint-disable-next-line no-template-curly-in-string + "${term} alınırken bir hata oluştu, lütfen daha sonra tekrar deneyin.", + boardHasNoRequiredWidget: + // eslint-disable-next-line no-template-curly-in-string + "${boardName} panosu, bu rota için gerekli olan ${SlugToWidgetNameMap[widget_template]} aracını içermiyor. Bu panoya ${SlugToWidgetNameMap[widget_template]} aracını ekleyin ve sayfayı yenileyin.", + back_to_home: "Ana Sayfaya Dön", + no_nfts_found: "Sağlanan cüzdan(lar) için NFT bulunamadı.", + no_video: "Seçili Video Yok", + something_wrong: "Bir şeyler yanlış gitti.", + }, + success: { + title: "Başarılı", + generic: "Talebiniz başarıyla işlendi.", + }, + queries: { + noResults: "Sonuç bulunamadı", + // eslint-disable-next-line no-template-curly-in-string + noMatchFound: "${item} eşleşmesi bulunamadı.", + }, + portfolio: { + signUp: "Portföyünüzü kaydetmek için kaydolun.", + connectWallet: "Kaydolmak için önce cüzdanınızı bağlayın.", + verifyWallet: + "Sahipliği doğrulamak ve yapılandırmanızı kaydetmek için ücretsiz bir mesaj imzalayın.", + }, + callToAction: { + signUpToBookmark: + // eslint-disable-next-line no-template-curly-in-string + "${item} öğesini yer imi olarak kaydetmek için kaydolun.", + }, + }, + countdown: { + labels: { + days: "Gün", + hours: "Saat", + minutes: "Dakika", + seconds: "Saniye", + }, + }, + datelocale: { + future: "%s içinde", + past: "%s önce", + s: "sn", + m: "dk", + mm: "dk", + h: "sa", + hh: "sa", + d: "g", + dd: "g", + w: "h", + M: "ay", + MM: "ay", + y: "y", + ytd: "yt", + yy: "y", + }, + gas: { + title: "Gas Fiyatı", + fast: "Hızlı", + standard: "Standart", + slow: "Yavaş", + beacon_chain_data: "Beacon Zinciri Verileri", + }, + qna: { + intro: "Bu araç, Alphaday'in topladığı kripto verilerine erişim arayüzüdür. Doğal dilde örneğin "en yüksek tvl'ye sahip proje hangisi?" gibi sorular yazarak bu verilere ulaşabilirsiniz.", + highlight: + "Bu aracı kullanmak için cüzdanınızı bağlayın ve doğrulayın.", + button: "Bir soru sorun", + }, + about_us: { + title: "Hakkımızda", + company_overview: { + title: "Şirket Hakkında:", + registered_name: "Kayıtlı Ad: Alphabox Solutions Pte. Ltd.", + registration_number: "Kayıt Numarası: 202136261C", + registered_office: + "Kayıtlı Ofis: 45 North Canal Road #01-01 Lew Building Singapur", + }, + contact_info: { + title: "İletişim Bilgileri:", + email: "E-posta Adresi: hello@alphaday.com", + xcom: "X.com: https://x.com/AlphadayHQ", + }, + legal_info: { + title: "Hukuki Bilgiler:", + terms: "Şartlar ve Koşullar: https://alphaday.com/terms", + privacy: "Gizlilik Politikası: https://alphaday.com/privacy", + }, + additional_resources: { + title: "Ek Kaynaklar:", + faqs: "SSS: alphaday.com", + feedback: "Geri Bildirim: https://forms.gle/RbrrLGdFPAeuNJhk9", + }, + mission: + "Alphaday'in misyonu, favori projelerinizi takip etmenizi, en son gelişmelerden haberdar olmanızı ve favori dApp'lerinizi kullanmanızı sağlamak için gerekli tüm araçları kolay kullanımlı, özelleştirilebilir bir panodan sunmaktır.", + close_button: "Kapat", + }, + error_page: { + offline: { + heading: { + text: "Şu an", + highlight: "çevrimdışısınız", + }, + description: + "Bağlantınızı kaybetmiş gibi görünüyorsunuz. Lütfen kontrol edip tekrar deneyin.", + }, + "503": { + heading: { + text: "Sistem", + highlight: "bakımı", + }, + description1: { + text: "Şu anda planlı bir bakım çalışması yapıyoruz. Kısa süre içinde geri döneceğiz! Bu arada, bizi", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + }, + description2: + "kontrol edebilirsiniz. Daha sonra tekrar kontrol etmeyi unutmayın.", + }, + "403": { + heading: { + text: "Yetkisiz", + highlight: "403", + }, + description: "Bu sayfaya erişim izniniz yok.", + }, + "404": { + heading: { + highlight: "404", + }, + description: "Üzgünüz, aradığınız sayfa bulunamadı.", + }, + default: { + description: { + text: "Bir şeyler yanlış gitti, kısa süre içinde geri döneceğiz! Bu arada, bizi", + link: { + text: "twitter", + url: "https://twitter.com/AlphadayHQ", + }, + textAfterLink: "üzerinden takip edebilirsiniz.", + }, + }, + }, + wallet_view: { + create_wallet_board: "Cüzdan Panosu Oluştur", + view_wallet_board: "Cüzdan Panosunu Görüntüle", + creating_wallet_board: "Cüzdan Panosu Oluşturuluyor", + }, + terms_of_service: { + titleOne: "Yasal Uyarı", + text_one: + "Alphaday, Uniswap dahil olmak üzere üçüncü taraf platformların ve araçların işleyişinden veya performansından sorumlu değildir. Uniswap Swap Aracı, kullanıcılarımız için bir kolaylık olarak sağlanmıştır. Alphaday, Uniswap üzerinden yapılan işlemleri kontrol etmez veya yönetmez ve Uniswap Swap Aracı'nın kullanılması sonucunda oluşabilecek herhangi bir kayıp veya hasardan sorumlu değildir. Kullanıcılar kendi araştırmalarını yapmalı ve kripto para ticareti yaparken dikkatli olmalıdır. Uniswap Swap Aracı'nı kullanarak, Uniswap Lab'ın", + text_two: "Hizmet Şartlarını", + text_three: "ve", + text_four: "Gizlilik Politikasını", + titleTwo: "Risk Açıklaması", + text_five: + "Kripto para ticareti, önemli riskler içerir ve yatırılan sermayenizin kaybına yol açabilir. Kaybetmeyi göze alabileceğinizden daha fazla yatırım yapmamalısınız ve dahil olunan riskleri tam olarak anladığınızdan emin olmalısınız. Fiyat dalgalanmaları ve kripto para piyasasının küresel doğası önemli kayıplara yol açabilir. Alphaday, herhangi bir yatırım tavsiyesi veya herhangi bir kripto para işleminin uygunluğuna dair önerilerde bulunmamaktadır. Tüm ticaret kararları kullanıcılar tarafından alınır ve Alphaday tarafından yönlendirilmez. Ticaret kararları almadan önce bir finansal danışmana danışın.", + }, + language: { + title: "Dil Seçin", + close_button: "Kapat", + }, +}; From 7a209c8d74df5cbe03732e22f5004a41fefa85b2 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 3 Dec 2024 19:01:37 +0100 Subject: [PATCH 38/51] add language button to menu --- .../profile-dropdown/ProfileDropdownWrapper.tsx | 5 ++++- packages/frontend/src/layout/LayoutHeader.tsx | 15 +++++++++++++++ packages/frontend/src/layout/MainLayout.tsx | 3 +++ packages/frontend/src/pages/index.tsx | 5 +++++ packages/ui-kit/src/assets/svg/language.svg | 3 +++ .../src/components/buttons/NavTabButton.tsx | 9 ++++++++- 6 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 packages/ui-kit/src/assets/svg/language.svg diff --git a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownWrapper.tsx b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownWrapper.tsx index 8e80d917..7c0a410e 100644 --- a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownWrapper.tsx +++ b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownWrapper.tsx @@ -122,7 +122,10 @@ const ProfileDropdownWrapper: React.FC = ({ - + {t("navigation.menu.language")} diff --git a/packages/frontend/src/layout/LayoutHeader.tsx b/packages/frontend/src/layout/LayoutHeader.tsx index 0d9d6337..49984a4b 100644 --- a/packages/frontend/src/layout/LayoutHeader.tsx +++ b/packages/frontend/src/layout/LayoutHeader.tsx @@ -21,6 +21,7 @@ import ViewsTabContainer from "src/containers/views-tab/ViewsTabContainer"; interface IProps { hideFeatures: boolean; toggleWidgetLib: (() => void) | undefined; + toggleLanguageModal: (() => void) | undefined; isBoardsLibOpen: boolean; setIsBoardsLibOpen: React.Dispatch>; setTutFocusElemRef?: @@ -31,6 +32,7 @@ interface IProps { const LayoutHeader: FC = ({ hideFeatures, toggleWidgetLib, + toggleLanguageModal, setTutFocusElemRef, isBoardsLibOpen, setIsBoardsLibOpen, @@ -75,6 +77,19 @@ const LayoutHeader: FC = ({ + + + {t("navigation.menu.language")} + + void; + toggleLanguageModal?: () => void; layoutState?: TUserViewWidget[][]; children?: React.ReactNode; setTutFocusElemRef?: @@ -20,6 +21,7 @@ const MainLayout: React.FC = ({ hideFooter, hideFeatures, toggleWidgetLib, + toggleLanguageModal, layoutState, setTutFocusElemRef, }) => { @@ -29,6 +31,7 @@ const MainLayout: React.FC = ({
dispatch(toggleLanguageModal()); + const { toggleWidgetLib } = useWidgetLib(); const { currentTutorial, setTutFocusElemRef } = useTutorial(); const isAuthenticated = useAppSelector(userStore.selectIsAuthenticated); @@ -283,6 +286,7 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { return ( + + diff --git a/packages/ui-kit/src/components/buttons/NavTabButton.tsx b/packages/ui-kit/src/components/buttons/NavTabButton.tsx index 27353917..6cfbacd6 100644 --- a/packages/ui-kit/src/components/buttons/NavTabButton.tsx +++ b/packages/ui-kit/src/components/buttons/NavTabButton.tsx @@ -1,11 +1,12 @@ import { FC } from "react"; import { ReactComponent as CloseSVG } from "../../assets/svg/close.svg"; +import { ReactComponent as LanguageSVG } from "../../assets/svg/language.svg"; import { ReactComponent as ViewsSVG } from "../../assets/svg/views.svg"; import { ReactComponent as WidgetsSVG } from "../../assets/svg/widgets.svg"; import { TabButton } from "./TabButton"; interface ButtonProps { - variant: "views" | "modules"; + variant: "views" | "modules" | "language"; open: boolean; disabled?: boolean; uppercase?: boolean; @@ -33,6 +34,12 @@ export const NavTabButton: FC = ({ className="fontGroup-supportBold bg-transparent border-none hover:bg-backgroundVariant200 px-4" {...restProps} > + {variant === "language" && + (open ? ( + + ) : ( + + ))} {variant === "modules" && (open ? ( From ea71ddb4b91510637a7f3b30c1ceef321b063a4a Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 23 Dec 2024 16:14:37 +0100 Subject: [PATCH 39/51] update yarn --- yarn.lock | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 7c3b01ae..fe710c74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12083,7 +12083,17 @@ module-deps@^6.2.3: through2 "^2.0.0" xtend "^4.0.0" -moment@2.29.4, moment@^2.19.3: +moment-with-locales-es6@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/moment-with-locales-es6/-/moment-with-locales-es6-1.0.1.tgz#c2eec19c902f98baa959afeacc34275bb61a3336" + integrity sha512-aKHuk7hHGVGk1X86rhu4aVwSEpBEwL3Lo5BEvZnqGueZeVK9pfpTrlLT3qN4A64vMkiKkxWpwQCcyg2YpoZGaQ== + +moment@2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +moment@^2.19.3: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== From 84d5899f1a2c0df2f46295b53011d201bad4cae8 Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 27 Dec 2024 07:24:57 +0100 Subject: [PATCH 40/51] reload on lang change --- .../src/api/hooks/usePreferredLanguage.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts index f01137f1..20144ef6 100644 --- a/packages/frontend/src/api/hooks/usePreferredLanguage.ts +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -1,16 +1,24 @@ +import { useRef } from "react"; import i18next from "i18next"; import moment from "moment-with-locales-es6"; import { useAppSelector } from "../store/hooks"; import { Logger } from "../utils/logging"; export const usePreferredLanguage = () => { - const selectedCode = useAppSelector( + const selectedLangCode = useAppSelector( (state) => state.ui.selectedLanguageCode ); - if (selectedCode) { - i18next.changeLanguage(selectedCode).catch((e) => { + const prevLangCodeRef = useRef(selectedLangCode); + + if (selectedLangCode) { + i18next.changeLanguage(selectedLangCode).catch((e) => { Logger.error("usePreferredLanguage::Error changing language::", e); }); - moment.locale(selectedCode); + moment.locale(selectedLangCode); + + if (selectedLangCode !== prevLangCodeRef.current) { + prevLangCodeRef.current = selectedLangCode; + location.reload(); + } } }; From 619fc268cf351f03684303dcbaada76e59bdad9d Mon Sep 17 00:00:00 2001 From: Xharles Date: Fri, 27 Dec 2024 08:27:49 +0100 Subject: [PATCH 41/51] remove unnecessary code --- .../frontend/src/components/LanguageModal.tsx | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index fb35471d..6b2dd462 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -7,17 +7,15 @@ import { ModalTitle, twMerge, } from "@alphaday/ui-kit"; -import i18next from "i18next"; import { useTranslation } from "react-i18next"; import { EnumLanguageCode } from "src/api/types/language"; -import { Logger } from "src/api/utils/logging"; import { ReactComponent as CheckedSVG } from "src/assets/icons/checkmark.svg"; interface IProps { onSetLanguageCode: (code: EnumLanguageCode) => void; selectedCode: string; showModal: boolean; - onClose?: () => void; + onClose: () => void; } const languages = [ @@ -37,18 +35,8 @@ export const LanguageModal: React.FC = ({ const { t } = useTranslation(); const handleLanguageSelect = (code: EnumLanguageCode) => { - i18next - .changeLanguage(code) - .then(() => { - onSetLanguageCode(code); - onClose?.(); - }) - .catch((e) => { - Logger.error( - "handleLanguageSelect::Error changing language::", - e - ); - }); + onSetLanguageCode(code); + onClose(); }; return ( From 9784913b7b6509c558a78e95144de01a75a8e1a8 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 14:47:59 +0100 Subject: [PATCH 42/51] make news nav items update on lang change --- packages/frontend/src/components/news/NewsModule.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/news/NewsModule.tsx b/packages/frontend/src/components/news/NewsModule.tsx index 20e753cc..7acb987b 100644 --- a/packages/frontend/src/components/news/NewsModule.tsx +++ b/packages/frontend/src/components/news/NewsModule.tsx @@ -20,7 +20,7 @@ interface INews { * This should ease adding new preference based buttons * auth can be set to true for buttons which require the user to be auth */ -const NEWS_NAV_ITEMS = [ +const translateNavItems = () => [ { label: translateLabels("Feed"), value: EItemFeedPreference.Last, @@ -47,12 +47,13 @@ const NewsModule: FC = memo(function NewsModule({ onBookmark, isAuthenticated, }) { + const newsNavItems = translateNavItems(); const NavItemPreference = - NEWS_NAV_ITEMS.find((item) => item.value === feedPreference) || - NEWS_NAV_ITEMS[0]; + newsNavItems.find((item) => item.value === feedPreference) || + newsNavItems[0]; const onTabOptionChange = (value: string) => { - const optionItem = NEWS_NAV_ITEMS.find((item) => item.value === value); + const optionItem = newsNavItems.find((item) => item.value === value); if (optionItem === undefined) { Logger.debug("NewsModule::Nav option item not found"); return; @@ -64,7 +65,7 @@ const NewsModule: FC = memo(function NewsModule({ <>
From 4251e15510e6e94143bd468c7033562f8809cf3f Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 15:03:17 +0100 Subject: [PATCH 43/51] make sort items update on lang change --- packages/frontend/src/api/utils/sortOptions.ts | 7 ++----- .../src/components/board-library/BoardsLibrary.tsx | 5 +++-- .../src/components/widget-library/WidgetLibrary.tsx | 5 +++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/frontend/src/api/utils/sortOptions.ts b/packages/frontend/src/api/utils/sortOptions.ts index 3ccc6cb5..9d07b82a 100644 --- a/packages/frontend/src/api/utils/sortOptions.ts +++ b/packages/frontend/src/api/utils/sortOptions.ts @@ -1,10 +1,7 @@ import { EItemsSortBy } from "../services"; import { translateLabels } from "./translationUtils"; -export const SORT_OPTIONS: { - label: string; - value: EItemsSortBy; -}[] = [ +export const generateSortOptions = () => [ { value: EItemsSortBy.Name, label: translateLabels("(A-Z)"), @@ -20,7 +17,7 @@ export const SORT_OPTIONS: { ]; export const getSortOptionValue = (value: string): EItemsSortBy | null => { - const option = SORT_OPTIONS.find((op) => op.value === value); + const option = generateSortOptions().find((op) => op.value === value); if (!option) { return null; } diff --git a/packages/frontend/src/components/board-library/BoardsLibrary.tsx b/packages/frontend/src/components/board-library/BoardsLibrary.tsx index 8a6b76d9..0c1ce8d7 100644 --- a/packages/frontend/src/components/board-library/BoardsLibrary.tsx +++ b/packages/frontend/src/components/board-library/BoardsLibrary.tsx @@ -16,7 +16,7 @@ import { import { TUserViewPreview, TViewMeta } from "src/api/types"; import { validateEthAddr } from "src/api/utils/accountUtils"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; -import { SORT_OPTIONS } from "src/api/utils/sortOptions"; +import { generateSortOptions } from "src/api/utils/sortOptions"; import { truncateWithEllipsis } from "src/api/utils/textUtils"; import { EToastRole, toast } from "src/api/utils/toastUtils"; import { @@ -153,6 +153,7 @@ const BoardsLibrary: FC = ({ subscribedViews, onEditView, }) => { + const sortOptions = generateSortOptions(); const { t } = useTranslation(); const customBoards = subscribedViews ?.filter((board) => !board.is_system_view) @@ -344,7 +345,7 @@ const BoardsLibrary: FC = ({
diff --git a/packages/frontend/src/components/widget-library/WidgetLibrary.tsx b/packages/frontend/src/components/widget-library/WidgetLibrary.tsx index a65a7610..c2a05c20 100644 --- a/packages/frontend/src/components/widget-library/WidgetLibrary.tsx +++ b/packages/frontend/src/components/widget-library/WidgetLibrary.tsx @@ -12,7 +12,7 @@ import { useTranslation } from "react-i18next"; import { EItemsSortBy, TRemoteWidgetCategory } from "src/api/services"; import { TWidget, TWidgetMini } from "src/api/types"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; -import { SORT_OPTIONS } from "src/api/utils/sortOptions"; +import { generateSortOptions } from "src/api/utils/sortOptions"; import { ETranslationValues, translateLabels, @@ -88,6 +88,7 @@ const WidgetLibrary: FC = ({ handlePaginate, }) => { const { t } = useTranslation(); + const sortOptions = generateSortOptions(); const handleFilterChange = (e: ChangeEvent) => { onFilter(e.target.value); }; @@ -263,7 +264,7 @@ const WidgetLibrary: FC = ({
From 8da1b8f292b2e356ddd92d8dc1a0ac62193f1b98 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 15:09:50 +0100 Subject: [PATCH 44/51] make translations change on language change --- .../src/components/podcast/PodcastModule.tsx | 14 +++++++------- packages/frontend/src/components/tvl/TvlModule.tsx | 12 +++++++----- .../frontend/src/components/video/VideoModule.tsx | 12 +++++++----- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/frontend/src/components/podcast/PodcastModule.tsx b/packages/frontend/src/components/podcast/PodcastModule.tsx index 57dc59c1..47720aec 100644 --- a/packages/frontend/src/components/podcast/PodcastModule.tsx +++ b/packages/frontend/src/components/podcast/PodcastModule.tsx @@ -39,7 +39,7 @@ const AUDIO_PLAYER_HEIGHT = 52; const CHANNELS_LIST_HEIGHT = 157; const CHANNELS_LIST_HEIGHT_COLLAPSED = 36; -const PODCAST_NAV_ITEMS = [ +const translateNavItems = () => [ { label: translateLabels("Feed"), value: EItemFeedPreference.Last, @@ -73,6 +73,8 @@ const PodcastModule: FC = ({ preferredChannelIds, setPreferredChannelIds, }) => { + const podcastNavItems = translateNavItems(); + const { squareRef, headerRef, @@ -115,13 +117,11 @@ const PodcastModule: FC = ({ ); const NavItemPreference = - PODCAST_NAV_ITEMS.find((item) => item.value === feedPreference) || - PODCAST_NAV_ITEMS[0]; + podcastNavItems.find((item) => item.value === feedPreference) || + podcastNavItems[0]; const onTabOptionChange = (value: string) => { - const optionItem = PODCAST_NAV_ITEMS.find( - (item) => item.value === value - ); + const optionItem = podcastNavItems.find((item) => item.value === value); if (optionItem === undefined) { Logger.debug("PodcastModule::Nav option item not found"); return; @@ -139,7 +139,7 @@ const PodcastModule: FC = ({ style={{ height: SWITCH_HEIGHT }} > diff --git a/packages/frontend/src/components/tvl/TvlModule.tsx b/packages/frontend/src/components/tvl/TvlModule.tsx index 836c63b6..72aea0a8 100644 --- a/packages/frontend/src/components/tvl/TvlModule.tsx +++ b/packages/frontend/src/components/tvl/TvlModule.tsx @@ -22,7 +22,7 @@ interface ITvl { onChangeProjectType: (type: ETVLItemPreference) => void; } -const TVL_NAV_ITEMS = [ +const translateNavItems = () => [ { label: translateLabels("Chains"), value: ETVLItemPreference.Chain, @@ -42,6 +42,8 @@ const TvlModule: FC = memo(function TvlModule({ selectedProjectType, onChangeProjectType, }) { + const tvlNavItems = translateNavItems(); + const [squareRef, { width }] = useElementSize(); const THRESHOLD = 475; @@ -62,11 +64,11 @@ const TvlModule: FC = memo(function TvlModule({ }; const selectedProjectOption = - TVL_NAV_ITEMS.find((item) => item.value === selectedProjectType) || - TVL_NAV_ITEMS[0]; + tvlNavItems.find((item) => item.value === selectedProjectType) || + tvlNavItems[0]; const onTabOptionChange = (value: string) => { - const optionItem = TVL_NAV_ITEMS.find((item) => item.value === value); + const optionItem = tvlNavItems.find((item) => item.value === value); if (optionItem === undefined) { Logger.debug( "TvlModule::onTabOptionsChange: Nav option item not found" @@ -85,7 +87,7 @@ const TvlModule: FC = memo(function TvlModule({
diff --git a/packages/frontend/src/components/video/VideoModule.tsx b/packages/frontend/src/components/video/VideoModule.tsx index 7cb4f691..16678ff2 100644 --- a/packages/frontend/src/components/video/VideoModule.tsx +++ b/packages/frontend/src/components/video/VideoModule.tsx @@ -31,7 +31,7 @@ const SWITCH_HEIGHT = 38; const CHANNELS_LIST_HEIGHT = 149; const CHANNELS_LIST_HEIGHT_COLLAPSED = 36; -const VIDEO_NAV_ITEMS = [ +const translateNavItems = () => [ { label: translateLabels("Feed"), value: EItemFeedPreference.Last, @@ -65,6 +65,8 @@ const VideoModule: FC = memo(function VideoModule({ preferredChannelIds, setPreferredChannelIds, }) { + const videoNavItems = translateNavItems(); + const { squareRef, headerRef, @@ -104,11 +106,11 @@ const VideoModule: FC = memo(function VideoModule({ }; const NavItemPreference = - VIDEO_NAV_ITEMS.find((item) => item.value === feedPreference) || - VIDEO_NAV_ITEMS[0]; + videoNavItems.find((item) => item.value === feedPreference) || + videoNavItems[0]; const onTabOptionChange = (value: string) => { - const optionItem = VIDEO_NAV_ITEMS.find((item) => item.value === value); + const optionItem = videoNavItems.find((item) => item.value === value); if (optionItem === undefined) { Logger.debug("VideoModule::Nav option item not found"); return; @@ -146,7 +148,7 @@ const VideoModule: FC = memo(function VideoModule({ style={{ height: SWITCH_HEIGHT }} > From fbbf1cc41123cbc4f0a6f007d282986626bbca6a Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 15:10:07 +0100 Subject: [PATCH 45/51] refetch queries on lang change --- .../src/api/hooks/usePreferredLanguage.ts | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts index 20144ef6..bcd541e8 100644 --- a/packages/frontend/src/api/hooks/usePreferredLanguage.ts +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -1,24 +1,37 @@ -import { useRef } from "react"; +import { useEffect, useRef } from "react"; import i18next from "i18next"; import moment from "moment-with-locales-es6"; +import { useDispatch } from "react-redux"; +import { alphadayApi } from "../services"; import { useAppSelector } from "../store/hooks"; import { Logger } from "../utils/logging"; export const usePreferredLanguage = () => { + const dispatch = useDispatch(); const selectedLangCode = useAppSelector( (state) => state.ui.selectedLanguageCode ); const prevLangCodeRef = useRef(selectedLangCode); - if (selectedLangCode) { - i18next.changeLanguage(selectedLangCode).catch((e) => { - Logger.error("usePreferredLanguage::Error changing language::", e); - }); - moment.locale(selectedLangCode); - - if (selectedLangCode !== prevLangCodeRef.current) { - prevLangCodeRef.current = selectedLangCode; - location.reload(); + useEffect(() => { + if (!selectedLangCode || i18next.language === selectedLangCode) { + return; } - } + moment.locale(selectedLangCode); + i18next + .changeLanguage(selectedLangCode) + .then(() => { + if (selectedLangCode !== prevLangCodeRef.current) { + prevLangCodeRef.current = selectedLangCode; + // Reset all queries + dispatch(alphadayApi.util.resetApiState()); + } + }) + .catch((e) => { + Logger.error( + "usePreferredLanguage::Error changing language::", + e + ); + }); + }, [selectedLangCode, dispatch]); }; From a32cb994f061302177b112183c62d441eb5ce3c2 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 15:17:31 +0100 Subject: [PATCH 46/51] fix unique key issue --- packages/frontend/src/components/LanguageModal.tsx | 5 ++++- packages/ui-kit/src/components/dropdown/SortBy.tsx | 2 +- packages/ui-kit/src/components/tabs/TabsBar.tsx | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index 6b2dd462..11c05d5a 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -46,7 +46,10 @@ export const LanguageModal: React.FC = ({ {languages.map(({ code, name, icon }) => ( -
+
); From 69243d0a71c6621b763fbe19679a9cf8e682376d Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 13 Jan 2025 19:05:47 +0100 Subject: [PATCH 49/51] add language header --- packages/frontend/src/api/services/alphadayApi.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/frontend/src/api/services/alphadayApi.ts b/packages/frontend/src/api/services/alphadayApi.ts index 5d72f76b..812cb69e 100644 --- a/packages/frontend/src/api/services/alphadayApi.ts +++ b/packages/frontend/src/api/services/alphadayApi.ts @@ -1,4 +1,5 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import i18next from "i18next"; import { TUserAuth } from "src/api/types"; import { Logger } from "src/api/utils/logging"; import CONFIG from "../../config/config"; @@ -22,6 +23,7 @@ export const alphadayApi = createApi({ headers.set("Version", CONFIG.APP.VERSION); headers.set("X-App-Id", CONFIG.APP.X_APP_ID); headers.set("X-App-Secret", CONFIG.APP.X_APP_SECRET); + headers.set("Accept-Language", i18next.language); // @ts-expect-error const authState = getState().user.auth as TUserAuth | null; if (authState != null && authState?.token !== undefined) { From 4df7325f2cf3055cec23ff0117c8691b8bf8a4ac Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 14 Jan 2025 12:50:04 +0100 Subject: [PATCH 50/51] update date --- packages/frontend/src/api/utils/dateUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/api/utils/dateUtils.ts b/packages/frontend/src/api/utils/dateUtils.ts index 651f170a..c6f3eba6 100644 --- a/packages/frontend/src/api/utils/dateUtils.ts +++ b/packages/frontend/src/api/utils/dateUtils.ts @@ -8,7 +8,7 @@ import moment from "moment-with-locales-es6"; */ export const computeDuration = (date: string | Date): string => { - moment.updateLocale("en", { + moment.updateLocale(i18next.language, { relativeTime: { future: `${i18next.t("datelocale.future")}`, // this shouldn't occur If it does there's an error. past: `${i18next.t("datelocale.past")}`, From 533d2b33ee3bd7155e87f5fc395dbe8b2b7da3fe Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 14 Jan 2025 14:04:07 +0100 Subject: [PATCH 51/51] key lettering case update --- .../frontend/src/api/hooks/useTutorial.ts | 19 +- .../frontend/src/components/AboutUsModal.tsx | 32 +- .../frontend/src/components/LanguageModal.tsx | 2 +- .../board-library/BoardsLibrary.tsx | 6 +- .../event-details/components/parts.tsx | 2 +- .../src/components/calendarCategories.ts | 36 +- .../client/VerasityTokenomicsModule.tsx | 12 +- .../custom-modules/CustomTableModule.tsx | 2 +- .../src/components/error/GeneralError.tsx | 2 +- .../src/components/gas/GasPriceTable.tsx | 2 +- .../src/components/market/MarketModule.tsx | 8 +- .../podcast/PodcastChannelsList.tsx | 8 +- .../components/portfolio/PortfolioModule.tsx | 2 +- .../src/components/portfolio/TopBar.tsx | 6 +- .../src/components/portfolio/nfts/NftCard.tsx | 2 +- .../src/components/portfolio/nfts/NftList.tsx | 4 +- .../src/components/summary/SummaryModule.tsx | 2 +- .../components/video/VideoChannelsList.tsx | 8 +- .../src/components/video/VideoPlayer.tsx | 4 +- .../widget-library/WidgetLibrary.tsx | 6 +- .../src/containers/base/BaseContainerMenu.tsx | 2 +- .../containers/base/BaseContainerOptions.tsx | 6 +- .../src/containers/error/ErrorContainer.tsx | 36 +- .../ProfileDropdownWrapper.tsx | 8 +- .../profile-dropdown/WalletViewButton.tsx | 8 +- .../src/containers/tutorial/staticData.ts | 29 +- .../src/containers/uniswap/termsOfService.tsx | 4 +- packages/frontend/src/locales/translation.ts | 772 +++++++++--------- 28 files changed, 516 insertions(+), 514 deletions(-) diff --git a/packages/frontend/src/api/hooks/useTutorial.ts b/packages/frontend/src/api/hooks/useTutorial.ts index 2701e057..6fdee7ea 100644 --- a/packages/frontend/src/api/hooks/useTutorial.ts +++ b/packages/frontend/src/api/hooks/useTutorial.ts @@ -1,4 +1,5 @@ -import { useCallback } from "react"; +import { useCallback, useMemo } from "react"; +import { useTranslation } from "react-i18next"; import { setCurrentTutorialTip, setStoreShowTutorial } from "src/api/store"; import { useAppSelector, useAppDispatch } from "src/api/store/hooks"; import { tutorials } from "src/containers/tutorial/staticData"; @@ -20,6 +21,7 @@ interface ITutorial { } export const useTutorial: () => ITutorial = () => { + const { t } = useTranslation(); const dispatch = useAppDispatch(); const { tutFocusElemRef, setTutFocusElemRef } = useTutorialContext(); const { isFullSize } = useViewRoute(); @@ -27,9 +29,20 @@ export const useTutorial: () => ITutorial = () => { EFeaturesRegistry.WalletBoard ); + const translate = useCallback( + (key: string) => { + return t(`tutorials.${key}`); + }, + [t] + ); + const translatedTutorials = useMemo( + () => tutorials(translate), + [translate] + ); + const allowedTutorials = isWalletBoardAllowed - ? tutorials - : tutorials.filter( + ? translatedTutorials + : translatedTutorials.filter( (tutorial) => tutorial.id !== ETutorialTipId.WalletView ); diff --git a/packages/frontend/src/components/AboutUsModal.tsx b/packages/frontend/src/components/AboutUsModal.tsx index 7d2ec5bd..81ab8e1c 100644 --- a/packages/frontend/src/components/AboutUsModal.tsx +++ b/packages/frontend/src/components/AboutUsModal.tsx @@ -18,25 +18,25 @@ export const AboutUsModal: React.FC = ({ showModal, onClose }) => { return ( - {t("about_us.title")} + {t("aboutUs.title")} -
{t("about_us.company_overview.title")}
+
{t("aboutUs.companyOverview.title")}

- {t("about_us.company_overview.registered_name")} + {t("aboutUs.companyOverview.registeredName")}
- {t("about_us.company_overview.registration_number")} + {t("aboutUs.companyOverview.registrationNumber")}
- {t("about_us.company_overview.registered_office")} + {t("aboutUs.companyOverview.registeredOffice")}

-
{t("about_us.contact_info.title")}
+
{t("aboutUs.contactInfo.title")}

- {t("about_us.contact_info.email")}{" "} + {t("aboutUs.contactInfo.email")}{" "} hello@alphaday.com
- {t("about_us.contact_info.xcom")}{" "} + {t("aboutUs.contactInfo.xcom")}{" "} = ({ showModal, onClose }) => {

-
{t("about_us.legal_info.title")}
+
{t("aboutUs.legalInfo.title")}

- {t("about_us.legal_info.terms")}{" "} + {t("aboutUs.legalInfo.terms")}{" "} = ({ showModal, onClose }) => { https://alphaday.com/terms
- {t("about_us.legal_info.privacy")}{" "} + {t("aboutUs.legalInfo.privacy")}{" "} = ({ showModal, onClose }) => {

-
{t("about_us.additional_resources.title")}
+
{t("aboutUs.additionalResources.title")}

- {t("about_us.additional_resources.faqs")}{" "} + {t("aboutUs.additionalResources.faqs")}{" "} = ({ showModal, onClose }) => { alphaday.com
- {t("about_us.additional_resources.feedback")}{" "} + {t("aboutUs.additionalResources.feedback")}{" "} = ({ showModal, onClose }) => { https://forms.gle/RbrrLGdFPAeuNJhk9

-

{t("about_us.mission")}

+

{t("aboutUs.mission")}

diff --git a/packages/frontend/src/components/LanguageModal.tsx b/packages/frontend/src/components/LanguageModal.tsx index 11c05d5a..60d24e2e 100644 --- a/packages/frontend/src/components/LanguageModal.tsx +++ b/packages/frontend/src/components/LanguageModal.tsx @@ -81,7 +81,7 @@ export const LanguageModal: React.FC = ({ diff --git a/packages/frontend/src/components/board-library/BoardsLibrary.tsx b/packages/frontend/src/components/board-library/BoardsLibrary.tsx index 0c1ce8d7..5759029c 100644 --- a/packages/frontend/src/components/board-library/BoardsLibrary.tsx +++ b/packages/frontend/src/components/board-library/BoardsLibrary.tsx @@ -254,16 +254,16 @@ const BoardsLibrary: FC = ({ {t( - "navigation.boards_library.custom_boards_title" + "navigation.boards_library.customBoardsTitle" )} {isAuthenticated ? t( - "navigation.boards_library.custom_boards_description_with_auth" + "navigation.boards_library.customBoardsDescriptionWithAuth" ) : t( - "navigation.boards_library.custom_boards_description" + "navigation.boards_library.customBoardsDescription" )} diff --git a/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx b/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx index 19661ca0..ae364073 100644 --- a/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx +++ b/packages/frontend/src/components/calendar/calendar-full/event-details/components/parts.tsx @@ -55,7 +55,7 @@ export const EventLink: FC<{ event: TEventDetails }> = ({ event }) => { - {t("calendar.more_details")} + {t("calendar.moreDetails")} diff --git a/packages/frontend/src/components/calendarCategories.ts b/packages/frontend/src/components/calendarCategories.ts index 7c210bbd..347a7736 100644 --- a/packages/frontend/src/components/calendarCategories.ts +++ b/packages/frontend/src/components/calendarCategories.ts @@ -4,94 +4,94 @@ import { TEventCategory } from "./types"; export const typeOptions: { value: string; name: string; color: string }[] = [ { value: "Co", - name: i18next.t("calendar.event_types.conferences"), + name: i18next.t("calendar.eventTypes.conferences"), color: "rgb(185, 225, 135)", }, { value: "MU", - name: i18next.t("calendar.event_types.meetups"), + name: i18next.t("calendar.eventTypes.meetups"), color: "rgb(117, 71, 247)", }, { value: "Hk", - name: i18next.t("calendar.event_types.hackathons"), + name: i18next.t("calendar.eventTypes.hackathons"), color: "rgb(162, 117, 84)", }, { value: "PR", - name: i18next.t("calendar.event_types.product_releases"), + name: i18next.t("calendar.eventTypes.productReleases"), color: "rgb(249, 132, 104)", }, { value: "DC", - name: i18next.t("calendar.event_types.developer_conferences"), + name: i18next.t("calendar.eventTypes.developer_conferences"), color: "rgb(224, 135, 135)", }, { value: "ICO", - name: i18next.t("calendar.event_types.icos"), + name: i18next.t("calendar.eventTypes.icos"), color: "rgb(144, 190, 109)", }, { value: "IDO", - name: i18next.t("calendar.event_types.idos"), + name: i18next.t("calendar.eventTypes.idos"), color: "rgb(67, 170, 139)", }, { value: "DV", - name: i18next.t("calendar.event_types.dev_updates"), + name: i18next.t("calendar.eventTypes.dev_updates"), color: "rgb(77, 144, 142)", }, { value: "EE", - name: i18next.t("calendar.event_types.exchange_events"), + name: i18next.t("calendar.eventTypes.exchange_events"), color: "rgb(87, 117, 144)", }, { value: "CC", - name: i18next.t("calendar.event_types.community_calls"), + name: i18next.t("calendar.eventTypes.communityCalls"), color: "rgb(39, 125, 161)", }, { value: "SF", - name: i18next.t("calendar.event_types.soft_forks"), + name: i18next.t("calendar.eventTypes.softForks"), color: "rgb(253, 153, 153)", }, { value: "HF", - name: i18next.t("calendar.event_types.hard_forks"), + name: i18next.t("calendar.eventTypes.hardForks"), color: "rgb(198, 179, 14)", }, { value: "EDU", - name: i18next.t("calendar.event_types.education"), + name: i18next.t("calendar.eventTypes.education"), color: "rgb(71, 127, 247)", }, { value: "INT", - name: i18next.t("calendar.event_types.interviews"), + name: i18next.t("calendar.eventTypes.interviews"), color: "rgb(17, 157, 164)", }, { value: "PY", - name: i18next.t("calendar.event_types.partnerships"), + name: i18next.t("calendar.eventTypes.partnerships"), color: "rgb(216, 227, 118)", }, { value: "WK", - name: i18next.t("calendar.event_types.workshops"), + name: i18next.t("calendar.eventTypes.workshops"), color: "rgb(126, 74, 15)", }, { value: "Unfiltered", - name: i18next.t("calendar.event_types.unfiltered"), + name: i18next.t("calendar.eventTypes.unfiltered"), color: "rgb(17, 78, 198)", }, ]; export const defaultEventCategory: TEventCategory = { value: "Unfiltered", - label: i18next.t("calendar.event_types.unfiltered"), + label: i18next.t("calendar.eventTypes.unfiltered"), category: "Unfiltered", color: "rgb(17, 78, 198)", }; diff --git a/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx b/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx index 65694dac..d98ef7d0 100644 --- a/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx +++ b/packages/frontend/src/components/client/VerasityTokenomicsModule.tsx @@ -225,19 +225,19 @@ const PieChartModule: FC = ({ data }) => {
- {t("verasity.token_name")}: + {t("verasity.tokenName")}: {" "} {name}
- {t("verasity.token_ticker")}: + {t("verasity.tokenTicker")}: {" "} ${ticker}
- {t("verasity.sm_address")}: + {t("verasity.smAddress")}: {" "} = ({ data }) => {
- {t("verasity.total_supply")}: + {t("verasity.totalSupply")}: {" "} {totalSupply}
- {t("verasity.max_circle_supply")}: + {t("verasity.max_circleSupply")}: {" "} {maxSupply}
- {t("verasity.circle_supply")}: + {t("verasity.circleSupply")}: {" "} {supply}
diff --git a/packages/frontend/src/components/custom-modules/CustomTableModule.tsx b/packages/frontend/src/components/custom-modules/CustomTableModule.tsx index f4f9d71e..18808752 100644 --- a/packages/frontend/src/components/custom-modules/CustomTableModule.tsx +++ b/packages/frontend/src/components/custom-modules/CustomTableModule.tsx @@ -74,7 +74,7 @@ const CustomTableModule: FC = ({ if (items.length === 0) { return (
-

{t("others.no_items_found")}

+

{t("others.noItemsFound")}

); } diff --git a/packages/frontend/src/components/error/GeneralError.tsx b/packages/frontend/src/components/error/GeneralError.tsx index d9f53155..968450bd 100644 --- a/packages/frontend/src/components/error/GeneralError.tsx +++ b/packages/frontend/src/components/error/GeneralError.tsx @@ -28,7 +28,7 @@ const GeneralError: FC<{ children?: React.ReactNode }> = ({ children }) => { alt="alphaday logo" className="m-0 mr-2 h-5" />{" "} - {t("back_to_home")} + {t("backTo_home")} )}
diff --git a/packages/frontend/src/components/gas/GasPriceTable.tsx b/packages/frontend/src/components/gas/GasPriceTable.tsx index 9999cc92..c546701d 100644 --- a/packages/frontend/src/components/gas/GasPriceTable.tsx +++ b/packages/frontend/src/components/gas/GasPriceTable.tsx @@ -62,7 +62,7 @@ const GasPriceTable: FC = ({ return ( <>
- {t("gas.beacon_chain_data")} + {t("gas.beaconChainData")}
diff --git a/packages/frontend/src/components/market/MarketModule.tsx b/packages/frontend/src/components/market/MarketModule.tsx index c61fd322..72f18a4f 100644 --- a/packages/frontend/src/components/market/MarketModule.tsx +++ b/packages/frontend/src/components/market/MarketModule.tsx @@ -71,14 +71,14 @@ const MarketModule: FC = ({ if (selectedMarket === undefined) { chartComponent = (
- {t("market.no_coins_selected")} + {t("market.noCoinSelected")}
); } else if (priceHistoryData === undefined && !isLoadingHistory) { chartComponent = (
{globalMessages.error.requestFailed( - evaluateTemplate(t("market.history_error"), { + evaluateTemplate(t("market.historyError"), { selectedChartRange, }) )} @@ -175,7 +175,7 @@ const MarketModule: FC = ({ >
- {t("market.market_cap")} + {t("market.marketCap")} @@ -191,7 +191,7 @@ const MarketModule: FC = ({
- {t("market.volume_24h")} + {t("market.volume24h")} diff --git a/packages/frontend/src/components/podcast/PodcastChannelsList.tsx b/packages/frontend/src/components/podcast/PodcastChannelsList.tsx index 0a536194..9e27a288 100644 --- a/packages/frontend/src/components/podcast/PodcastChannelsList.tsx +++ b/packages/frontend/src/components/podcast/PodcastChannelsList.tsx @@ -114,7 +114,7 @@ const PodcastChannelsList: FC = ({ > {showAllChannels - ? t("podcasts.selected_channels") + ? t("podcasts.selectedChannels") : t("podcasts.channels")}
@@ -215,15 +215,13 @@ const PodcastChannelsList: FC = ({ {!isLoadingChannels && (

- {t("podcasts.all_channels")} + {t("podcasts.allChannels")}

setSearchState(e.target.value)} - placeholder={t( - "podcasts.channels_input_placeholder" - )} + placeholder={t("podcasts.channelsInputPlaceholder")} id="search-podcast-channels" name="search podcast channels" /> diff --git a/packages/frontend/src/components/portfolio/PortfolioModule.tsx b/packages/frontend/src/components/portfolio/PortfolioModule.tsx index 18b7aea9..662a7574 100644 --- a/packages/frontend/src/components/portfolio/PortfolioModule.tsx +++ b/packages/frontend/src/components/portfolio/PortfolioModule.tsx @@ -181,7 +181,7 @@ const Portfolio: FC = ({ onClick={onConnectWallet} className=" max-w-[49%]" > - {t("buttons.connect_wallet")} + {t("buttons.connectWallet")}