diff --git a/.env.example b/.env.example index 08e8ef5b97d..b16d4a8b822 100644 --- a/.env.example +++ b/.env.example @@ -29,7 +29,7 @@ IS_PREVIEW_DEPLOY=false # Build pages only for the specified langs. Leave it empty to build all the langs # e.g. `en,fr` will only build English and French pages # Note: always include `en` as it is the default lang of the site -BUILD_LOCALES= +NEXT_PUBLIC_BUILD_LOCALES= # If resource constraints are being hit during builds, change LIMIT_CPUS to a # fixed number of CPUs (e.g. 2) to limit the demand during build time diff --git a/.eslintrc.json b/.eslintrc.json index c8813d5bbf6..02e6c67aab5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -23,8 +23,6 @@ // Packages. `react` related packages come first. // Also, put `react-icons` in sorting order not with `react` ["^react(?!-.)$", "^\\w", "^@\\w"], - // The Chakra theme directory if imported to story file or other places - ["^@/@chakra-ui"], // From the `types` directory. ["^@/lib/types", "^@/lib/interfaces"], // From the `components` directory. @@ -65,17 +63,6 @@ "varsIgnorePattern": "^_$" } ], - "unused-imports/no-unused-imports-ts": "warn", - "no-restricted-imports": [ - "warn", - { - "paths": [ - { - "name": "react-i18next", - "message": "Please use next-i18next instead of react-i18next." - } - ] - } - ] + "unused-imports/no-unused-imports-ts": "warn" } } diff --git a/.github/ISSUE_TEMPLATE/suggest_quiz.yaml b/.github/ISSUE_TEMPLATE/suggest_quiz.yaml index 7ca8c1d7b93..af037b47770 100644 --- a/.github/ISSUE_TEMPLATE/suggest_quiz.yaml +++ b/.github/ISSUE_TEMPLATE/suggest_quiz.yaml @@ -1,5 +1,5 @@ name: Suggest quiz -description: Add, update, delete questions for a quiz on ethereum.osg +description: Add, update, delete questions for a quiz on ethereum.org title: Add/Update/Delete quiz question labels: ["feature ✨", "quiz 📚"] body: diff --git a/.github/labeler.yml b/.github/labeler.yml index e6d58364be9..db08d5281e7 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -16,7 +16,6 @@ "config ⚙️": - i18n.config.json - next.config.js - - next-i18next.config,js - next-sitemap.config.js - tsconfig.json - .nvmrc diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 3054c265b98..7422a81a40f 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -15,7 +15,6 @@ on: - "src/components/**/*" - "src/pages/**/*" - "src/layouts/**/*" - - "src/@chakra-ui/**/*" - ".storybook/**/*" - "tailwind.config.ts" - "src/styles/**/*" diff --git a/.storybook/ChakraDecorator.tsx b/.storybook/ChakraDecorator.tsx deleted file mode 100644 index dbde5985d55..00000000000 --- a/.storybook/ChakraDecorator.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useEffect, useMemo, useState } from "react" -import { - ChakraBaseProvider, - extendBaseTheme, - useColorMode, -} from "@chakra-ui/react" -import type { Decorator } from "@storybook/react" - -import theme from "../src/@chakra-ui/theme" - -import i18n from "./i18next" - -type DecoratorProps = Parameters - -const ColorModeSync = ({ context }: { context: DecoratorProps[1] }) => { - const { setColorMode } = useColorMode() - - useEffect(() => { - const isDarkMode = localStorage.getItem("chakra-ui-color-mode") === "dark" - - context.globals.colorMode = isDarkMode ? "dark" : "light" - }, []) - - useEffect(() => { - setColorMode(context.globals.colorMode) - }, [setColorMode, context]) - - return null -} - -/** - * This is a custom local setup of the official Chakra UI Storybook addon. - * - * A local version was created in response to provide a better sync between - * updated local direction to the Chakra theme. - * - * (This would most likely not be updated in the addon due to ongoing creation of Chakra v3 at the time this - * setup was created.) - * - * Will be deprecated and removed when Chakra v3 is available for migration. - * - */ -export const ChakraDecorator: Decorator = (getStory, context) => { - const [dir, updateDir] = useState<"ltr" | "rtl">() - - i18n.on("languageChanged", (locale) => { - const direction = i18n.dir(locale) - document.documentElement.dir = direction - updateDir(direction) - }) - - const themeWithDirectionOverride = useMemo(() => { - return extendBaseTheme({ direction: dir }, theme) - }, [dir]) - - return ( - - <> - - {getStory(context)} - - - ) -} diff --git a/.storybook/main.ts b/.storybook/main.ts index 02d785aefdc..e0f73e81f1c 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,5 +1,4 @@ import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin" -import { propNames } from "@chakra-ui/react" import type { StorybookConfig } from "@storybook/nextjs" /** @@ -17,8 +16,8 @@ import type { StorybookConfig } from "@storybook/nextjs" const config: StorybookConfig = { stories: [ "../src/components/**/*.stories.{ts,tsx}", - "../src/@chakra-ui/stories/*.stories.tsx", "../src/layouts/stories/*.stories.tsx", + "../src/styles/*.stories.tsx", ], addons: [ "@storybook/addon-links", @@ -29,9 +28,9 @@ const config: StorybookConfig = { }, }, "@storybook/addon-interactions", - "storybook-react-i18next", "@storybook/addon-themes", "@chromatic-com/storybook", + "storybook-next-intl", ], staticDirs: ["../public"], framework: { @@ -41,11 +40,6 @@ const config: StorybookConfig = { docs: { autodocs: "tag", }, - refs: { - "@chakra-ui/react": { - disable: true, - }, - }, webpackFinal: async (config) => { config.module = config.module || {} config.module.rules = config.module.rules || [] @@ -79,23 +73,6 @@ const config: StorybookConfig = { typescript: { reactDocgenTypescriptOptions: { shouldExtractLiteralValuesFromEnum: true, - /** - * For handling bloated controls table of Chakra Props - * - * https://github.com/chakra-ui/chakra-ui/issues/2009#issuecomment-852793946 - */ - propFilter: (prop) => { - const excludedPropNames = propNames.concat([ - "as", - "apply", - "sx", - "__css", - ]) - const isStyledSystemProp = excludedPropNames.includes(prop.name) - const isHTMLElementProp = - prop.parent?.fileName.includes("node_modules") ?? false - return !(isStyledSystemProp || isHTMLElementProp) - }, }, reactDocgen: "react-docgen-typescript", diff --git a/.storybook/modes.ts b/.storybook/modes.ts index 086d07ab0d1..ed683104212 100644 --- a/.storybook/modes.ts +++ b/.storybook/modes.ts @@ -1,6 +1,6 @@ import pickBy from "lodash/pickBy" -import { baseLocales } from "./i18next" +import { baseLocales } from "./next-intl" import { breakpointSet } from "./preview" export const viewportModes = breakpointSet.reduce<{ diff --git a/.storybook/i18next.ts b/.storybook/next-intl.ts similarity index 71% rename from .storybook/i18next.ts rename to .storybook/next-intl.ts index a2fbde38908..4d2a7844b37 100644 --- a/.storybook/i18next.ts +++ b/.storybook/next-intl.ts @@ -1,7 +1,3 @@ -import i18n, { Resource } from "i18next" -// eslint-disable-next-line no-restricted-imports -import { initReactI18next } from "react-i18next" - export const baseLocales = { en: { title: "English", left: "En" }, zh: { title: "中国人", left: "Zh" }, @@ -32,7 +28,7 @@ const supportedLngs = Object.keys(baseLocales) /** * Taking the ns array and generating those files for each language available. */ -const resources: Resource = ns.reduce((acc, n) => { +const messagesByLocale = ns.reduce((acc, n) => { supportedLngs.forEach((lng) => { if (!acc[lng]) acc[lng] = {} @@ -57,16 +53,18 @@ const resources: Resource = ns.reduce((acc, n) => { return acc }, {}) -console.log("🚀 ~ constresources:Resource=ns.reduce ~ resources:", resources) +console.log( + "🚀 ~ constresources:Resource=ns.reduce ~ resources:", + messagesByLocale +) -i18n.use(initReactI18next).init({ - debug: true, - fallbackLng: "en", - interpolation: { escapeValue: false }, - react: { useSuspense: false }, - supportedLngs, - resources, - defaultNS: "common", -}) +const nextIntl = { + defaultLocale: "en", + messagesByLocale, + getMessageFallback: ({ key }: { key: string }) => { + const keyOnly = key.split(".").pop() + return keyOnly || key + }, +} -export default i18n +export default nextIntl diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 191fa7888d7..1095a3011c2 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -5,7 +5,7 @@ import type { Preview } from "@storybook/react" import ThemeProvider from "@/components/ThemeProvider" import { TooltipProvider } from "@/components/ui/tooltip" -import i18n, { baseLocales } from "./i18next" +import nextIntl, { baseLocales } from "./next-intl" import { withNextThemes } from "./withNextThemes" import "../src/styles/global.css" @@ -47,7 +47,7 @@ const preview: Preview = { ), ], parameters: { - i18n, + nextIntl, controls: { matchers: { color: /(background|color)$/i, diff --git a/.storybook/types.ts b/.storybook/types.ts deleted file mode 100644 index 1b8116ee78a..00000000000 --- a/.storybook/types.ts +++ /dev/null @@ -1,83 +0,0 @@ -import type { StyleConfig, ThemingProps } from "@chakra-ui/react" -import type { ArgTypes } from "@storybook/react" - -// Type declarations below pulled directly from `@chakra-ui/storybook-addon` -// with some alteration -// (Subject to deprecation and removal upon release of Chakra v3) - -/** - * `keyof` alternative which omits non-string keys - */ -type KeyOf = [T] extends [never] - ? never - : T extends object - ? Extract - : never - -export type ThemingArgTypeKey = "variant" | "size" - -/** - * Create Storybook controls based on a Chakra UI theme component. - * - * @example - * export default { - * title: "Components / Forms / Button", - * argTypes: getThemingArgTypes(theme, "Button"), - * } - * - * @example full example - * import { Meta, StoryFn } from "@storybook/react" - * import { getThemingArgTypes } from "@chakra-ui/storybook-addon" - * import { theme } from "" - * - * export default { - * title: "Components / Forms / Button", - * argTypes: { - * ...getThemingArgTypes(theme, "Button"), - * children: "string" - * }, - * args: { children: "Button" }, - * } as Meta - * - * interface StoryProps extends ThemingProps<"Button"> { - * children?: React.ReactNode - * } - * - * export const Basic: StoryFn = (props) => + ) }, diff --git a/src/components/CentralizedExchanges/index.tsx b/src/components/CentralizedExchanges/index.tsx index 555e3c6bdd1..d769a0f37e3 100644 --- a/src/components/CentralizedExchanges/index.tsx +++ b/src/components/CentralizedExchanges/index.tsx @@ -1,5 +1,4 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { ChildOnlyProp, Lang } from "@/lib/types" @@ -14,6 +13,7 @@ import { WEBSITE_EMAIL } from "@/lib/constants" import Select from "../Select" import { useCentralizedExchanges } from "@/hooks/useCentralizedExchanges" +import { useTranslation } from "@/hooks/useTranslation" const ListContainer = (props: ChildOnlyProp) => (
@@ -66,7 +66,7 @@ const CentralizedExchanges = ({ lastDataUpdateDate, }: CentralizedExchangesProps) => { const { t } = useTranslation("page-get-eth") - const { locale } = useRouter() + const locale = useLocale() const { selectOptions, handleSelectChange, diff --git a/src/components/CodeModal.tsx b/src/components/CodeModal.tsx index 6a12880b449..f2631ea05c0 100644 --- a/src/components/CodeModal.tsx +++ b/src/components/CodeModal.tsx @@ -1,5 +1,4 @@ import { Children, type ReactElement } from "react" -import { useTranslation } from "next-i18next" import { IoMdCopy } from "react-icons/io" import { MdCheck } from "react-icons/md" @@ -13,6 +12,7 @@ import { } from "./ui/dialog-modal" import { useClipboard } from "@/hooks/useClipboard" +import { useTranslation } from "@/hooks/useTranslation" type CodeModalProps = { title: string diff --git a/src/components/Codeblock.tsx b/src/components/Codeblock.tsx index ef6b7b9ca55..5273fbcf4bd 100644 --- a/src/components/Codeblock.tsx +++ b/src/components/Codeblock.tsx @@ -1,5 +1,4 @@ import React, { useState } from "react" -import { useTranslation } from "next-i18next" import Highlight, { defaultProps, Language, @@ -17,6 +16,7 @@ import { cn } from "@/lib/utils/cn" import { LINES_BEFORE_COLLAPSABLE } from "@/lib/constants" import useColorModeValue from "@/hooks/useColorModeValue" +import { useTranslation } from "@/hooks/useTranslation" ;(typeof global !== "undefined" ? global : window).Prism = Prism require("prismjs/components/prism-solidity") diff --git a/src/components/DataProductCard.tsx b/src/components/DataProductCard.tsx index d6a3ec6d158..b9ccaad34fd 100644 --- a/src/components/DataProductCard.tsx +++ b/src/components/DataProductCard.tsx @@ -1,7 +1,7 @@ import React from "react" import { StaticImageData } from "next/image" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import { Flex } from "@/components/ui/flex" import InlineLink from "./ui/Link" @@ -42,7 +42,7 @@ const DataProductCard = ({ } style={{ background }} > - {logo && ( - export default meta @@ -19,11 +18,6 @@ export const Default: Story = { href: "/history/", children: "History of Ethereum", }, - render: (args) => ( - - - - ), } export const ExternalLink: Story = { @@ -32,11 +26,6 @@ export const ExternalLink: Story = { children: "Ethereum Website", isExternal: true, }, - render: (args) => ( - - - - ), } export const MultipleLinks: Story = { @@ -44,7 +33,7 @@ export const MultipleLinks: Story = { href: "#", }, render: () => ( - + History of Ethereum Ethereum Website diff --git a/src/components/DocsNav.tsx b/src/components/DocsNav.tsx index 6465116d450..dce514dc45c 100644 --- a/src/components/DocsNav.tsx +++ b/src/components/DocsNav.tsx @@ -1,6 +1,3 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" - import { TranslationKey } from "@/lib/types" import type { DeveloperDocsLink } from "@/lib/interfaces" @@ -15,6 +12,8 @@ import { Stack } from "./ui/flex" import { LinkBox, LinkOverlay } from "./ui/link-box" import { useRtlFlip } from "@/hooks/useRtlFlip" +import { useTranslation } from "@/hooks/useTranslation" +import { usePathname } from "@/i18n/routing" const TextDiv = ({ children, className, ...props }) => ( { - const { asPath } = useRouter() + const pathname = usePathname() // Construct array of all linkable documents in order recursively const docsArray: DocsArrayProps[] = [] const getDocs = (links: Array): void => { @@ -112,8 +111,8 @@ const DocsNav = ({ contentNotTranslated }: DocsNavProps) => { let currentIndex = 0 for (let i = 0; i < docsArray.length; i++) { if ( - asPath.indexOf(docsArray[i].href) >= 0 && - asPath.length === docsArray[i].href.length + pathname.indexOf(docsArray[i].href) >= 0 && + pathname.length === docsArray[i].href.length ) { currentIndex = i } diff --git a/src/components/EnergyConsumptionChart/index.tsx b/src/components/EnergyConsumptionChart/index.tsx index 6f8d0008657..5e9bc1795e3 100644 --- a/src/components/EnergyConsumptionChart/index.tsx +++ b/src/components/EnergyConsumptionChart/index.tsx @@ -9,8 +9,7 @@ import { LinearScale, } from "chart.js" import ChartDataLabels from "chartjs-plugin-datalabels" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { Bar } from "react-chartjs-2" import type { Lang } from "@/lib/types" @@ -23,6 +22,7 @@ import { isLangRightToLeft } from "@/lib/utils/translations" import { useBreakpointValue } from "@/hooks/useBreakpointValue" import useColorModeValue from "@/hooks/useColorModeValue" import { useIsClient } from "@/hooks/useIsClient" +import { useTranslation } from "@/hooks/useTranslation" // ChartDataLabels required to display y-labels on top of bars ChartJS.register( @@ -35,7 +35,7 @@ ChartJS.register( const EnergyConsumptionChart = () => { const { t } = useTranslation("page-what-is-ethereum") - const { locale } = useRouter() + const locale = useLocale() const isClient = useIsClient() const isRtl = isLangRightToLeft(locale as Lang) diff --git a/src/components/EthPriceCard.tsx b/src/components/EthPriceCard.tsx index 3e2a51a441c..657aa5aa0fb 100644 --- a/src/components/EthPriceCard.tsx +++ b/src/components/EthPriceCard.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { MdInfoOutline } from "react-icons/md" import type { LoadingState } from "@/lib/types" @@ -13,6 +12,7 @@ import { cn } from "@/lib/utils/cn" import { Flex } from "./ui/flex" import { useRtlFlip } from "@/hooks/useRtlFlip" +import { useTranslation } from "@/hooks/useTranslation" type EthPriceResponse = { ethereum: { @@ -30,7 +30,7 @@ const EthPriceCard = ({ className, ...props }: React.HTMLAttributes) => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation() const [state, setState] = useState>({ loading: true, diff --git a/src/components/EventCard.tsx b/src/components/EventCard.tsx index a18611f3a4e..3996f8d78f2 100644 --- a/src/components/EventCard.tsx +++ b/src/components/EventCard.tsx @@ -1,6 +1,5 @@ import React from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { BsCalendar3 } from "react-icons/bs" import type { EventCardProps } from "@/lib/types" @@ -10,8 +9,9 @@ import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card" import { cn } from "@/lib/utils/cn" -import { TwImage } from "./Image" +import { Image } from "./Image" +import { useTranslation } from "@/hooks/useTranslation" import EventFallback from "@/public/images/events/event-placeholder.png" const EventCard: React.FC = ({ @@ -24,7 +24,7 @@ const EventCard: React.FC = ({ endDate, startDate, }) => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-community") const formatedDate = new Intl.DateTimeFormat(locale, { @@ -55,7 +55,7 @@ const EventCard: React.FC = ({ className="max-h-[224px] w-full object-cover xl:h-[124px]" /> ) : ( - + )}
diff --git a/src/components/ExpandableCard.tsx b/src/components/ExpandableCard.tsx index 448898ef6c2..e1e9a791c6f 100644 --- a/src/components/ExpandableCard.tsx +++ b/src/components/ExpandableCard.tsx @@ -1,5 +1,4 @@ import React, { type ReactNode, useState } from "react" -import { useTranslation } from "next-i18next" import { Flex, HStack, VStack } from "@/components/ui/flex" @@ -13,6 +12,8 @@ import { AccordionTrigger, } from "./ui/accordion" +import { useTranslation } from "@/hooks/useTranslation" + export type ExpandableCardProps = { children?: ReactNode contentPreview?: ReactNode diff --git a/src/components/FeedbackCard.tsx b/src/components/FeedbackCard.tsx index 4caf5327c24..be9340d051b 100644 --- a/src/components/FeedbackCard.tsx +++ b/src/components/FeedbackCard.tsx @@ -1,6 +1,5 @@ import { type ReactNode, useState } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { Lang } from "@/lib/types" @@ -13,6 +12,8 @@ import { Button } from "./ui/buttons/Button" import Translation from "./Translation" import { useSurvey } from "@/hooks/useSurvey" +import { useTranslation } from "@/hooks/useTranslation" +import { usePathname } from "@/i18n/routing" type FeedbackCardProps = { prompt?: string @@ -23,10 +24,11 @@ const FeedbackCard = ({ prompt, isArticle, ...props }: FeedbackCardProps) => { const { t } = useTranslation("common") const [feedbackSubmitted, setFeedbackSubmitted] = useState(false) const surveyUrl = useSurvey(feedbackSubmitted) - const { locale, asPath } = useRouter() + const locale = useLocale() + const pathname = usePathname() const dir = isLangRightToLeft(locale! as Lang) ? "rtl" : "ltr" - const isTutorial = asPath?.includes("tutorials") + const isTutorial = pathname?.includes("tutorials") const getTitle = (feedbackSubmitted: boolean): ReactNode => { if (!feedbackSubmitted) { diff --git a/src/components/FeedbackWidget/FeedbackWidget.stories.tsx b/src/components/FeedbackWidget/FeedbackWidget.stories.tsx index 41fecc73ecc..d326503f490 100644 --- a/src/components/FeedbackWidget/FeedbackWidget.stories.tsx +++ b/src/components/FeedbackWidget/FeedbackWidget.stories.tsx @@ -1,8 +1,9 @@ import * as React from "react" -import { Box, Stack } from "@chakra-ui/react" import { Meta, StoryObj } from "@storybook/react" import { expect, fireEvent, waitFor, within } from "@storybook/test" +import { Stack } from "../ui/flex" + import FeedbackWidget from "./" const meta = { @@ -13,8 +14,8 @@ const meta = { component: FeedbackWidget, decorators: [ (Story) => ( - - + +
), @@ -25,12 +26,9 @@ export default meta type Story = StoryObj -export const WidgetButton: Story = { - render: () => , -} +export const WidgetButton: Story = {} export const WidgetModal: Story = { - render: () => , play: async ({ canvasElement }) => { // Add delay for snapshot capture of the modal const canvas = within(canvasElement) diff --git a/src/components/FeedbackWidget/FixedDot.tsx b/src/components/FeedbackWidget/FixedDot.tsx index 952470553a7..cc77b3fb55d 100644 --- a/src/components/FeedbackWidget/FixedDot.tsx +++ b/src/components/FeedbackWidget/FixedDot.tsx @@ -1,5 +1,4 @@ import { forwardRef } from "react" -import { useTranslation } from "next-i18next" import type { ButtonHTMLAttributes } from "react" import { Button } from "@/components/ui/buttons/Button" @@ -8,6 +7,8 @@ import { cn } from "@/lib/utils/cn" import { FeedbackGlyphIcon } from "../icons" +import { useTranslation } from "@/hooks/useTranslation" + type FixedDotProps = ButtonHTMLAttributes & { isExpanded: boolean offsetBottom?: boolean diff --git a/src/components/FeedbackWidget/index.tsx b/src/components/FeedbackWidget/index.tsx index b15b9986476..09c0502bcc4 100644 --- a/src/components/FeedbackWidget/index.tsx +++ b/src/components/FeedbackWidget/index.tsx @@ -1,4 +1,3 @@ -import { useTranslation } from "next-i18next" import { MdClose } from "react-icons/md" import { Button } from "@/components/ui/buttons/Button" @@ -13,6 +12,8 @@ import { import FixedDot from "./FixedDot" import { useFeedbackWidget } from "./useFeedbackWidget" +import { useTranslation } from "@/hooks/useTranslation" + const FeedbackWidget = () => { const { t } = useTranslation("common") const { diff --git a/src/components/FeedbackWidget/useFeedbackWidget.ts b/src/components/FeedbackWidget/useFeedbackWidget.ts index 1f2032496f9..7ef25e355fe 100644 --- a/src/components/FeedbackWidget/useFeedbackWidget.ts +++ b/src/components/FeedbackWidget/useFeedbackWidget.ts @@ -1,13 +1,13 @@ import { useEffect, useMemo, useRef, useState } from "react" -import { useRouter } from "next/router" import { trackCustomEvent } from "@/lib/utils/matomo" import { useDisclosure } from "@/hooks/useDisclosure" import { useSurvey } from "@/hooks/useSurvey" +import { usePathname } from "@/i18n/routing" export const useFeedbackWidget = () => { - const { asPath } = useRouter() + const pathname = usePathname() const [isExpanded, setIsExpanded] = useState(false) const [feedbackSubmitted, setFeedbackSubmitted] = useState(false) @@ -25,7 +25,7 @@ export const useFeedbackWidget = () => { const expandTimeout = setTimeout(() => setIsExpanded(true), 30_000) return () => clearTimeout(expandTimeout) - }, [asPath, onClose]) + }, [pathname, onClose]) const surveyUrl = useSurvey(feedbackSubmitted) @@ -33,12 +33,12 @@ export const useFeedbackWidget = () => { const pathsWithBottomNav = ["/staking", "/dao", "/defi", "/nft"] let shouldOffset = false pathsWithBottomNav.forEach((path) => { - if (asPath.includes(path)) { + if ((pathname || "").includes(path)) { shouldOffset = true } }) return shouldOffset - }, [asPath]) + }, [pathname]) const handleClose = (): void => { onClose() diff --git a/src/components/FileContributors.tsx b/src/components/FileContributors.tsx index 473d211147d..ad503e2e78c 100644 --- a/src/components/FileContributors.tsx +++ b/src/components/FileContributors.tsx @@ -2,7 +2,6 @@ import { BaseHTMLAttributes, useState } from "react" import type { ChildOnlyProp, FileContributor } from "@/lib/types" -import InlineLink from "@/components/Link" import Translation from "@/components/Translation" import { Button } from "@/components/ui/buttons/Button" import { Flex, VStack } from "@/components/ui/flex" @@ -13,6 +12,7 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import { Avatar } from "./ui/avatar" import Modal from "./ui/dialog-modal" +import InlineLink from "./ui/Link" import { useBreakpointValue } from "@/hooks/useBreakpointValue" diff --git a/src/components/FindWalletProductTable/FindWalletLanguageSelectInput.tsx b/src/components/FindWalletProductTable/FindWalletLanguageSelectInput.tsx index 0679045b332..4bbea017e44 100644 --- a/src/components/FindWalletProductTable/FindWalletLanguageSelectInput.tsx +++ b/src/components/FindWalletProductTable/FindWalletLanguageSelectInput.tsx @@ -1,5 +1,4 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { FilterInputState, Lang } from "@/lib/types" @@ -15,6 +14,8 @@ import { getLanguageCodeName } from "@/lib/utils/intl" import { trackCustomEvent } from "@/lib/utils/matomo" import { getLanguageCountWalletsData } from "@/lib/utils/wallets" +import { useTranslation } from "@/hooks/useTranslation" + interface FindWalletLanguageSelectInputProps { filterIndex: number itemIndex: number @@ -32,7 +33,7 @@ const FindWalletLanguageSelectInput = ({ inputState, updateFilterState, }: FindWalletLanguageSelectInputProps) => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-wallets-find-wallet") const languageCountWalletsData = getLanguageCountWalletsData(locale as string) const countSortedLanguagesCount = languageCountWalletsData.sort( diff --git a/src/components/FindWalletProductTable/FindWalletsNoResults.tsx b/src/components/FindWalletProductTable/FindWalletsNoResults.tsx index bbb487f559f..8ee9dfbba83 100644 --- a/src/components/FindWalletProductTable/FindWalletsNoResults.tsx +++ b/src/components/FindWalletProductTable/FindWalletsNoResults.tsx @@ -1,9 +1,9 @@ -import { useTranslation } from "next-i18next" - import { trackCustomEvent } from "@/lib/utils/matomo" import { Button } from "../ui/buttons/Button" +import { useTranslation } from "@/hooks/useTranslation" + const FindWalletsNoResults = ({ resetFilters }) => { const { t } = useTranslation("page-wallets-find-wallet") diff --git a/src/components/FindWalletProductTable/WalletInfo.tsx b/src/components/FindWalletProductTable/WalletInfo.tsx index 035a4824d12..e4f6b2d0aea 100644 --- a/src/components/FindWalletProductTable/WalletInfo.tsx +++ b/src/components/FindWalletProductTable/WalletInfo.tsx @@ -1,12 +1,10 @@ -import { useTranslation } from "next-i18next" import { IoChevronDownSharp, IoChevronUpSharp } from "react-icons/io5" import { Wallet } from "@/lib/types" -import { ButtonLink } from "@/components/Buttons" import { SupportedLanguagesTooltip } from "@/components/FindWalletProductTable/SupportedLanguagesTooltip" import { DevicesIcon, LanguagesIcon } from "@/components/icons/wallets" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import Tooltip from "@/components/Tooltip" import { Tag } from "@/components/ui/tag" @@ -14,6 +12,10 @@ import { formatStringList, getWalletPersonas } from "@/lib/utils/wallets" import { ethereumNetworkData, layer2Data } from "@/data/networks/networks" +import { ButtonLink } from "../ui/buttons/Button" + +import { useTranslation } from "@/hooks/useTranslation" + interface WalletInfoProps { wallet: Wallet isExpanded: boolean @@ -38,7 +40,7 @@ const WalletInfo = ({ wallet, isExpanded }: WalletInfoProps) => {
- { className="-ml-1.5 overflow-hidden rounded-full" > - {
- { className="-ml-1.5 overflow-hidden rounded-full" > - { ( { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-wallets-find-wallet") const walletFiltersOptions: FilterOption[] = useWalletFilters() diff --git a/src/components/FindWalletProductTable/hooks/useWalletFilters.tsx b/src/components/FindWalletProductTable/hooks/useWalletFilters.tsx index 247f6b676e6..f8cc36ba2f3 100644 --- a/src/components/FindWalletProductTable/hooks/useWalletFilters.tsx +++ b/src/components/FindWalletProductTable/hooks/useWalletFilters.tsx @@ -1,5 +1,4 @@ import { useRef } from "react" -import { useTranslation } from "next-i18next" import { FilterOption } from "@/lib/types" @@ -34,6 +33,8 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import { DEFAULT_LOCALE } from "@/lib/constants" +import { useTranslation } from "@/hooks/useTranslation" + export const useWalletFilters = (): FilterOption[] => { const { t } = useTranslation("page-wallets-find-wallet") const prevNetworkArray = useRef([]) diff --git a/src/components/FindWalletProductTable/hooks/useWalletPersonaPresets.tsx b/src/components/FindWalletProductTable/hooks/useWalletPersonaPresets.tsx index c09efa677e2..9e4c02e2cf1 100644 --- a/src/components/FindWalletProductTable/hooks/useWalletPersonaPresets.tsx +++ b/src/components/FindWalletProductTable/hooks/useWalletPersonaPresets.tsx @@ -1,7 +1,7 @@ -import { useTranslation } from "next-i18next" - import { WalletPersonas } from "@/lib/types" +import { useTranslation } from "@/hooks/useTranslation" + export const useWalletPersonaPresets = (): WalletPersonas[] => { const { t } = useTranslation("page-wallets-find-wallet") const personas: WalletPersonas[] = [ diff --git a/src/components/FindWalletProductTable/index.tsx b/src/components/FindWalletProductTable/index.tsx index 97fb0546a43..b386d7b9aa9 100644 --- a/src/components/FindWalletProductTable/index.tsx +++ b/src/components/FindWalletProductTable/index.tsx @@ -1,5 +1,4 @@ import { useEffect, useMemo, useState } from "react" -import { useTranslation } from "next-i18next" import { ChainName, FilterOption, Lang, Wallet } from "@/lib/types" @@ -13,6 +12,8 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import FindWalletsNoResults from "./FindWalletsNoResults" import WalletSubComponent from "./WalletSubComponent" +import { useTranslation } from "@/hooks/useTranslation" + const FindWalletProductTable = ({ wallets }: { wallets: Wallet[] }) => { const { t } = useTranslation("page-wallets-find-wallet") const walletPersonas = useWalletPersonaPresets() diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index a2d2a69e415..236a722b66b 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,4 +1,3 @@ -import { useTranslation } from "next-i18next" import { FaDiscord, FaGithub, FaXTwitter } from "react-icons/fa6" import { IoChevronUpSharp } from "react-icons/io5" @@ -13,6 +12,8 @@ import { Button } from "./ui/buttons/Button" import { BaseLink } from "./ui/Link" import { List, ListItem } from "./ui/list" +import { useTranslation } from "@/hooks/useTranslation" + const socialLinks = [ { icon: FaGithub, @@ -320,9 +321,7 @@ const Footer = ({ lastDeployLocaleTimestamp }: FooterProps) => {
{linkSections.map((section: FooterLinkSection, idx) => (
-

- -

+

{section.title}

{section.links.map((link, linkIdx) => ( diff --git a/src/components/GitStars.tsx b/src/components/GitStars.tsx index 10ff810e559..fde0ceda7ae 100644 --- a/src/components/GitStars.tsx +++ b/src/components/GitStars.tsx @@ -1,4 +1,4 @@ -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import { FaGithub } from "react-icons/fa" import { Center, Flex } from "@/components/ui/flex" @@ -17,7 +17,7 @@ type GitStarsProps = Omit & { } const GitStars = ({ gitHubRepo, hideStars, ...props }: GitStarsProps) => { - const { locale } = useRouter() + const locale = useLocale() // Use Intl.NumberFormat to format the number for locale const starsString = Intl.NumberFormat(locale, { compactDisplay: "short", diff --git a/src/components/Glossary/GlossaryDefinition/index.tsx b/src/components/Glossary/GlossaryDefinition/index.tsx index 9b68ecfc9b8..e50fde03be1 100644 --- a/src/components/Glossary/GlossaryDefinition/index.tsx +++ b/src/components/Glossary/GlossaryDefinition/index.tsx @@ -1,5 +1,3 @@ -import { ComponentProps } from "react" - import IdAnchor from "@/components/IdAnchor" import Translation from "@/components/Translation" import { Stack } from "@/components/ui/flex" @@ -12,7 +10,7 @@ import { DEFAULT_GLOSSARY_NS } from "@/lib/constants" interface GlossaryDefinitionProps { term: string size?: "md" | "sm" - options?: ComponentProps["options"] + ns?: string } // Override the default `a` mapping to prevent displaying the glossary tooltip @@ -24,7 +22,7 @@ const components = { const GlossaryDefinition = ({ term, size = "md", - options = { ns: DEFAULT_GLOSSARY_NS }, + ns = DEFAULT_GLOSSARY_NS, }: GlossaryDefinitionProps) => { const textClasses = size === "sm" ? "mb-0" : "" @@ -35,19 +33,11 @@ const GlossaryDefinition = ({ {...(term ? { "data-group": true, id: term } : {})} > - +
- +
) diff --git a/src/components/Glossary/GlossaryTooltip/GlossaryTooltip.stories.tsx b/src/components/Glossary/GlossaryTooltip/GlossaryTooltip.stories.tsx index 7fe2ad9ea65..3529d1fad65 100644 --- a/src/components/Glossary/GlossaryTooltip/GlossaryTooltip.stories.tsx +++ b/src/components/Glossary/GlossaryTooltip/GlossaryTooltip.stories.tsx @@ -1,6 +1,7 @@ -import { Center } from "@chakra-ui/react" import { Meta, StoryObj } from "@storybook/react" +import { Center } from "@/components/ui/flex" + import GlossaryTooltipComponent from "." const meta = { @@ -12,7 +13,7 @@ const meta = { }, decorators: [ (Story) => ( -
+
), diff --git a/src/components/Glossary/GlossaryTooltip/index.tsx b/src/components/Glossary/GlossaryTooltip/index.tsx index a2ec9ed1dbf..54e4639c547 100644 --- a/src/components/Glossary/GlossaryTooltip/index.tsx +++ b/src/components/Glossary/GlossaryTooltip/index.tsx @@ -1,13 +1,14 @@ import React, { ReactNode } from "react" -import { useRouter } from "next/router" -import InlineLink from "@/components/Link" import Tooltip, { type TooltipProps } from "@/components/Tooltip" import Translation from "@/components/Translation" +import InlineLink from "@/components/ui/Link" import { trackCustomEvent } from "@/lib/utils/matomo" import { cleanPath } from "@/lib/utils/url" +import { usePathname } from "@/i18n/routing" + type GlossaryTooltipProps = Omit & { children: ReactNode termKey: string @@ -18,7 +19,7 @@ const GlossaryTooltip = ({ termKey, ...props }: GlossaryTooltipProps) => { - const { asPath } = useRouter() + const pathname = usePathname() return ( @@ -29,7 +30,7 @@ const GlossaryTooltip = ({
{ trackCustomEvent({ eventCategory: "Glossary Tooltip", - eventAction: cleanPath(asPath), + eventAction: cleanPath(pathname), eventName: termKey, }) }} diff --git a/src/components/Heading/index.tsx b/src/components/Heading/index.tsx deleted file mode 100644 index a4972266413..00000000000 --- a/src/components/Heading/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - forwardRef, - Heading as ChakraHeading, - type HeadingProps, - type ThemingProps, -} from "@chakra-ui/react" - -export type HeadingTags = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" - -const HEADING_SIZE_DEFAULTS: Record< - HeadingTags, - ThemingProps<"Heading">["size"] -> = { - h1: "2xl", - h2: "xl", - h3: "lg", - h4: "md", - h5: "sm", - h6: "xs", -} - -/** - * This is a wrapper component for the Chakra `Heading` component, and forwards its ref and props. - * - * This supplies a default `size` theme token based on the - * heading tag being passed to the `as` prop. Defaults to `h2` with the `xl` - * tag, per the Chakra default. - */ -const Heading = forwardRef((props, ref) => { - const { as = "h2", size: sizeProp, ...rest } = props - - let size: typeof sizeProp - - if (sizeProp) { - // If a `size` value is passed to this wrapper, send it on through! - size = sizeProp - } else { - // If a `size` value is not passed to this wrapper, set a default based on the element - // provided to the `as` prop - // Only heading elements will set the defaults (Default heading is `h2`) - const headingDefaultKeys = Object.keys(HEADING_SIZE_DEFAULTS) - - if (typeof as === "string" && headingDefaultKeys.includes(as)) { - size = HEADING_SIZE_DEFAULTS[as] - } - } - - return -}) - -export default Heading diff --git a/src/components/Hero/ContentHero/ContentHero.stories.tsx b/src/components/Hero/ContentHero/ContentHero.stories.tsx index 5dd3e15b687..2d7d93af293 100644 --- a/src/components/Hero/ContentHero/ContentHero.stories.tsx +++ b/src/components/Hero/ContentHero/ContentHero.stories.tsx @@ -1,7 +1,6 @@ +import { useTranslations } from "next-intl" import { Meta, StoryObj } from "@storybook/react" -import { getTranslation } from "@/storybook-utils" - import { langViewportModes } from "../../../../.storybook/modes" import ContentHeroComponent, { ContentHeroProps } from "." @@ -32,10 +31,11 @@ export const ContentHero: StoryObj = { }, }, render: () => { - const PAGE_LEARN_NS = "page-learn" + const t = useTranslations("page-learn") + const buttons: ContentHeroProps["buttons"] = [ { - content: getTranslation("hero-button-lets-get-started", PAGE_LEARN_NS), + content: t("hero-button-lets-get-started"), toId: "what-is-crypto-ethereum", matomo: { eventCategory: "learn hub hero buttons", @@ -58,8 +58,8 @@ export const ContentHero: StoryObj = { heroImg="/images/upgrades/merge.png" // Can not properly hardcode this URL. So it's left blank blurDataURL="" - title={getTranslation("hero-header", PAGE_LEARN_NS)} - description={getTranslation("hero-subtitle", PAGE_LEARN_NS)} + title={t("hero-header")} + description={t("hero-subtitle")} buttons={buttons} /> ) diff --git a/src/components/Hero/ContentHero/index.tsx b/src/components/Hero/ContentHero/index.tsx index 27cdc123617..ee384590d1e 100644 --- a/src/components/Hero/ContentHero/index.tsx +++ b/src/components/Hero/ContentHero/index.tsx @@ -1,7 +1,7 @@ import type { CommonHeroProps } from "@/lib/types" import Breadcrumbs from "@/components/Breadcrumbs" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import { Stack } from "@/components/ui/flex" import { CallToAction } from "../CallToAction" @@ -15,7 +15,7 @@ const ContentHero = (props: ContentHeroProps) => {
- & ClassNameProp const HomeHero = ({ heroImg, className }: HomeHeroProps) => { @@ -13,7 +13,7 @@ const HomeHero = ({ heroImg, className }: HomeHeroProps) => { return (
- ( - +
- +
), ], } satisfies Meta @@ -34,9 +37,11 @@ export default meta export const HubHero: StoryObj = { render: () => { + const t = useTranslations() + const buttons: HubHeroProps["buttons"] = [ { - content: getTranslation("hero-button-lets-get-started", "page-learn"), + content: t("page-learn.hero-button-lets-get-started"), toId: "what-is-crypto-ethereum", matomo: { eventCategory: "learn hub hero buttons", @@ -56,9 +61,9 @@ export const HubHero: StoryObj = { return ( diff --git a/src/components/Hero/HubHero/index.tsx b/src/components/Hero/HubHero/index.tsx index 168bd328843..dd8188aac4b 100644 --- a/src/components/Hero/HubHero/index.tsx +++ b/src/components/Hero/HubHero/index.tsx @@ -1,7 +1,7 @@ import type { CommonHeroProps } from "@/lib/types" import { CallToAction } from "@/components/Hero/CallToAction" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import { Stack } from "@/components/ui/flex" import { cn } from "@/lib/utils/cn" @@ -23,7 +23,7 @@ const HubHero = ({ return (
- ( - + ), diff --git a/src/components/History/NetworkUpgradeSummary.tsx b/src/components/History/NetworkUpgradeSummary.tsx index 45ed895dc79..410a2ead61a 100644 --- a/src/components/History/NetworkUpgradeSummary.tsx +++ b/src/components/History/NetworkUpgradeSummary.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { Lang } from "@/lib/types" @@ -10,7 +9,9 @@ import { getLocaleForNumberFormat } from "@/lib/utils/translations" import NetworkUpgradeSummaryData from "../../data/NetworkUpgradeSummaryData" import Emoji from "../Emoji" -import InlineLink from "../Link" +import InlineLink from "../ui/Link" + +import { useTranslation } from "@/hooks/useTranslation" type NetworkUpgradeSummaryProps = { name: string @@ -18,7 +19,7 @@ type NetworkUpgradeSummaryProps = { const NetworkUpgradeSummary = ({ name }: NetworkUpgradeSummaryProps) => { const [formattedUTC, setFormattedUTC] = useState("") - const { locale } = useRouter() + const locale = useLocale() const localeForStatsBoxNumbers = getLocaleForNumberFormat(locale as Lang) const { t } = useTranslation("page-history") diff --git a/src/components/Homepage/BentoCard.tsx b/src/components/Homepage/BentoCard.tsx index ff212f3cdac..ae68ddb4c58 100644 --- a/src/components/Homepage/BentoCard.tsx +++ b/src/components/Homepage/BentoCard.tsx @@ -1,7 +1,7 @@ import { HTMLAttributes } from "react" import { type StaticImageData } from "next/image" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import { ButtonLink } from "@/components/ui/buttons/Button" import { cn } from "@/lib/utils/cn" @@ -40,7 +40,7 @@ const BentoCard = ({ )} >
- +
diff --git a/src/components/Homepage/useBentoBox.ts b/src/components/Homepage/useBentoBox.ts index b4a0deb4ceb..6be21b99857 100644 --- a/src/components/Homepage/useBentoBox.ts +++ b/src/components/Homepage/useBentoBox.ts @@ -1,7 +1,6 @@ -import { useTranslation } from "next-i18next" - import { cn } from "@/lib/utils/cn" +import useTranslation from "@/hooks/useTranslation" import ImpactImage from "@/public/images/impact_transparent.png" import ManAndDogImage from "@/public/images/man-and-dog-playing.png" import ManBabyWomanImage from "@/public/images/man-baby-woman.png" diff --git a/src/components/Homepage/useHome.ts b/src/components/Homepage/useHome.ts index e5c70f57b85..1833663d64e 100644 --- a/src/components/Homepage/useHome.ts +++ b/src/components/Homepage/useHome.ts @@ -1,6 +1,5 @@ import { useState } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { FaDiscord, FaGithub, FaXTwitter } from "react-icons/fa6" import type { EventCardProps } from "@/lib/types" @@ -28,10 +27,13 @@ import SimpleDomainRegistryContent from "!!raw-loader!@/data/SimpleDomainRegistr import SimpleTokenContent from "!!raw-loader!@/data/SimpleToken.sol" import SimpleWalletContent from "!!raw-loader!@/data/SimpleWallet.sol" import { useRtlFlip } from "@/hooks/useRtlFlip" +import useTranslation from "@/hooks/useTranslation" +import { usePathname } from "@/i18n/routing" export const useHome = () => { const { t } = useTranslation(["common", "page-index"]) - const { locale, asPath } = useRouter() + const locale = useLocale() + const asPath = usePathname() const [isModalOpen, setModalOpen] = useState(false) const [activeCode, setActiveCode] = useState(0) diff --git a/src/components/Homepage/useValuesMarquee.ts b/src/components/Homepage/useValuesMarquee.ts index 2189c924471..fd09e13b7a7 100644 --- a/src/components/Homepage/useValuesMarquee.ts +++ b/src/components/Homepage/useValuesMarquee.ts @@ -1,5 +1,6 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" + +import useTranslation from "@/hooks/useTranslation" type Item = { label: string @@ -13,7 +14,7 @@ export type Pairing = { export const useValuesMarquee = () => { const { t } = useTranslation("page-index") - const { locale } = useRouter() + const locale = useLocale() const pairings: Pairing[] = [ { legacy: { diff --git a/src/components/Image.tsx b/src/components/Image.tsx index 3c67258b35a..ddcf2547b7f 100644 --- a/src/components/Image.tsx +++ b/src/components/Image.tsx @@ -2,36 +2,8 @@ import NextImage, { ImageProps as NextImageProps, StaticImageData, } from "next/image" -import { chakra, ChakraComponent, HTMLChakraProps } from "@chakra-ui/react" -export type ImageProps = NextImageProps & - Omit, keyof NextImageProps> - -const imageProps: (keyof NextImageProps)[] = [ - "src", - "alt", - "sizes", - "width", - "height", - "fill", - "loader", - "quality", - "priority", - "loading", - "placeholder", - "blurDataURL", - "unoptimized", - "onLoadingComplete", - "alt", - "crossOrigin", - "decoding", - "loading", - "referrerPolicy", - "sizes", - "src", - "style", - "useMap", -] +export type ImageProps = NextImageProps const isStaticImageData = (src: ImageProps["src"]): src is StaticImageData => { return typeof src === "object" && "blurDataURL" in src @@ -46,23 +18,4 @@ const DefaultNextImage = (props: ImageProps) => { return } -/** - * TODO: Rename this component to `Image` once all components are using Tailwind - */ -export const TwImage = (props: NextImageProps) => ( - -) - -/** - * DEPRECATED: Use `TWImage` instead - * - * TODO: Remove this component once all components are using Tailwind - * - * @deprecated - */ -export const Image: ChakraComponent<"img", NextImageProps> = chakra( - DefaultNextImage, - { - shouldForwardProp: (prop) => (imageProps as string[]).includes(prop), - } -) +export const Image = (props: NextImageProps) => diff --git a/src/components/LanguagePicker/MenuItem.tsx b/src/components/LanguagePicker/MenuItem.tsx index 3a7bd35019d..752e4df006b 100644 --- a/src/components/LanguagePicker/MenuItem.tsx +++ b/src/components/LanguagePicker/MenuItem.tsx @@ -1,6 +1,5 @@ import { ComponentPropsWithoutRef } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import { BsCheck } from "react-icons/bs" import type { LocaleDisplayInfo } from "@/lib/types" @@ -12,6 +11,8 @@ import { Tag } from "../ui/tag" import ProgressBar from "./ProgressBar" +import { useTranslation } from "@/hooks/useTranslation" + type ItemProps = ComponentPropsWithoutRef & { displayInfo: LocaleDisplayInfo } @@ -26,7 +27,7 @@ const MenuItem = ({ displayInfo, ...props }: ItemProps) => { isBrowserDefault, } = displayInfo const { t } = useTranslation("common") - const { locale } = useRouter() + const locale = useLocale() const isCurrent = localeOption === locale const getProgressInfo = (approvalProgress: number, wordsApproved: number) => { diff --git a/src/components/LanguagePicker/MobileCloseBar.tsx b/src/components/LanguagePicker/MobileCloseBar.tsx index 5678294259c..60937dcdf19 100644 --- a/src/components/LanguagePicker/MobileCloseBar.tsx +++ b/src/components/LanguagePicker/MobileCloseBar.tsx @@ -1,8 +1,9 @@ import { MouseEventHandler } from "react" -import { useTranslation } from "next-i18next" import { Button } from "../ui/buttons/Button" +import { useTranslation } from "@/hooks/useTranslation" + type MobileCloseBarProps = { handleClick: MouseEventHandler } diff --git a/src/components/LanguagePicker/NoResultsCallout.tsx b/src/components/LanguagePicker/NoResultsCallout.tsx index 69b3dc767f2..cb2c9f33e8d 100644 --- a/src/components/LanguagePicker/NoResultsCallout.tsx +++ b/src/components/LanguagePicker/NoResultsCallout.tsx @@ -1,8 +1,6 @@ -import { useTranslation } from "next-i18next" +import { BaseLink } from "../ui/Link" -import { BaseLink } from "@/components/Link" - -import MenuItem from "./MenuItem" +import { useTranslation } from "@/hooks/useTranslation" type NoResultsCalloutProps = { onClose: () => void } @@ -14,9 +12,7 @@ const NoResultsCallout = ({ onClose }: NoResultsCalloutProps) => {

{t("page-languages-want-more-paragraph")}

- {/* TODO: use migrated Link component */} { - const { asPath, push } = useRouter() + const pathname = usePathname() + const { push } = useRouter() + const params = useParams() const { disclosure, languages } = useLanguagePicker(handleClose) const { isOpen, setValue, onClose, onOpen } = disclosure @@ -52,9 +54,15 @@ const LanguagePicker = ({ // onClick handlers const handleMobileCloseBarClick = () => onClose() const handleMenuItemSelect = (currentValue: string) => { - push(asPath, asPath, { - locale: currentValue, - }) + push( + // @ts-expect-error -- TypeScript will validate that only known `params` + // are used in combination with a given `pathname`. Since the two will + // always match for the current route, we can skip runtime checks. + { pathname, params }, + { + locale: currentValue, + } + ) onClose({ eventAction: "Locale chosen", eventName: currentValue, diff --git a/src/components/LanguagePicker/useLanguagePicker.tsx b/src/components/LanguagePicker/useLanguagePicker.tsx index 441424ce59b..7bb23526efc 100644 --- a/src/components/LanguagePicker/useLanguagePicker.tsx +++ b/src/components/LanguagePicker/useLanguagePicker.tsx @@ -1,22 +1,24 @@ import { useMemo } from "react" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { Lang, LocaleDisplayInfo } from "@/lib/types" import { MatomoEventOptions, trackCustomEvent } from "@/lib/utils/matomo" import { filterRealLocales } from "@/lib/utils/translations" +import { LOCALES_CODES } from "@/lib/constants" + import { localeToDisplayInfo } from "./localeToDisplayInfo" import { useDisclosure } from "@/hooks/useDisclosure" +import { useTranslation } from "@/hooks/useTranslation" export const useLanguagePicker = (handleClose?: () => void) => { const { t } = useTranslation("common") - const { locale, locales: rawLocales } = useRouter() + const locale = useLocale() const languages = useMemo(() => { - const locales = filterRealLocales(rawLocales) + const locales = filterRealLocales(LOCALES_CODES) // Get the preferred languages for the users browser const navLangs = typeof navigator !== "undefined" ? navigator.languages : [] @@ -60,7 +62,7 @@ export const useLanguagePicker = (handleClose?: () => void) => { return b.approvalProgress - a.approvalProgress }) || [] ) - }, [locale, rawLocales, t]) + }, [locale, t]) const { isOpen, setValue, ...menu } = useDisclosure() diff --git a/src/components/Layer2NetworksTable/NetworksSubComponent.tsx b/src/components/Layer2NetworksTable/NetworksSubComponent.tsx index f5b86621c58..d705211c7bf 100644 --- a/src/components/Layer2NetworksTable/NetworksSubComponent.tsx +++ b/src/components/Layer2NetworksTable/NetworksSubComponent.tsx @@ -1,10 +1,11 @@ import { MdInfoOutline } from "react-icons/md" -import { ButtonLink } from "@/components/Buttons" import NetworkUsageChart from "@/components/Layer2NetworksTable/NetworkUsageChart" -import InlineLink from "@/components/Link" import Tooltip from "@/components/Tooltip" +import { ButtonLink } from "../ui/buttons/Button" +import InlineLink from "../ui/Link" + const formatNumber = (num: number): string => { if (num >= 1e9) { return (num / 1e9).toFixed(2) + "B" diff --git a/src/components/Layer2NetworksTable/hooks/useNetworkColumns.tsx b/src/components/Layer2NetworksTable/hooks/useNetworkColumns.tsx index ed4b630b8b5..11f1f818c0a 100644 --- a/src/components/Layer2NetworksTable/hooks/useNetworkColumns.tsx +++ b/src/components/Layer2NetworksTable/hooks/useNetworkColumns.tsx @@ -7,11 +7,11 @@ import { ColumnDef } from "@tanstack/react-table" import { ExtendedRollup, Lang } from "@/lib/types" import { TableMeta } from "@/components/DataTable" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import NetworkMaturityTooltip from "@/components/Layer2NetworksTable/NetworkMaturityTooltip" -import InlineLink from "@/components/Link" import Tooltip from "@/components/Tooltip" import { Button } from "@/components/ui/buttons/Button" +import InlineLink from "@/components/ui/Link" import { TableCell, TableHead } from "@/components/ui/table" import { cn } from "@/lib/utils/cn" @@ -57,7 +57,7 @@ export const useNetworkColumns: ColumnDef[] = [
- - { return ( @@ -20,7 +19,7 @@ const LearningToolsCardGrid = ({ category }: LearningToolsCardGridProps) => { name={name} subjects={subjects} > - + {description} ))}
diff --git a/src/components/Link.tsx b/src/components/Link.tsx deleted file mode 100644 index d694af331d8..00000000000 --- a/src/components/Link.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import NextLink, { type LinkProps as NextLinkProps } from "next/link" -import { useRouter } from "next/router" -import { RxExternalLink } from "react-icons/rx" -import { - forwardRef, - Icon, - Link as ChakraLink, - type LinkProps as ChakraLinkProps, - type StyleProps, - VisuallyHidden, -} from "@chakra-ui/react" - -import { type MatomoEventOptions, trackCustomEvent } from "@/lib/utils/matomo" -import { getRelativePath } from "@/lib/utils/relativePath" -import * as url from "@/lib/utils/url" - -import { DISCORD_PATH, SITE_URL } from "@/lib/constants" - -import { useRtlFlip } from "@/hooks/useRtlFlip" - -type BaseProps = { - hideArrow?: boolean - isPartiallyActive?: boolean - activeStyle?: StyleProps - customEventOptions?: MatomoEventOptions -} - -export type LinkProps = BaseProps & - ChakraLinkProps & - Omit - -/** - * Link wrapper which handles: - * - * - Hashed links - * e.g. - * - * - External links - * e.g. - * - * - PDFs & static files (which open in a new tab) - * e.g. - */ -export const BaseLink = forwardRef(function Link( - { - href, - children, - hideArrow, - isPartiallyActive = true, - activeStyle = { color: "primary.base" }, - customEventOptions, - ...props - }: LinkProps, - ref -) { - const { locale, asPath } = useRouter() - const { flipForRtl } = useRtlFlip() - - if (!href) { - console.warn("Link component is missing href prop:", asPath, locale) - return - } - - const isActive = url.isHrefActive(href, asPath, isPartiallyActive) - const isDiscordInvite = url.isDiscordInvite(href) - const isPdf = url.isPdf(href) - const isExternal = url.isExternal(href) - const isInternalPdf = isPdf && !isExternal - const isHash = url.isHash(href) - - // Get proper download link for internally hosted PDF's & static files (ex: whitepaper) - // Opens in separate window. - if (isInternalPdf) { - href = getRelativePath(asPath, href) - } - - if (isDiscordInvite) { - href = new URL(DISCORD_PATH, SITE_URL).href - } - - const commonProps = { - ref, - ...props, - ...(isActive && activeStyle), - href, - } - - if (isExternal) { - return ( - - trackCustomEvent( - customEventOptions ?? { - eventCategory: `Link`, - eventAction: `Clicked`, - eventName: "Clicked on external link", - eventValue: href, - } - ) - } - {...commonProps} - > - {children} - (opens in a new tab) - {!hideArrow && ( - - )} - - ) - } - - if (isInternalPdf) { - return ( - - trackCustomEvent( - customEventOptions ?? { - eventCategory: `Link`, - eventAction: `Clicked`, - eventName: "Clicked on internal PDF", - eventValue: href, - } - ) - } - {...commonProps} - as={NextLink} - > - {children} - - ) - } - - if (isHash) { - return ( - { - e.stopPropagation() - trackCustomEvent( - customEventOptions ?? { - eventCategory: "Link", - eventAction: "Clicked", - eventName: "Clicked on hash link", - eventValue: href, - } - ) - }} - {...commonProps} - > - {children} - - ) - } - - return ( - - trackCustomEvent( - customEventOptions ?? { - eventCategory: `Link`, - eventAction: `Clicked`, - eventName: `Clicked on internal link`, - eventValue: href, - } - ) - } - {...commonProps} - as={NextLink} - > - {children} - - ) -}) - -const InlineLink = forwardRef((props: LinkProps, ref) => { - return -}) - -export default InlineLink diff --git a/src/components/LocaleDateTime.tsx b/src/components/LocaleDateTime.tsx index ea21c327a6a..2ab4c7e50b7 100644 --- a/src/components/LocaleDateTime.tsx +++ b/src/components/LocaleDateTime.tsx @@ -1,4 +1,4 @@ -import { useRouter } from "next/router" +import { useLocale } from "next-intl" type LocaleDateTimeProps = { utcDateTime: string @@ -26,7 +26,7 @@ const LocaleDateTime = ({ "LocaleDateTime hideDate and hideTime props cannot both be true" ) - const { locale } = useRouter() + const locale = useLocale() const date = new Date(utcDateTime) const defaultDateOptions: Intl.DateTimeFormatOptions = { month: "long", diff --git a/src/components/Logo/index.tsx b/src/components/Logo/index.tsx index 9c32a6d7544..73516511844 100644 --- a/src/components/Logo/index.tsx +++ b/src/components/Logo/index.tsx @@ -1,8 +1,7 @@ -import { useTranslation } from "next-i18next" - -import { TwImage as Image } from "@/components/Image" +import { Image } from "@/components/Image" import useColorModeValue from "@/hooks/useColorModeValue" +import { useTranslation } from "@/hooks/useTranslation" import darkImage from "@/public/images/ef-logo.png" import lightImage from "@/public/images/ef-logo-white.png" diff --git a/src/components/MarkdownImage.tsx b/src/components/MarkdownImage.tsx index 28eb16ac05b..6d44ae121cb 100644 --- a/src/components/MarkdownImage.tsx +++ b/src/components/MarkdownImage.tsx @@ -1,13 +1,13 @@ import { extname } from "path" -import { type ImageProps, TwImage } from "@/components/Image" +import NextLink from "next/link" + +import { Image, type ImageProps } from "@/components/Image" import { toPosixPath } from "@/lib/utils/relativePath" import { CONTENT_IMAGES_MAX_WIDTH } from "@/lib/constants" -import InlineLink from "./ui/Link" - interface MarkdownImageProps extends Omit { width: string height: string @@ -42,13 +42,8 @@ const MarkdownImage = ({ // display the wrapper as a `span` to avoid dom nesting warnings as mdx // sometimes wraps images in `p` tags - - + {alt} - + ) } diff --git a/src/components/MergeArticleList.tsx b/src/components/MergeArticleList.tsx index 307394df22d..1763cfa61b3 100644 --- a/src/components/MergeArticleList.tsx +++ b/src/components/MergeArticleList.tsx @@ -1,7 +1,7 @@ -import { useTranslation } from "next-i18next" - import CardList, { type CardProps } from "@/components/CardList" +import { useTranslation } from "@/hooks/useTranslation" + const MergeArticleList = () => { const { t } = useTranslation(["page-upgrades", "page-upgrades-index"]) diff --git a/src/components/MergeInfographic/MergeInfographic.stories.tsx b/src/components/MergeInfographic/MergeInfographic.stories.tsx index 073e4272fe9..6b486f5e1ec 100644 --- a/src/components/MergeInfographic/MergeInfographic.stories.tsx +++ b/src/components/MergeInfographic/MergeInfographic.stories.tsx @@ -1,4 +1,3 @@ -import { Box } from "@chakra-ui/react" import { Meta, StoryObj } from "@storybook/react" import { langViewportModes } from "../../../.storybook/modes" @@ -18,9 +17,9 @@ const meta = { }, decorators: [ (Story) => ( - +
- +
), ], } satisfies Meta diff --git a/src/components/MergeInfographic/index.tsx b/src/components/MergeInfographic/index.tsx index 2dc30128ea1..163af7e8225 100644 --- a/src/components/MergeInfographic/index.tsx +++ b/src/components/MergeInfographic/index.tsx @@ -1,4 +1,3 @@ -import { useTranslation } from "next-i18next" import type { SVGTextElementAttributes } from "react" import Translation from "@/components/Translation" @@ -10,6 +9,8 @@ import { HStack } from "../ui/flex" import { Background } from "./Background" +import { useTranslation } from "@/hooks/useTranslation" + const Text = ({ className, ...rest @@ -63,9 +64,7 @@ const MergeInfographic = () => {
void @@ -19,7 +19,7 @@ type DesktopNavMenuProps = { const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => { const { t } = useTranslation("common") - const { locale } = useRouter() + const locale = useLocale() const languagePickerRef = useRef(null) const ThemeIcon = useColorModeValue(MdBrightness2, MdWbSunny) diff --git a/src/components/Nav/Menu/useSubMenu.ts b/src/components/Nav/Menu/useSubMenu.ts index b44b39e7999..6d51aca23bc 100644 --- a/src/components/Nav/Menu/useSubMenu.ts +++ b/src/components/Nav/Menu/useSubMenu.ts @@ -1,10 +1,12 @@ import type { MotionProps } from "framer-motion" -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import { useRtlFlip } from "@/hooks/useRtlFlip" +import { usePathname } from "@/i18n/routing" export const useSubMenu = () => { - const { asPath, locale } = useRouter() + const pathname = usePathname() + const locale = useLocale() const { isRtl } = useRtlFlip() const menuVariants: MotionProps["variants"] = { @@ -13,7 +15,7 @@ export const useSubMenu = () => { } return { - asPath, + asPath: pathname, locale, menuVariants, } diff --git a/src/components/Nav/Mobile/HamburgerButton.tsx b/src/components/Nav/Mobile/HamburgerButton.tsx index 1bb8c2c484d..15fa6f967a7 100644 --- a/src/components/Nav/Mobile/HamburgerButton.tsx +++ b/src/components/Nav/Mobile/HamburgerButton.tsx @@ -1,6 +1,5 @@ import { forwardRef } from "react" import { motion } from "framer-motion" -import { useTranslation } from "next-i18next" import { cn } from "@/lib/utils/cn" @@ -8,6 +7,8 @@ import { HAMBURGER_BUTTON_ID } from "@/lib/constants" import { Button, type ButtonProps } from "../../ui/buttons/Button" +import { useTranslation } from "@/hooks/useTranslation" + const hamburgerSvg = "M 2 13 l 10 0 l 0 0 l 10 0 M 4 19 l 8 0 M 12 19 l 8 0 M 2 25 l 10 0 l 0 0 l 10 0" const glyphSvg = diff --git a/src/components/Nav/Mobile/LvlAccordion.tsx b/src/components/Nav/Mobile/LvlAccordion.tsx index e3596464ab5..c213eca9ce4 100644 --- a/src/components/Nav/Mobile/LvlAccordion.tsx +++ b/src/components/Nav/Mobile/LvlAccordion.tsx @@ -1,5 +1,5 @@ import { useState } from "react" -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import * as AccordionPrimitive from "@radix-ui/react-accordion" import { cn } from "@/lib/utils/cn" @@ -18,6 +18,8 @@ import { AccordionTrigger, } from "./MenuAccordion" +import { usePathname } from "@/i18n/routing" + type LvlAccordionProps = { lvl: Level items: NavItem[] @@ -45,14 +47,15 @@ const LvlAccordion = ({ activeSection, onToggle, }: LvlAccordionProps) => { - const { asPath, locale } = useRouter() + const pathname = usePathname() + const locale = useLocale() const [value, setValue] = useState("") return ( {items.map(({ label, description, ...action }) => { const isLink = "href" in action - const isActivePage = isLink && cleanPath(asPath) === action.href + const isActivePage = isLink && cleanPath(pathname) === action.href const isExpanded = value === label const nestedAccordionSpacingMap = { diff --git a/src/components/Nav/Mobile/MenuBody.tsx b/src/components/Nav/Mobile/MenuBody.tsx index 70e7e2435b2..19dc48b7414 100644 --- a/src/components/Nav/Mobile/MenuBody.tsx +++ b/src/components/Nav/Mobile/MenuBody.tsx @@ -1,5 +1,5 @@ import { useState } from "react" -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import { cn } from "@/lib/utils/cn" import { trackCustomEvent } from "@/lib/utils/matomo" @@ -23,7 +23,7 @@ type MenuBodyProps = { } const MenuBody = ({ linkSections, onToggle }: MenuBodyProps) => { - const { locale } = useRouter() + const locale = useLocale() const [value, setValue] = useState("") return ( diff --git a/src/components/Nav/Mobile/MenuFooter.tsx b/src/components/Nav/Mobile/MenuFooter.tsx index db48b3a132c..0fb8c5672fb 100644 --- a/src/components/Nav/Mobile/MenuFooter.tsx +++ b/src/components/Nav/Mobile/MenuFooter.tsx @@ -1,4 +1,3 @@ -import { useTranslation } from "next-i18next" import { BsTranslate } from "react-icons/bs" import { MdBrightness2, MdSearch, MdWbSunny } from "react-icons/md" @@ -10,6 +9,7 @@ import FooterButton from "./FooterButton" import FooterItemText from "./FooterItemText" import useColorModeValue from "@/hooks/useColorModeValue" +import { useTranslation } from "@/hooks/useTranslation" type MenuFooterProps = { onToggle: () => void diff --git a/src/components/Nav/Mobile/MenuHeader.tsx b/src/components/Nav/Mobile/MenuHeader.tsx index 6d26290c881..b7c43fce378 100644 --- a/src/components/Nav/Mobile/MenuHeader.tsx +++ b/src/components/Nav/Mobile/MenuHeader.tsx @@ -1,7 +1,7 @@ -import { useTranslation } from "next-i18next" - import { SheetClose, SheetTitle } from "@/components/ui/sheet" +import { useTranslation } from "@/hooks/useTranslation" + const MenuHeader = () => { const { t } = useTranslation("common") diff --git a/src/components/Nav/index.tsx b/src/components/Nav/index.tsx index 66833cf7f4c..83f7547145d 100644 --- a/src/components/Nav/index.tsx +++ b/src/components/Nav/index.tsx @@ -1,6 +1,5 @@ import { useRef } from "react" import dynamic from "next/dynamic" -import { useTranslation } from "next-i18next" import { EthHomeIcon } from "@/components/icons" import Search from "@/components/Search" @@ -14,6 +13,7 @@ import { useNav } from "./useNav" import { useBreakpointValue } from "@/hooks/useBreakpointValue" import { useIsClient } from "@/hooks/useIsClient" +import { useTranslation } from "@/hooks/useTranslation" const Menu = dynamic(() => import("./Menu"), { ssr: false, diff --git a/src/components/Nav/useNav.ts b/src/components/Nav/useNav.ts index 95ab3496483..48f77916df0 100644 --- a/src/components/Nav/useNav.ts +++ b/src/components/Nav/useNav.ts @@ -1,4 +1,3 @@ -import { useTranslation } from "next-i18next" import { useTheme } from "next-themes" import { BsBook, @@ -18,7 +17,6 @@ import { BsUiChecksGrid, } from "react-icons/bs" import { PiFlask, PiUsersFourLight } from "react-icons/pi" -import { useColorMode } from "@chakra-ui/react" import EthereumIcon from "@/components/icons/ethereum-icon.svg" @@ -26,10 +24,11 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import type { NavSections } from "./types" +import useTranslation from "@/hooks/useTranslation" + export const useNav = () => { const { t } = useTranslation("common") const { setTheme, resolvedTheme } = useTheme() - const { setColorMode } = useColorMode() const linkSections: NavSections = { learn: { @@ -475,7 +474,6 @@ export const useNav = () => { const targetTheme = resolvedTheme === "dark" ? "light" : "dark" setTheme(targetTheme) - setColorMode(targetTheme) trackCustomEvent({ eventCategory: "nav bar", diff --git a/src/components/OldHeading.tsx b/src/components/OldHeading.tsx deleted file mode 100644 index e8f3a400ed4..00000000000 --- a/src/components/OldHeading.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Heading, type HeadingProps } from "@chakra-ui/react" - -/** - * @deprecated To be removed in favor of new Chakra Heading theme - * - * Renders a heading with the styles from the old theme. - */ -const OldHeading = (props: HeadingProps) => { - let mt = 8 - - if (typeof props.as === "undefined" || props.as === "h2") { - mt = 12 - } - - if (props.as === "h3") { - mt = 10 - } - - return -} - -export default OldHeading diff --git a/src/components/OldText.tsx b/src/components/OldText.tsx deleted file mode 100644 index 38cc17ee9de..00000000000 --- a/src/components/OldText.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Text, type TextProps } from "@chakra-ui/react" - -/** - * @deprecated To be removed in favor of new Chakra Text theme - * - * Renders body copy with a defined margin bottom for spacing (old theme) - */ -const OldText = (props: TextProps) => { - const mb = props.as && props.as !== "p" ? 0 : "1.45rem" - return -} - -export default OldText diff --git a/src/components/OrderedList.tsx b/src/components/OrderedList.tsx deleted file mode 100644 index a418f05670b..00000000000 --- a/src/components/OrderedList.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// Libraries -import React from "react" -import { - Box, - ListItem, - OrderedList as ChakraOrderedList, - SystemStyleObject, -} from "@chakra-ui/react" - -export type OrderedListProps = { - listData: Array -} - -/** - * The custom ordered list numbers in a solid circular background - */ -const liCustomType: SystemStyleObject = { - content: `counter(li-counter)`, - position: "absolute", - top: "-3px", // adjusts circle + number up and down - insetInlineStart: "-3rem", - width: "34px", - height: "1.6rem", - pt: "9px", // adjusts number up and down, - lineHeight: "100%", - borderRadius: "50%", - background: "grayBackground", - textAlign: "center", -} - -// `listData` should be a list of strings, or HTML components -// ex: [

string

] or ['string'] -const OrderedList = ({ listData }: OrderedListProps) => { - return ( - - - {listData.map((data, idx) => { - return ( - - {data} - - ) - })} - - - ) -} - -export default OrderedList diff --git a/src/components/PageHero.tsx b/src/components/PageHero.tsx index 15029253ad5..89062e01219 100644 --- a/src/components/PageHero.tsx +++ b/src/components/PageHero.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from "react" -import { type ImageProps, TwImage } from "@/components/Image" +import { Image, type ImageProps } from "@/components/Image" import { cn } from "@/lib/utils/cn" import { type MatomoEventOptions } from "@/lib/utils/matomo" @@ -131,7 +131,7 @@ const PageHero = ({ "w-full self-center" )} > - { - const { locale, locales: rawLocales, asPath } = useRouter() + const locale = useLocale() + const pathname = usePathname() const { t } = useTranslation() - const locales = filterRealLocales(rawLocales) + const locales = filterRealLocales(LOCALES_CODES) const desc = description || t("site-description") const siteTitle = t("site-title") // Remove any query params (?) or hash links (#) - const path = asPath.replace(/[?#].*/, "") + const path = pathname.replace(/[?#].*/, "") const slug = path.split("/") // Set canonical URL w/ language path to avoid duplicate content diff --git a/src/components/ProductCard.tsx b/src/components/ProductCard.tsx index 6d335c8f649..5efd34d4b56 100644 --- a/src/components/ProductCard.tsx +++ b/src/components/ProductCard.tsx @@ -1,5 +1,4 @@ import type { ImageProps } from "next/image" -import { useTranslation } from "next-i18next" import type { ReactNode } from "react" import { cn } from "@/lib/utils/cn" @@ -8,7 +7,9 @@ import { ButtonLink } from "./ui/buttons/Button" import { Center, Flex, HStack } from "./ui/flex" import { Tag } from "./ui/tag" import GitStars from "./GitStars" -import { TwImage } from "./Image" +import { Image } from "./Image" + +import { useTranslation } from "@/hooks/useTranslation" type SubjectBadgeProps = { subject: string @@ -87,7 +88,7 @@ const ProductCard = ({ )} >

- + {alt}
{githubRepoStars > 0 && ( diff --git a/src/components/ProductList.tsx b/src/components/ProductList.tsx index c3a6efaab4d..4a745682993 100644 --- a/src/components/ProductList.tsx +++ b/src/components/ProductList.tsx @@ -4,7 +4,7 @@ import { VisuallyHidden } from "@radix-ui/react-visually-hidden" import { ButtonLink } from "./ui/buttons/Button" import { Flex } from "./ui/flex" import { List, ListItem } from "./ui/list" -import { TwImage } from "./Image" +import { Image } from "./Image" type Content = { title: string @@ -37,7 +37,7 @@ const ProductList = ({ actionLabel, content, category }: ProductListProps) => {
{image && ( - > diff --git a/src/components/ProductTable/PresetFilters.tsx b/src/components/ProductTable/PresetFilters.tsx index ca6ed2023dc..f8251967003 100644 --- a/src/components/ProductTable/PresetFilters.tsx +++ b/src/components/ProductTable/PresetFilters.tsx @@ -1,9 +1,9 @@ -import { useTranslation } from "next-i18next" - import type { TPresetFilters } from "@/lib/types" import { cn } from "@/lib/utils/cn" +import { useTranslation } from "@/hooks/useTranslation" + export interface PresetFiltersProps { presets: TPresetFilters activePresets: number[] diff --git a/src/components/ProductTable/index.tsx b/src/components/ProductTable/index.tsx index 74e96d858a2..76a5f3f2568 100644 --- a/src/components/ProductTable/index.tsx +++ b/src/components/ProductTable/index.tsx @@ -90,9 +90,11 @@ const ProductTable = ({ })), })) setFilters(updatedFilters) - router.replace(router.pathname, undefined, { shallow: true }) + + // TODO: Fix this, removed to avoid infinite re-renders + // router.replace(pathname, undefined, { shallow: true }) } - }, [router]) + }, [router.query]) // Update or remove preset filters const handleSelectPreset = (idx: number) => { diff --git a/src/components/Quiz/QuizItem.tsx b/src/components/Quiz/QuizItem.tsx index 7a0565f9308..0088e5c2394 100644 --- a/src/components/Quiz/QuizItem.tsx +++ b/src/components/Quiz/QuizItem.tsx @@ -1,5 +1,3 @@ -import { useTranslation } from "next-i18next" - import type { QuizzesSection } from "@/lib/types" import { cn } from "@/lib/utils/cn" @@ -11,6 +9,8 @@ import { Flex, Stack } from "../ui/flex" import { ListItem } from "../ui/list" import { Tag } from "../ui/tag" +import { useTranslation } from "@/hooks/useTranslation" + export type QuizzesListItemProps = Omit & { isCompleted: boolean numberOfQuestions: number diff --git a/src/components/Quiz/QuizWidget/QuizRadioGroup.tsx b/src/components/Quiz/QuizWidget/QuizRadioGroup.tsx index b248677840a..73b4a4b7221 100644 --- a/src/components/Quiz/QuizWidget/QuizRadioGroup.tsx +++ b/src/components/Quiz/QuizWidget/QuizRadioGroup.tsx @@ -1,6 +1,5 @@ -import { useMemo } from "react" -import { useTranslation } from "next-i18next" -import { useRadio, useRadioGroup, UseRadioProps } from "@chakra-ui/react" +import { useMemo, useState } from "react" +import * as RadioGroup from "@radix-ui/react-radio-group" import type { AnswerChoice, @@ -15,6 +14,8 @@ import { cn } from "@/lib/utils/cn" import type { AnswerStatus } from "./useQuizWidget" +import useTranslation from "@/hooks/useTranslation" + type QuizRadioGroupProps = { questions: Question[] currentQuestionIndex: number @@ -30,21 +31,16 @@ export const QuizRadioGroup = ({ }: QuizRadioGroupProps) => { const { t } = useTranslation("learn-quizzes") + const [selectedAnswer, setSelectedAnswer] = + useState("") + const handleSelection = (answerId: AnswerKey) => { + setSelectedAnswer(answerId) const isCorrect = answerId === questions[currentQuestionIndex].correctAnswerId setCurrentQuestionAnswerChoice({ answerId, isCorrect }) } - const { - getRadioProps, - getRootProps, - value: selectedAnswer, - } = useRadioGroup({ - name: `quiz-question-${currentQuestionIndex}`, - onChange: handleSelection, - }) - const { answers, correctAnswerId, @@ -65,24 +61,24 @@ export const QuizRadioGroup = ({ ) return ( -
+
{t("question-number", { number: currentQuestionIndex + 1 })} {t(prompt)} - -
{answers.map(({ id, label }, idx) => { const display = !answerStatus || id === selectedAnswer ? "inline-flex" : "hidden" - return (
) })}
- {!!answerStatus && (

{t("explanation")}

@@ -104,12 +99,12 @@ export const QuizRadioGroup = ({

{t(explanation)}

)} -
+
) } -type CustomRadioProps = UseRadioProps & { +type CustomRadioProps = RadioGroup.RadioGroupItemProps & { index: number isAnswerVisible: boolean isSelectedCorrect: boolean @@ -117,73 +112,46 @@ type CustomRadioProps = UseRadioProps & { } const CustomRadio = ({ - isAnswerVisible, index, + isAnswerVisible, isSelectedCorrect, label, - ...radioProps + ...itemProps }: CustomRadioProps) => { - const INPUT_ID = `quiz-question-answer-${index}` - const { state, getInputProps, getRadioProps, getLabelProps } = useRadio({ - ...radioProps, - id: INPUT_ID, - }) - - const buttonBg = useMemo(() => { - if (!state.isChecked) return "bg-background-highlight" - if (!isAnswerVisible) return "bg-primary" - if (!isSelectedCorrect) return "bg-error" - return "bg-success" - }, [state.isChecked, isAnswerVisible, isSelectedCorrect]) - - const radioInputProps = getInputProps({ id: INPUT_ID }) - return ( - <> -
- void isDecentralizedAndSecure: boolean diff --git a/src/components/Trilemma/index.tsx b/src/components/Trilemma/index.tsx index af0602b3a4c..1e82fce90db 100644 --- a/src/components/Trilemma/index.tsx +++ b/src/components/Trilemma/index.tsx @@ -1,5 +1,3 @@ -import { useTranslation } from "next-i18next" - import Card from "@/components/Card" import { Flex, Stack, VStack } from "@/components/ui/flex" import { Sheet, SheetClose, SheetContent } from "@/components/ui/sheet" @@ -7,6 +5,8 @@ import { Sheet, SheetClose, SheetContent } from "@/components/ui/sheet" import { TriangleSVG, TriangleSVGProps } from "./Triangle" import { useTrilemma } from "./useTrilemma" +import { useTranslation } from "@/hooks/useTranslation" + const Trilemma = () => { const { t } = useTranslation("page-roadmap-vision") diff --git a/src/components/Trilemma/useTrilemma.tsx b/src/components/Trilemma/useTrilemma.tsx index cbe2bb60b5d..5ec36e1fb02 100644 --- a/src/components/Trilemma/useTrilemma.tsx +++ b/src/components/Trilemma/useTrilemma.tsx @@ -1,10 +1,11 @@ import { useState } from "react" -import { useTranslation } from "next-i18next" import { isMobile } from "@/lib/utils/isMobile" import { CardProps } from "../Card" +import { useTranslation } from "@/hooks/useTranslation" + /** * The `selection` param accepted values for the click handler */ diff --git a/src/components/TutorialMetadata.tsx b/src/components/TutorialMetadata.tsx index 0fbb8307100..263bdd28476 100644 --- a/src/components/TutorialMetadata.tsx +++ b/src/components/TutorialMetadata.tsx @@ -1,20 +1,21 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { Lang, TranslationKey } from "@/lib/types" import { TutorialFrontmatter } from "@/lib/interfaces" import CopyToClipboard from "@/components/CopyToClipboard" import Emoji from "@/components/Emoji" -import InlineLink from "@/components/Link" import Translation from "@/components/Translation" import TutorialTags from "@/components/TutorialTags" import { getLocaleTimestamp } from "@/lib/utils/time" import { Flex } from "./ui/flex" +import InlineLink from "./ui/Link" import { Tag } from "./ui/tag" +import { useTranslation } from "@/hooks/useTranslation" + export type TutorialMetadataProps = { frontmatter: TutorialFrontmatter timeToRead: number @@ -35,7 +36,7 @@ const TutorialMetadata = ({ frontmatter, timeToRead, }: TutorialMetadataProps) => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-developers-tutorials") const hasSource = frontmatter.source && frontmatter.sourceUrl diff --git a/src/components/UpcomingEventsList.tsx b/src/components/UpcomingEventsList.tsx index 107691f1b22..b6647600cb0 100644 --- a/src/components/UpcomingEventsList.tsx +++ b/src/components/UpcomingEventsList.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from "react" import _ from "lodash" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" import type { CommunityConference, Lang } from "@/lib/types" @@ -15,8 +14,10 @@ import { getLocaleTimestamp } from "@/lib/utils/time" import communityEvents from "@/data/community-events.json" +import { useTranslation } from "@/hooks/useTranslation" + const UpcomingEventsList = () => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-community") const monthsPerLoad = 2 diff --git a/src/components/UpgradeStatus.tsx b/src/components/UpgradeStatus.tsx index 6cf191099bb..ece95d25b6b 100644 --- a/src/components/UpgradeStatus.tsx +++ b/src/components/UpgradeStatus.tsx @@ -1,9 +1,9 @@ -import { useTranslation } from "next-i18next" - import type { TranslationKey } from "@/lib/types" import { cn } from "@/lib/utils/cn" +import { useTranslation } from "@/hooks/useTranslation" + export type UpgradeStatusProps = { children?: React.ReactNode dateKey: TranslationKey diff --git a/src/components/icons/HighlightDarkIcon.tsx b/src/components/icons/HighlightDarkIcon.tsx index 5f83dc9a052..1d6548d31f9 100644 --- a/src/components/icons/HighlightDarkIcon.tsx +++ b/src/components/icons/HighlightDarkIcon.tsx @@ -1,14 +1,10 @@ -import * as React from "react" -import { createIcon } from "@chakra-ui/react" +import { createIconBase } from "./icon-base" -export const HighlightDarkIcon = createIcon({ +export const HighlightDarkIcon = createIconBase({ displayName: "HighlightDarkIcon", viewBox: "0 0 280 28", - defaultProps: { - width: "280px", - height: "28px", - }, - path: ( + className: "w-[280px] h-[28px]", + children: ( +} satisfies Meta export default meta @@ -197,15 +196,10 @@ iconsDefinitions.sort((a, b) => const items = iconsDefinitions.map((IconDef) => (
- +
{IconDef.displayName}
@@ -213,6 +207,10 @@ const items = iconsDefinitions.map((IconDef) => ( export const Icons: StoryObj = { render: () => { - return {items} + return ( +
+ {items} +
+ ) }, } diff --git a/src/components/ui/Link.tsx b/src/components/ui/Link.tsx index ec1df595401..531c5cd0577 100644 --- a/src/components/ui/Link.tsx +++ b/src/components/ui/Link.tsx @@ -1,6 +1,5 @@ -import { AnchorHTMLAttributes, forwardRef } from "react" -import NextLink, { type LinkProps as NextLinkProps } from "next/link" -import { useRouter } from "next/router" +import { AnchorHTMLAttributes, ComponentProps, forwardRef } from "react" +import NextLink from "next/link" import { RxExternalLink } from "react-icons/rx" import { VisuallyHidden } from "@radix-ui/react-visually-hidden" @@ -12,6 +11,8 @@ import * as url from "@/lib/utils/url" import { DISCORD_PATH, SITE_URL } from "@/lib/constants" import { useRtlFlip } from "@/hooks/useRtlFlip" +import { Link as I18nLink } from "@/i18n/routing" +import { usePathname } from "@/i18n/routing" type BaseProps = { hideArrow?: boolean @@ -22,7 +23,7 @@ type BaseProps = { export type LinkProps = BaseProps & AnchorHTMLAttributes & - Omit + Omit, "href"> /** * Link wrapper which handles: @@ -49,7 +50,7 @@ export const BaseLink = forwardRef(function Link( }: LinkProps, ref ) { - const { asPath } = useRouter() + const pathname = usePathname() const { twFlipForRtl } = useRtlFlip() if (!href) { @@ -57,17 +58,17 @@ export const BaseLink = forwardRef(function Link( return } - const isActive = url.isHrefActive(href, asPath, isPartiallyActive) + const isActive = url.isHrefActive(href, pathname || "", isPartiallyActive) const isDiscordInvite = url.isDiscordInvite(href) - const isPdf = url.isPdf(href) + const isFile = url.isFile(href) const isExternal = url.isExternal(href) - const isInternalPdf = isPdf && !isExternal + const isInternalFile = isFile && !isExternal const isHash = url.isHash(href) - // Get proper download link for internally hosted PDF's & static files (ex: whitepaper) + // Get proper download link for internally hosted files (ex: whitepaper.pdf) // Opens in separate window. - if (isInternalPdf) { - href = getRelativePath(asPath, href) + if (isInternalFile && !href.startsWith("/")) { + href = "/" + getRelativePath(pathname, href) } if (isDiscordInvite) { @@ -112,15 +113,11 @@ export const BaseLink = forwardRef(function Link( ) } - if (isInternalPdf) { + if (isInternalFile) { return ( trackCustomEvent( customEventOptions ?? { @@ -160,7 +157,7 @@ export const BaseLink = forwardRef(function Link( } return ( - trackCustomEvent( customEventOptions ?? { @@ -174,7 +171,7 @@ export const BaseLink = forwardRef(function Link( {...commonProps} > {children} - + ) }) BaseLink.displayName = "BaseLink" diff --git a/src/components/ui/__stories__/Link.stories.tsx b/src/components/ui/__stories__/Link.stories.tsx index f76526c7551..72da6edf602 100644 --- a/src/components/ui/__stories__/Link.stories.tsx +++ b/src/components/ui/__stories__/Link.stories.tsx @@ -1,15 +1,15 @@ -import * as React from "react" -import { Center, ListItem, Stack, Text, UnorderedList } from "@chakra-ui/react" import { Meta, StoryObj } from "@storybook/react" +import { Center, Stack } from "../flex" import Link from "../Link" +import { ListItem, UnorderedList } from "../list" const meta = { title: "Molecules / Navigation / Links", component: Link, decorators: [ (Story) => ( -
+
), @@ -21,12 +21,12 @@ export default meta type Story = StoryObj const MockParagraph = ({ href }: { href: string }) => ( - +

Text body normal. Ethereum is open access to digital money and data-friendly services for everyone – no matter your background or location. It's a community-built technology behind the cryptocurrency ether (ETH) and thousands of applications you can use today. - +

) export const InternalLink: Story = { @@ -45,14 +45,14 @@ export const ExternalLink: Story = { export const LinkList: Story = { render: () => ( - - + +

Text body normal. Ethereum is open access to digital money and data-friendly services for everyone – no matter your background or location. It's a community-built technology behind the cryptocurrency ether (ETH) and thousands of applications you can use today. - +

{Array.from({ length: 9 }).map((_, idx) => ( diff --git a/src/components/ui/__stories__/Table/Table.stories.tsx b/src/components/ui/__stories__/Table/Table.stories.tsx index 15480c28fba..9da2168a39b 100644 --- a/src/components/ui/__stories__/Table/Table.stories.tsx +++ b/src/components/ui/__stories__/Table/Table.stories.tsx @@ -1,7 +1,9 @@ -import * as React from "react" -import { Flex } from "@chakra-ui/react" +import type { CSSProperties } from "react" import { Meta, StoryObj } from "@storybook/react" +import { screens } from "@/lib/utils/screen" + +import { Flex } from "../../flex" import { Table as TableComponent } from "../../table" import { @@ -15,7 +17,10 @@ const meta = { component: TableComponent, decorators: [ (Story) => ( - + ), diff --git a/src/components/ui/__stories__/Table/mockMdxData.tsx b/src/components/ui/__stories__/Table/mockMdxData.tsx index 4802cf6e842..48a220a289c 100644 --- a/src/components/ui/__stories__/Table/mockMdxData.tsx +++ b/src/components/ui/__stories__/Table/mockMdxData.tsx @@ -10,16 +10,6 @@ import { TableRow, } from "../../table" -/* - * Note on the Chakra Table components: - * - * Only the `TableCell`, `Th`, `Tr`, `TableBody`, and `TableHeader` components are used because those are the - * only table elements we are defining styles with and sending to the MDX provider - * - * The use of `align` is a mock for the `align` prop from the MDX parsing going to - * the former prop in the given Chakra component. - */ - export const MdxDemoData = () => ( <> diff --git a/src/components/ui/__stories__/Text.stories.tsx b/src/components/ui/__stories__/Text.stories.tsx index ccd292b4378..2ed713992d0 100644 --- a/src/components/ui/__stories__/Text.stories.tsx +++ b/src/components/ui/__stories__/Text.stories.tsx @@ -3,9 +3,9 @@ import { Meta, StoryObj } from "@storybook/react" import { cn } from "@/lib/utils/cn" -import LinkComponent from "../../Link" import Translation from "../../Translation" import { Center, Flex, Stack, VStack } from "../flex" +import LinkComponent from "../Link" const meta = { title: "Atoms / Typography / Text", diff --git a/src/components/Buttons/SvgButtonLink.tsx b/src/components/ui/buttons/SvgButtonLink.tsx similarity index 91% rename from src/components/Buttons/SvgButtonLink.tsx rename to src/components/ui/buttons/SvgButtonLink.tsx index 001216b2722..1e13dd7e51e 100644 --- a/src/components/Buttons/SvgButtonLink.tsx +++ b/src/components/ui/buttons/SvgButtonLink.tsx @@ -1,11 +1,12 @@ -import { cva, VariantProps } from "class-variance-authority" import type { FC, SVGProps } from "react" +import { tv, type VariantProps } from "tailwind-variants" import { cn } from "@/lib/utils/cn" -import { BaseLink, LinkProps } from "../ui/Link" +import { BaseLink, LinkProps } from "../Link" -const variants = cva("flex items-center gap-3.5", { +const variants = tv({ + base: "flex items-center gap-3.5", variants: { variant: { col: "flex-col text-center [&_.body]:text-center", diff --git a/src/components/ui/swiper.tsx b/src/components/ui/swiper.tsx index 9c6ef00a843..e74bcac005c 100644 --- a/src/components/ui/swiper.tsx +++ b/src/components/ui/swiper.tsx @@ -1,6 +1,5 @@ import * as React from "react" import { cva, VariantProps } from "class-variance-authority" -import { useTranslation } from "next-i18next" import { EffectCards, Keyboard, Navigation, Pagination } from "swiper/modules" import { Swiper as SwiperReact, @@ -20,6 +19,8 @@ import "swiper/css/navigation" import "swiper/css/pagination" import "swiper/css/effect-cards" +import { useTranslation } from "@/hooks/useTranslation" + const SwiperContainer = React.forwardRef< HTMLDivElement, React.HTMLAttributes diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx index abce6ca20f9..d5cf6206d1e 100644 --- a/src/components/ui/switch.tsx +++ b/src/components/ui/switch.tsx @@ -28,6 +28,6 @@ const Switch = React.forwardRef< ) }) -Switch.displayName = SwitchPrimitives.Root.displayName +Switch.displayName = "Switch" export default Switch diff --git a/src/data/NetworkUpgradeSummaryData.ts b/src/data/NetworkUpgradeSummaryData.ts index 7e9bb46a68a..302044d376b 100644 --- a/src/data/NetworkUpgradeSummaryData.ts +++ b/src/data/NetworkUpgradeSummaryData.ts @@ -1,6 +1,9 @@ import type { NetworkUpgradeData } from "@/lib/types" const NetworkUpgradeSummaryData: NetworkUpgradeData = { + pectra: { + isPending: true, + }, dencun: { dateTimeAsString: "2024-03-13T13:55:35.000Z", ethPriceInUSD: 3984, diff --git a/src/data/WalletSimulatorData.tsx b/src/data/WalletSimulatorData.tsx index b851087ee8b..24ecc556729 100644 --- a/src/data/WalletSimulatorData.tsx +++ b/src/data/WalletSimulatorData.tsx @@ -1,9 +1,9 @@ import { Stack } from "@/components/ui/flex" +import Link from "@/components/ui/Link" import { ListItem, OrderedList, UnorderedList } from "@/components/ui/list" import Emoji from "../components/Emoji" import GlossaryTooltip from "../components/Glossary/GlossaryTooltip" -import Link from "../components/Link" import { CONNECT_WEB3, CREATE_ACCOUNT, @@ -337,7 +337,7 @@ export const walletOnboardingSimData: SimulatorData = { <>

Your wallet can be used to connect to all sorts of applications, - allowing you to interact with your on-chain assets. + allowing you to interact with your onchain assets.

Your friend just sent an NFT art piece to your address! Let's @@ -354,7 +354,7 @@ export const walletOnboardingSimData: SimulatorData = { Your account is universal across all Ethereum and Ethereum-compatible applications.

-

Assets stored on-chain can be accessed from any application.

+

Assets stored onchain can be accessed from any application.

), }, diff --git a/src/data/chains.ts b/src/data/chains.ts index bb6f3691a8b..948a5fa472a 100644 --- a/src/data/chains.ts +++ b/src/data/chains.ts @@ -252,6 +252,17 @@ const chains = [ }, chain: "FETH", }, + { + name: "Unichain", + infoURL: "https://unichain.org", + chainId: 130, + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + chain: "ETH", + }, { name: "Defi Oracle Meta Mainnet", infoURL: "https://info.defi-oracle.io/", @@ -1594,6 +1605,17 @@ const chains = [ }, chain: "henez", }, + { + name: "Lumoz Chain Mainnet", + infoURL: "https://lumoz.org", + chainId: 96370, + nativeCurrency: { + name: "Lumoz Mainnet Token", + symbol: "MOZ", + decimals: 18, + }, + chain: "ETH", + }, { name: "Plume Devnet", infoURL: "https://plumenetwork.xyz/", diff --git a/src/data/community-events.json b/src/data/community-events.json index b48f24a5de1..2f770e57b72 100644 --- a/src/data/community-events.json +++ b/src/data/community-events.json @@ -42,7 +42,7 @@ "href": "https://ethkyiv.com", "location": "Kyiv, Ukraine", "description": "Welcome to the 1st edition of ETHKyiv, hosted this June 21-23 and bringing together participants from diverse backgrounds, including developers, designers, entrepreneurs, and blockchain enthusiasts!", - "imageUrl": "" + "imageUrl": "https://ethkyiv.com/_next/image?url=%2Fimages%2Fmain-banner_01.png&w=1920&q=75" }, { "title": "DappCon", @@ -237,7 +237,7 @@ "title": "BUIDL Asia", "startDate": "2025-04-15", "endDate": "2025-04-16", - "href": "https://-", + "href": "https://www.buidl.asia/", "location": "Seoul, KR", "description": "", "imageUrl": "" @@ -543,10 +543,10 @@ "title": "Crecimiento", "startDate": "2025-03-05", "endDate": "2025-03-28", - "href": "https://crecimientoar", - "location": "TBD, ARG", - "description": "", - "imageUrl": "" + "href": "https://aleph.crecimiento.build/", + "location": "Buenos Aires, Argentina", + "description": "The Crecimiento Pop-Up City is a moment-in-time for these visionaries to come together with renowned experts, and transform Argentina into a world-leading startup & innovation hub.", + "imageUrl": "https://cdn.prod.website-files.com/6661b1a3c1bce60cd61fc966/669e83df3c3a7535a9cc05fa_1200xlogo.png" }, { "title": "EthereumSF", @@ -617,7 +617,7 @@ "endDate": "2025-09-06", "href": "https://ethaccra.xyz", "location": "Accra, GHA", - "description": "", + "description": "ETHAccra", "imageUrl": "http://eth-accra-website.vercel.app/assets/pngs/meta_image.png" }, { @@ -628,5 +628,59 @@ "location": "Tokyo, JAP", "description": "View and subscribe to events from ETHTokyo on Luma. ETHTokyo", "imageUrl": "https://images.lumacdn.com/calendar-cover-images/rv/316a4b25-a9fb-4ff0-ab1a-d7f23a2ba0e0" + }, + { + "title": "Edge City Austin", + "startDate": "2025-03-02", + "endDate": "2025-03-07", + "href": "https://www.edgecity.live/austin", + "location": "Austin, USA", + "description": "Edge City Austin", + "imageUrl": "https://cdn.prod.website-files.com/65b2cb5abdecf7cd7747e170/67aba5d16f625f40658dde92_edge-sxsw-10.png" + }, + { + "title": "Edge Expedition South Africa", + "startDate": "2025-04-03", + "endDate": "2025-04-12", + "href": "https://www.edgecity.live/southafrica", + "location": "Capetown, ZA", + "description": "Edge Expedition | South Africa", + "imageUrl": "https://cdn.prod.website-files.com/65b2cb5abdecf7cd7747e170/67802a19fb53c877dd9f5eb0_og-southafricaexpedition%20(1).png" + }, + { + "title": "ETH Seoul", + "startDate": "2025-04-12", + "endDate": "2025-04-12", + "href": "https://ethseoul.org", + "location": "Seoul, KR", + "description": "", + "imageUrl": "" + }, + { + "title": "ETH Cinco de Mayo", + "startDate": "2025-05-01", + "endDate": "2025-05-04", + "href": "https://ethcdm.com/", + "location": "Mexico, MX", + "description": "ETH Cinco de Mayo Hackathon, Feb. 2nd-4th 2024, Puebla, Mexico. A perfect combination of competition, workshops, networking, entrepreneurship and culture!", + "imageUrl": "https://ethcdm.com/assets/images/og-918.jpg" + }, + { + "title": "World Expo on Blockchain*", + "startDate": "2025-05-10", + "endDate": "2025-06-03", + "href": "https://web2025.world/", + "location": "Osaka, JPN", + "description": "A future without financial inclusion, digital trust, data privacy and security is no future at all. Blockchain isn’t just relevant—it’s essential.", + "imageUrl": "https://framerusercontent.com/images/Ivp1oWg8CFUDERZIoey9dadW7E.png" + }, + { + "title": "ETHBratislava", + "startDate": "2025-05-23", + "endDate": "2025-05-25", + "href": "https://ethbratislava.com/", + "location": "Bratislava, SVK", + "description": "Two-day conference and hackathon focused on sharing knowledge and sparking innovative ideas aimed at energizing the entire ethereum ecosystem.", + "imageUrl": "https://framerusercontent.com/assets/IBAFZwu44FpNo95n3OoOapeFUyw.png" } ] diff --git a/src/data/crowdin/combined-translators.json b/src/data/crowdin/combined-translators.json index 0ff30db9288..6cf639ed389 100644 --- a/src/data/crowdin/combined-translators.json +++ b/src/data/crowdin/combined-translators.json @@ -3871,6 +3871,12 @@ { "fileId": "5487", "contributors": [ + { + "id": 15123193, + "username": "Coram_Deo", + "totalCosts": 505, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15123193/medium/b3211607cc43c707c0034f7502299d8d.jpeg" + }, { "id": 14920111, "username": "JueK3y", @@ -3896,7 +3902,7 @@ { "id": 15123193, "username": "Coram_Deo", - "totalCosts": 2176.55, + "totalCosts": 2276.54, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15123193/medium/b3211607cc43c707c0034f7502299d8d.jpeg" }, { @@ -8235,7 +8241,7 @@ { "id": 14568334, "username": "mr_giorgos", - "totalCosts": 377.74, + "totalCosts": 392.89, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14568334/medium/245b5c69aab62ffabb575daf603b70b8.jpg" } ] @@ -8246,7 +8252,7 @@ { "id": 14568334, "username": "mr_giorgos", - "totalCosts": 720.13, + "totalCosts": 728.21, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14568334/medium/245b5c69aab62ffabb575daf603b70b8.jpg" } ] @@ -31877,7 +31883,7 @@ { "id": 15954931, "username": "XofEE", - "totalCosts": 1165.54, + "totalCosts": 1260.48, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15954931/medium/7254d648c451b822632980e5bfcb61fa.png" }, { @@ -35578,18 +35584,18 @@ "totalCosts": 254.52, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15594493/medium/ada4e2f5276b6085495631bb59486bc8.gif" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 84.84, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 14907079, "username": "Ayano85", "totalCosts": 62.62, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14907079/medium/546f51cbefa424d02ea4aafec17bc45f_default.png" }, - { - "id": 14866604, - "username": "yeremiaryangunadi", - "totalCosts": 59.59, - "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" - }, { "id": 14682718, "username": "ketut", @@ -35999,7 +36005,7 @@ { "id": 14866604, "username": "yeremiaryangunadi", - "totalCosts": 106.05, + "totalCosts": 146.45, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" }, { @@ -36174,7 +36180,7 @@ { "id": 14866604, "username": "yeremiaryangunadi", - "totalCosts": 572.67, + "totalCosts": 598.93, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" }, { @@ -36392,18 +36398,18 @@ "totalCosts": 323.2, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15934037/medium/e913f10d6d3550452e0b7c072e15aa40.jpeg" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 99.99, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 14861756, "username": "RahayuRafika_12", "totalCosts": 84.84, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14861756/medium/68ce2b760b107d1cf2a5a1508aa8ee96.jpeg" }, - { - "id": 14866604, - "username": "yeremiaryangunadi", - "totalCosts": 74.74, - "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" - }, { "id": 14708760, "username": "hypebeans", @@ -36930,18 +36936,18 @@ "totalCosts": 264.62, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15927303/medium/e39f725004e850246a765bb86dddf780_default.png" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 175.74, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 14891244, "username": "vaiahmad", "totalCosts": 166.65, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14891244/medium/d51812ca6f71924544bf03b9a23efb68_default.png" }, - { - "id": 14866604, - "username": "yeremiaryangunadi", - "totalCosts": 144.43, - "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" - }, { "id": 15126147, "username": "anggunh", @@ -37357,7 +37363,7 @@ { "id": 14866604, "username": "yeremiaryangunadi", - "totalCosts": 50.5, + "totalCosts": 71.71, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" }, { @@ -38530,7 +38536,7 @@ { "id": 14866604, "username": "yeremiaryangunadi", - "totalCosts": 1550.35, + "totalCosts": 1580.65, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" }, { @@ -38791,6 +38797,12 @@ "username": "Ediii_id", "totalCosts": 34.34, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/16495377/medium/b5707b9b085d2e9bdb7e28873bbf24f2.jpg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 21.21, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -38873,6 +38885,12 @@ "username": "fuji.anggara10", "totalCosts": 16.16, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15934037/medium/e913f10d6d3550452e0b7c072e15aa40.jpeg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 15.15, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39071,6 +39089,12 @@ "totalCosts": 658.52, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15662523/medium/a1bde18af96dc28c3fd1c1dd610e8896.JPG" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 209.07, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 14861756, "username": "RahayuRafika_12", @@ -39190,6 +39214,12 @@ "username": "fuji.anggara10", "totalCosts": 371.68, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15934037/medium/e913f10d6d3550452e0b7c072e15aa40.jpeg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 15.15, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39207,6 +39237,12 @@ "username": "hypebeans", "totalCosts": 25.25, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14708760/medium/c99d5e08a676eaebe6f2a383a81222e1.jpg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 8.08, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39218,6 +39254,12 @@ "username": "fuji.anggara10", "totalCosts": 175.74, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15934037/medium/e913f10d6d3550452e0b7c072e15aa40.jpeg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 22.22, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39242,6 +39284,12 @@ "totalCosts": 102.01, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14861756/medium/68ce2b760b107d1cf2a5a1508aa8ee96.jpeg" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 36.36, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 15962457, "username": "danimeister", @@ -39459,6 +39507,12 @@ "username": "AI_bangkit", "totalCosts": 27.27, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/16863657/medium/0d11ffa1616fbe44fe28aa36c70cf2a6_default.png" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 12.12, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39493,6 +39547,12 @@ "username": "RahayuRafika_12", "totalCosts": 11.11, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14861756/medium/68ce2b760b107d1cf2a5a1508aa8ee96.jpeg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 7.07, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39807,6 +39867,12 @@ "totalCosts": 112.11, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15927303/medium/e39f725004e850246a765bb86dddf780_default.png" }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 7.07, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" + }, { "id": 15620833, "username": "IrfanSidik.id", @@ -39862,6 +39928,12 @@ "username": "danimeister", "totalCosts": 595.9, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15962457/medium/97c701528b519a4a784b0d6b5f845fb8.jpg" + }, + { + "id": 14866604, + "username": "yeremiaryangunadi", + "totalCosts": 47.47, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" } ] }, @@ -39894,7 +39966,7 @@ { "id": 14866604, "username": "yeremiaryangunadi", - "totalCosts": 127.26, + "totalCosts": 141.4, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14866604/medium/285a89179a206f3621ba14bf04085b27.png" }, { @@ -40953,6 +41025,12 @@ "totalCosts": 79.79, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15185884/medium/0d349af8ba0364fdd96b55b46c40590c.jpg" }, + { + "id": 14618598, + "username": "emanuele-vacca", + "totalCosts": 36.36, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14618598/medium/42897a4bea750f0e5720bb0fe6f23077.jpg" + }, { "id": 15754717, "username": "Tgualtieri1976", @@ -41015,6 +41093,12 @@ "username": "Herbie_23", "totalCosts": 1105.95, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/13461670/medium/c9291075edb8582a7efe26fe983237e1.jpg" + }, + { + "id": 14618598, + "username": "emanuele-vacca", + "totalCosts": 59.59, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14618598/medium/42897a4bea750f0e5720bb0fe6f23077.jpg" } ] }, @@ -41033,6 +41117,12 @@ "totalCosts": 423.19, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15946127/medium/fb8809671278895b42cf50c752fd7bf2.png" }, + { + "id": 14618598, + "username": "emanuele-vacca", + "totalCosts": 78.78, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14618598/medium/42897a4bea750f0e5720bb0fe6f23077.jpg" + }, { "id": 15185884, "username": "carmen1912", @@ -41091,6 +41181,12 @@ "totalCosts": 41.41, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15266690/medium/beb929d96ab06718fce198051fdffaae.jpg" }, + { + "id": 14618598, + "username": "emanuele-vacca", + "totalCosts": 40.4, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14618598/medium/42897a4bea750f0e5720bb0fe6f23077.jpg" + }, { "id": 15754717, "username": "Tgualtieri1976", @@ -45465,7 +45561,7 @@ { "id": 14618598, "username": "emanuele-vacca", - "totalCosts": 3496.62, + "totalCosts": 4618.73, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14618598/medium/42897a4bea750f0e5720bb0fe6f23077.jpg" }, { @@ -49702,6 +49798,12 @@ "totalCosts": 105.04, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15488702/medium/05e244b35702080883c4e5730ef4d1e5.jpeg" }, + { + "id": 14899254, + "username": "shouki", + "totalCosts": 101, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/14899254/medium/68c57b6a2745f9ffc60fab8463011d87.jpeg" + }, { "id": 14880458, "username": "sekisanchi", @@ -58947,6 +59049,12 @@ "totalCosts": 475.71, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/15515516/medium/cad56d6fa7c03af94b18ead23e791019.png" }, + { + "id": 13315100, + "username": "timbalabuch", + "totalCosts": 177.76, + "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/13315100/medium/eb8b94eb99e44f8a238e797e9adb078a.JPG" + }, { "id": 16496053, "username": "henderson.mateus1", @@ -62191,7 +62299,7 @@ { "id": 13315100, "username": "timbalabuch", - "totalCosts": 142.41, + "totalCosts": 787.8, "avatarUrl": "https://crowdin-static.cf-downloads.crowdin.com/avatar/13315100/medium/eb8b94eb99e44f8a238e797e9adb078a.JPG" }, { diff --git a/src/data/externalTutorials.json b/src/data/externalTutorials.json index 7204118e040..18b3512f1e1 100644 --- a/src/data/externalTutorials.json +++ b/src/data/externalTutorials.json @@ -557,7 +557,7 @@ { "url": "https://docs.replit.com/tutorials/web3/build-smart-contract-oracle", "title": "Build a smart contract oracle with Solidity, Node.js, and Replit", - "description": "Learn how to use oracles in smart contracts and how oracles work internally, and gain experience with hybrid on-and-off chain systems.", + "description": "Learn how to use oracles in smart contracts and how oracles work internally, and gain experience with hybrid on-and-offchain systems.", "author": "replit", "authorGithub": "https://github.com/replit", "tags": ["solidity", "oracles", "javascript"], diff --git a/src/data/published.json b/src/data/published.json index 0c4018d6eb6..3afb12a725c 100644 --- a/src/data/published.json +++ b/src/data/published.json @@ -1 +1 @@ -{"date":"2025-02-12"} +{"date":"2025-02-25"} diff --git a/src/data/translationProgress.json b/src/data/translationProgress.json index 8642addad15..a4d4373cec9 100644 --- a/src/data/translationProgress.json +++ b/src/data/translationProgress.json @@ -79,7 +79,7 @@ { "languageId": "cs", "words": { - "approved": 113096, + "approved": 132738, "total": 277274 } }, @@ -114,7 +114,7 @@ { "languageId": "el", "words": { - "approved": 205960, + "approved": 216561, "total": 277274 } }, @@ -177,14 +177,14 @@ { "languageId": "fr", "words": { - "approved": 272957, + "approved": 276688, "total": 277274 } }, { "languageId": "ga-IE", "words": { - "approved": 0, + "approved": 392, "total": 277336 } }, @@ -240,7 +240,7 @@ { "languageId": "hu", "words": { - "approved": 260003, + "approved": 260460, "total": 277274 } }, @@ -268,7 +268,7 @@ { "languageId": "it", "words": { - "approved": 271658, + "approved": 272957, "total": 277274 } }, @@ -464,7 +464,7 @@ { "languageId": "pt-BR", "words": { - "approved": 266613, + "approved": 267177, "total": 277274 } }, @@ -569,7 +569,7 @@ { "languageId": "te", "words": { - "approved": 26550, + "approved": 26691, "total": 277274 } }, @@ -625,7 +625,7 @@ { "languageId": "uk", "words": { - "approved": 81899, + "approved": 81999, "total": 277274 } }, diff --git a/src/hooks/useCentralizedExchanges.ts b/src/hooks/useCentralizedExchanges.ts index da6544c9f77..b89b56afdbe 100644 --- a/src/hooks/useCentralizedExchanges.ts +++ b/src/hooks/useCentralizedExchanges.ts @@ -1,7 +1,6 @@ import { useState } from "react" import shuffle from "lodash/shuffle" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" +import { useLocale } from "next-intl" // TODO: Remove unused? // import argent from "@/public/images/wallets/argent.png" @@ -18,6 +17,7 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import exchangeData from "@/data/exchangesByCountry" +import { useTranslation } from "@/hooks/useTranslation" import binance from "@/public/images/exchanges/binance.png" import bitbuy from "@/public/images/exchanges/bitbuy.png" import bitfinex from "@/public/images/exchanges/bitfinex.png" @@ -303,7 +303,7 @@ const exchanges: ExchangeDetails = { } export const useCentralizedExchanges = () => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-get-eth") const [selectedCountry, setSelectedCountry] = useState() diff --git a/src/hooks/useLocaleDirection.ts b/src/hooks/useLocaleDirection.ts index e9f86e376bf..ba9213c81f0 100644 --- a/src/hooks/useLocaleDirection.ts +++ b/src/hooks/useLocaleDirection.ts @@ -1,5 +1,5 @@ -import { useEffect, useState } from "react" -import { useRouter } from "next/router" +import { useEffect } from "react" +import { useLocale } from "next-intl" import { Lang } from "@/lib/types" @@ -9,15 +9,11 @@ import { isLangRightToLeft } from "@/lib/utils/translations" * Custom hook that sets the DOM direction based on the locale, * responding to changes in the locale without requiring refresh. */ -export const useLocaleDirection = (): string => { - const [direction, setDirection] = useState<"ltr" | "rtl">("ltr") - const { locale } = useRouter() +export const useLocaleDirection = () => { + const locale = useLocale() useEffect(() => { const dir = isLangRightToLeft(locale as Lang) ? "rtl" : "ltr" document.documentElement.setAttribute("dir", dir) - setDirection(dir) }, [locale]) - - return direction } diff --git a/src/hooks/useRtlFlip.ts b/src/hooks/useRtlFlip.ts index 3c684d06800..07fb662a140 100644 --- a/src/hooks/useRtlFlip.ts +++ b/src/hooks/useRtlFlip.ts @@ -1,4 +1,4 @@ -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import type { Lang } from "@/lib/types" @@ -18,7 +18,7 @@ type UseDirection = { * @returns An object containing the Tailwind className, RTL flag, and direction. */ export const useRtlFlip = (): UseDirection => { - const { locale } = useRouter() + const locale = useLocale() const isRtl = isLangRightToLeft(locale as Lang) return { flipForRtl: isRtl ? "scaleX(-1)" : undefined, // transform (deprecated) diff --git a/src/hooks/useStakingConsiderations.tsx b/src/hooks/useStakingConsiderations.tsx index 70b070f6ebe..d315d17ded3 100644 --- a/src/hooks/useStakingConsiderations.tsx +++ b/src/hooks/useStakingConsiderations.tsx @@ -1,5 +1,4 @@ import { ElementType, useState } from "react" -import { useTranslation } from "next-i18next" import type { StakingPage } from "@/lib/types" @@ -20,6 +19,8 @@ import { StakingConsiderationsProps } from "@/components/Staking/StakingConsider import { MatomoEventOptions } from "@/lib/utils/matomo" +import { useTranslation } from "@/hooks/useTranslation" + type DataType = { title: string description: string diff --git a/src/hooks/useSurvey.ts b/src/hooks/useSurvey.ts index b8fcb8f0ba1..a9762ca738b 100644 --- a/src/hooks/useSurvey.ts +++ b/src/hooks/useSurvey.ts @@ -1,15 +1,21 @@ import path from "path" import { useMemo } from "react" -import { useRouter } from "next/router" +import { useLocale } from "next-intl" import type { Lang } from "@/lib/types" import { SITE_URL } from "@/lib/constants" +import { usePathname } from "@/i18n/routing" + export const useSurvey = (feedbackSubmitted: boolean) => { - const { asPath, locale } = useRouter() - const { href: url } = new URL(path.join(locale! as Lang, asPath), SITE_URL) + const locale = useLocale() + const pathname = usePathname() + const { href: url } = new URL( + path.join(locale! as Lang, pathname || ""), + SITE_URL + ) return useMemo((): string | null => { if (!feedbackSubmitted) return null return `https://ethereumorg.paperform.co//?url=${url}` diff --git a/src/hooks/useTranslation.ts b/src/hooks/useTranslation.ts new file mode 100644 index 00000000000..9928ae365b1 --- /dev/null +++ b/src/hooks/useTranslation.ts @@ -0,0 +1,55 @@ +import { useTranslations } from "next-intl" + +/** + * Cases to handle: + * + * - using t("key") + * - & useTranslation() => "common.key" + * - & useTranslation("namespace") => "namespace.key" + * - & useTranslation(["namespace1", "namespace2"]) => "namespace1.key" + * + * - using t("namespace:key") + * - & useTranslation("namespace") and t("namespace:key") => "namespace.key" + * - & useTranslation(["namespace1", "namespace2"]) and t("namespace1:key") => "namespace1.key" + * - & useTranslation(["namespace1", "namespace2"]) and t("namespace2:key") => "namespace2.key" + */ + +const DEFAULT_NAMESPACE = "common" + +export function useTranslation(namespaces?: string[] | string) { + const t = useTranslations() + + const customT: typeof t = (fullKey, values) => { + try { + if (fullKey.includes(":")) { + const [namespace, key] = fullKey.split(":") + + if (values) { + return t(`${namespace}.${key}`, values) + } + + return t.raw(`${namespace}.${key}`) + } + + const namespace = Array.isArray(namespaces) + ? namespaces[0] + : namespaces || DEFAULT_NAMESPACE + + return t.raw(`${namespace}.${fullKey}`) + } catch (error) { + // Suppress errors by default, enable if needed to debug + // console.error(error) + return fullKey + } + } + + // keep the original methods + customT.raw = t.raw + customT.rich = t.rich + customT.markup = t.markup + customT.has = t.has + + return { t: customT } +} + +export default useTranslation diff --git a/src/i18n/loadNamespaces.ts b/src/i18n/loadNamespaces.ts new file mode 100644 index 00000000000..c5940b2ebd1 --- /dev/null +++ b/src/i18n/loadNamespaces.ts @@ -0,0 +1,31 @@ +import { DEFAULT_LOCALE } from "@/lib/constants" + +export default async function loadNamespaces( + locale: string, + namespaces: string[] +) { + const byNamespace = await Promise.all( + namespaces.map(async (namespace) => { + try { + const defaultNamespace = ( + await import(`../intl/${DEFAULT_LOCALE}/${namespace}.json`) + ).default + const localeNamespace = ( + await import(`../intl/${locale}/${namespace}.json`) + ).default + + // Merge the namespaces to have default translations for keys that are not present in the locale + return { ...defaultNamespace, ...localeNamespace } + } catch (error) { + // If the namespace is not found, return the default namespace + return (await import(`../intl/${DEFAULT_LOCALE}/${namespace}.json`)) + .default + } + }) + ) + + return byNamespace.reduce((acc, namespace, index) => { + acc[namespaces[index]] = namespace + return acc + }, {}) +} diff --git a/src/i18n/request.ts b/src/i18n/request.ts new file mode 100644 index 00000000000..c27ae4c2bc0 --- /dev/null +++ b/src/i18n/request.ts @@ -0,0 +1,20 @@ +import { getRequestConfig } from "next-intl/server" + +import { Lang } from "@/lib/types" + +import { routing } from "./routing" + +export default getRequestConfig(async ({ requestLocale }) => { + // This typically corresponds to the `[locale]` segment + let locale = await requestLocale + + // Ensure that the incoming locale is valid + if (!locale || !routing.locales.includes(locale as Lang)) { + locale = routing.defaultLocale + } + + return { + locale, + messages: (await import(`../../intl/${locale}/common.json`)).default, + } +}) diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts new file mode 100644 index 00000000000..9e4a073dca4 --- /dev/null +++ b/src/i18n/routing.ts @@ -0,0 +1,14 @@ +import { createNavigation } from "next-intl/navigation" +import { defineRouting } from "next-intl/routing" + +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +export const routing = defineRouting({ + locales: LOCALES_CODES, + defaultLocale: DEFAULT_LOCALE, +}) + +// Lightweight wrappers around Next.js' navigation APIs +// that will consider the routing configuration +export const { Link, redirect, usePathname, useRouter, getPathname } = + createNavigation(routing) diff --git a/src/intl/en/glossary-tooltip.json b/src/intl/en/glossary-tooltip.json index 17099323f81..ac6643bde32 100644 --- a/src/intl/en/glossary-tooltip.json +++ b/src/intl/en/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "A software client that participates in the network.
More on nodes and clients.", "ommer-term": "Ommer (uncle) block", "ommer-definition": "When a proof-of-work miner finds a valid block, another miner may have published a competing block which is added to the tip of the blockchain first. This valid, but stale, block can be included by newer blocks as ommers and receive a partial block reward. The term \"ommer\" is the preferred gender-neutral term for the sibling of a parent block, but this is also sometimes referred to as an \"uncle\". This was common for Ethereum when it was a proof-of-work network. Now that Ethereum uses proof-of-stake, only one block proposer is selected per slot.", - "on-chain-term": "On-chain", - "on-chain-definition": "Refers to actions or transactions that happen on the blockchain and are publicly available.", + "onchain-term": "Onchain", + "onchain-definition": "Refers to actions or transactions that happen on the blockchain and are publicly available.", "optimistic-rollup-term": "Optimistic rollup", "optimistic-rollup-definition": "Optimistic Rollup is a Layer 2 solution that speeds up transactions on Ethereum, assuming they're valid by default unless challenged. More on Optimistic rollups.", "peer-to-peer-network-term": "Peer-to-peer network", @@ -150,7 +150,7 @@ "validator-term": "Validator", "validator-definition": "A node in a proof-of-stake system responsible for storing data, processing transactions, and adding new blocks to the blockchain. To activate validator software, you need to be able to stake 32 ETH. More on staking in Ethereum.", "validity-proof-term": "Validity proof", - "validity-proof-definition": "A security model for certain layer 2 solutions where, to increase speed, transactions are rolled up into batches and submitted to Ethereum in a single transaction. The transaction computation is done off-chain and then supplied to the main chain with a proof of their validity. This method increases the amount of transactions possible while maintaining security. Some rollups use fraud proof. More on zero-knowledge rollups.", + "validity-proof-definition": "A security model for certain layer 2 solutions where, to increase speed, transactions are rolled up into batches and submitted to Ethereum in a single transaction. The transaction computation is done offchain and then supplied to the main chain with a proof of their validity. This method increases the amount of transactions possible while maintaining security. Some rollups use fraud proof. More on zero-knowledge rollups.", "wallet-term": "Wallet", "wallet-definition": "A wallet is a digital tool to store, send, and receive digital currency, like a virtual purse for your online money. More on Ethereum wallets.", "web2-term": "Web2", diff --git a/src/intl/en/glossary.json b/src/intl/en/glossary.json index b878aff0a80..90ae44a9515 100644 --- a/src/intl/en/glossary.json +++ b/src/intl/en/glossary.json @@ -112,7 +112,7 @@ "distributed-hash-table-term": "Distributed hash table (DHT)", "distributed-hash-table-definition": "A data structure containing `(key, value)` pairs used by Ethereum nodes to identify peers to connect to and determine which protocols to use to communicate.", "double-spend-term": "Double spend", - "double-spend-definition": "A deliberate blockchain fork, where a user with a sufficiently large amount of mining power/stake sends a transaction moving some currency off-chain (e.g. exiting into fiat money or making an off-chain purchase) then reorganizing the blockchain to remove that transaction. A successful double spend leaves the attacker with both their on and off-chain assets.", + "double-spend-definition": "A deliberate blockchain fork, where a user with a sufficiently large amount of mining power/stake sends a transaction moving some currency offchain (e.g. exiting into fiat money or making an offchain purchase) then reorganizing the blockchain to remove that transaction. A successful double spend leaves the attacker with both their on and offchain assets.", "ecdsa-term": "Elliptic Curve Digital Signature Algorithm (ECDSA)", "ecdsa-definition": "A cryptographic algorithm used by Ethereum to ensure that funds can only be spent by their owners. It's the preferred method for creating public and private keys. Relevant for account address generation and transaction verification.", "encryption-term": "Encryption", @@ -257,16 +257,16 @@ "node-definition": "A software client that participates in the network. More on nodes and clients.", "nonce-term": "Nonce", "nonce-definition": "In cryptography, a value that can only be used once. An account nonce is a transaction counter in each account, which is used to prevent replay attacks.", - "off-chain-term": "Off-Chain", - "off-chain-definition": "Off-chain means any transaction or data that exists outside the blockchain. Because committing every transaction on-chain can be expensive and inefficient, third-party tools like oracles that handle pricing data, or layer 2 solutions that execute a higher throughput of transactions, handle a bulk of the processing work off-chain, and will submit information on-chain at less frequent intervals.", + "offchain-term": "Offchain", + "offchain-definition": "Offchain means any transaction or data that exists outside the blockchain. Because committing every transaction onchain can be expensive and inefficient, third-party tools like oracles that handle pricing data, or layer 2 solutions that execute a higher throughput of transactions, handle a bulk of the processing work offchain, and will submit information onchain at less frequent intervals.", "ommer-term": "Ommer (uncle) block", "ommer-definition": "When a proof-of-work miner finds a valid block, another miner may have published a competing block which is added to the tip of the blockchain first. This valid, but stale, block can be included by newer blocks as ommers and receive a partial block reward. The term \"ommer\" is the preferred gender-neutral term for the sibling of a parent block, but this is also sometimes referred to as an \"uncle\". This was common for Ethereum when it was a proof-of-work network. Now that Ethereum uses proof-of-stake, only one block proposer is selected per slot.", - "on-chain-term": "On-Chain", - "on-chain-definition": "Refers to actions or transactions that happen on the blockchain and are publicly available.

Think of it as writing something in a big, shared notebook that everyone can see and check, making sure that whatever is written (like sending digital money or making a contract) is permanent and can't be changed or erased.", + "onchain-term": "Onchain", + "onchain-definition": "Refers to actions or transactions that happen on the blockchain and are publicly available.

Think of it as writing something in a big, shared notebook that everyone can see and check, making sure that whatever is written (like sending digital money or making a contract) is permanent and can't be changed or erased.", "optimistic-rollup-term": "Optimistic rollup", "optimistic-rollup-definition": "Optimistic Rollup is a Layer 2 solution that speeds up transactions on Ethereum, assuming they're valid by default unless challenged. More on Optimistic rollups.", "oracle-term": "Oracle", - "oracle-definition": "An oracle is a bridge between the blockchain and the real world. They act as on-chain APIs that can be queried for information and used in smart contracts. More on oracles.", + "oracle-definition": "An oracle is a bridge between the blockchain and the real world. They act as onchain APIs that can be queried for information and used in smart contracts. More on oracles.", "peer-term": "Peer", "peer-definition": "Connected computers running Ethereum client software that have identical copies of the blockchain.", "peer-to-peer-network-term": "Peer-to-peer network", @@ -274,7 +274,7 @@ "permissionless-term": "Permissionless", "permissionless-definition": "Permissionless means anyone can join and use a system like Ethereum. It's open for everyone to participate and doesn't require any approval.", "plasma-term": "Plasma", - "plasma-definition": "An off-chain scaling solution that uses fraud proofs, like optimistic rollups. Plasma is limited to simple transactions like basic token transfers and swaps. More on plasma.", + "plasma-definition": "An offchain scaling solution that uses fraud proofs, like optimistic rollups. Plasma is limited to simple transactions like basic token transfers and swaps. More on plasma.", "private-key-term": "Private key", "private-key-definition": "A private key is a secret code that proves you own your digital money and lets you spend it, like a PIN for your account. DO NOT SHARE IT.", "public-goods-term": "Public goods", @@ -378,9 +378,9 @@ "validator-lifecycle-term": "Validator lifecycle", "validator-lifecycle-definition": "The sequence of states that a validator can exist in. These include:

  • deposited: At least 32 ETH has been deposited to the deposit contract by the validator
  • pending: the validator is in the activation queue waiting to be voted into the network by existing validators
  • active: currently attesting and proposing blocks
  • slashing: the validator has misbehaved and is being slashed
  • exiting: the validator has been flagged for exiting the network, either voluntarily or because they have been ejected.
", "validity-proof-term": "Validity proof", - "validity-proof-definition": "A security model for certain layer 2 solutions where, to increase speed, transactions are rolled up into batches and submitted to Ethereum in a single transaction. The transaction computation is done off-chain and then supplied to the main chain with a proof of their validity. This method increases the amount of transactions possible while maintaining security. Some rollups use fraud proof. More on zero-knowledge rollups.", + "validity-proof-definition": "A security model for certain layer 2 solutions where, to increase speed, transactions are rolled up into batches and submitted to Ethereum in a single transaction. The transaction computation is done offchain and then supplied to the main chain with a proof of their validity. This method increases the amount of transactions possible while maintaining security. Some rollups use fraud proof. More on zero-knowledge rollups.", "validium-term": "Validium", - "validium-definition": "An off-chain solution that uses validity proofs to improve transaction throughput. Unlike Zero-knowledge rollups, validium data isn't stored on layer 1 Mainnet. More on validium.", + "validium-definition": "An offchain solution that uses validity proofs to improve transaction throughput. Unlike Zero-knowledge rollups, validium data isn't stored on layer 1 Mainnet. More on validium.", "vyper-term": "Vyper", "vyper-definition": "A high-level programming language with Python-like syntax. Intended to get closer to a pure functional language. Created by Vitalik Buterin. More on Vyper.", "wallet-term": "Wallet", diff --git a/src/intl/en/learn-quizzes.json b/src/intl/en/learn-quizzes.json index 1b41af9995c..62ca7fc486e 100644 --- a/src/intl/en/learn-quizzes.json +++ b/src/intl/en/learn-quizzes.json @@ -348,7 +348,7 @@ "daos-3-a-label": "Usually hierarchical", "daos-3-a-explanation": "DAOs are usually flat, and fully democratized.", "daos-3-b-label": "Transparent and fully public about their activities", - "daos-3-b-explanation": "Thanks to on-chain voting, decisions are transparent on the blockchain. Discussions and other elements of the decision-making process are open to all members.", + "daos-3-b-explanation": "Thanks to onchain voting, decisions are transparent on the blockchain. Discussions and other elements of the decision-making process are open to all members.", "daos-3-c-label": "Controlled by a central party", "daos-3-c-explanation": "Changes require voting by the members. Services offered are handled automatically in a decentralized manner.", "daos-3-d-label": "Restricted regarding who can suggest changes", @@ -369,8 +369,8 @@ "daos-5-b-explanation": "Share-based DAOs are more permissioned but still quite open. Any prospective member can submit a proposal to join the DAO, usually offering a tribute of some value in the form of tokens or work.", "daos-5-c-label": "Reputation-based membership", "daos-5-c-explanation": "Unlike token or share-based membership, reputation-based DAOs don't transfer ownership to contributors. DAO members must earn reputation through participation.", - "daos-5-d-label": "Executive board and off-chain treasury management", - "daos-5-d-explanation": "This approach uses highly centralized and opaque mechanisms of governing. On the contrary, DAOs use verifiable voting mechanisms and on-chain treasury management to ensure transparency and accountability.", + "daos-5-d-label": "Executive board and offchain treasury management", + "daos-5-d-explanation": "This approach uses highly centralized and opaque mechanisms of governing. On the contrary, DAOs use verifiable voting mechanisms and onchain treasury management to ensure transparency and accountability.", "staking-solo-1-prompt": "Which is true about slashing?", "staking-solo-1-a-label": "Penalty for being offline, rewards resume when back online", "staking-solo-1-a-explanation": "Being offline does NOT result in slashing. Small penalties are incurred for being offline, and rewards resume when the validator returns online and resumes attestations.", diff --git a/src/intl/en/page-dapps.json b/src/intl/en/page-dapps.json index 9c8734d69f2..9ecb4862060 100644 --- a/src/intl/en/page-dapps.json +++ b/src/intl/en/page-dapps.json @@ -97,7 +97,7 @@ "page-dapps-dapp-description-meeds": "Web3 community hubs for the age of decentralized work. Reward fairly and transparently contributions that matter.", "page-dapps-dapp-description-mirror": "Built on web3 for web3, Mirror’s robust publishing platform pushes the boundaries of writing online", "page-dapps-dapp-description-multichain": "The ultimate Router for web3. It is an infrastructure developed for arbitrary cross-chain interactions.", - "page-dapps-dapp-description-nifty-gateway": "Buy works on-chain from top artists, athletes, brands, and creators.", + "page-dapps-dapp-description-nifty-gateway": "Buy works onchain from top artists, athletes, brands, and creators.", "page-dapps-dapp-description-summerfi": "Trade, borrow, and save with Dai, an Ethereum stablecoin.", "page-dapps-dapp-description-opensea": "Buy, sell, discover, and trade limited-edition goods.", "page-dapps-dapp-description-opera": "Send crypto from your browser to merchants, other users and apps.", @@ -198,7 +198,7 @@ "page-dapps-hero-header": "Ethereum-powered tools and services", "page-dapps-hero-subtitle": "Dapps are a growing movement of applications that use Ethereum to disrupt business models or invent new ones.", "page-dapps-how-dapps-work-p1": "Dapps have their backend code (smart contracts) running on a decentralized network and not a centralized server. They use the Ethereum blockchain for data storage and smart contracts for their app logic.", - "page-dapps-how-dapps-work-p2": "A smart contract is like a set of rules that live on-chain for all to see and run exactly according to those rules. Imagine a vending machine: if you supply it with enough funds and the right selection, you'll get the item you want. And like vending machines, smart contracts can hold funds much like your Ethereum account. This allows code to mediate agreements and transactions.", + "page-dapps-how-dapps-work-p2": "A smart contract is like a set of rules that live onchain for all to see and run exactly according to those rules. Imagine a vending machine: if you supply it with enough funds and the right selection, you'll get the item you want. And like vending machines, smart contracts can hold funds much like your Ethereum account. This allows code to mediate agreements and transactions.", "page-dapps-how-dapps-work-p3": "Once dapps are deployed on the Ethereum network you can't change them. Dapps can be decentralized because they are controlled by the logic written into the contract, not an individual or a company.", "page-dapps-how-dapps-work-title": "How dapps work", "page-dapps-ipfs-logo-alt": "IPFS logo", @@ -283,7 +283,7 @@ "page-wallets-get-some": "Get some ETH", "page-dapps-dapp-description-curve": "Curve is a dex focused on stablecoins", "page-dapps-curve-image-alt": "Curve logo", - "page-dapps-dapp-description-dodo": "DODO is a on-chain liquidity provider, which leverages the Proactive Market Maker algorithm (PMM)", + "page-dapps-dapp-description-dodo": "DODO is a onchain liquidity provider, which leverages the Proactive Market Maker algorithm (PMM)", "page-dapps-dodo-image-alt": "DODO logo", "page-dapps-dapp-description-artblocks": "Art Blocks is dedicated to bringing compelling works of contemporary generative art to life", "page-dapps-artblocks-image-alt": "Art Blocks logo", diff --git a/src/intl/en/page-developers-index.json b/src/intl/en/page-developers-index.json index f4e6a175f5e..f03059ed36b 100644 --- a/src/intl/en/page-developers-index.json +++ b/src/intl/en/page-developers-index.json @@ -59,7 +59,7 @@ "page-developers-networks-link": "Networks", "page-developers-node-clients-desc": "How blocks and transactions are verified in the network", "page-developers-node-clients-link": "Nodes and clients", - "page-developers-oracle-desc": "Getting off-chain data into your smart contracts", + "page-developers-oracle-desc": "Getting offchain data into your smart contracts", "page-developers-oracles-link": "Oracles", "page-developers-play-code": "Play with code", "page-developers-read-docs": "Read the docs", diff --git a/src/intl/en/page-layer-2-learn.json b/src/intl/en/page-layer-2-learn.json index 0940906aad4..28c9e5b980b 100644 --- a/src/intl/en/page-layer-2-learn.json +++ b/src/intl/en/page-layer-2-learn.json @@ -37,7 +37,7 @@ "page-layer-2-learn-rollupCards-optimistic-description": "Optimistic rollups use fault proofs where transactions are assumed to be valid, but can be challenged if an invalid transaction is suspected. If an invalid transaction is suspected, a fault proof is ran to see if this has taken place.", "page-layer-2-learn-rollupCards-optimistic-childSentence": "More on optimistic rollups", "page-layer-2-learn-rollupCards-zk-title": "Zero knowledge rollups", - "page-layer-2-learn-rollupCards-zk-description": "Zero Knowledge rollups use validity proofs where transactions calculations are computed off-chain, and then this data is then supplied to Ethereum Mainnet with a proof of their validity.", + "page-layer-2-learn-rollupCards-zk-description": "Zero Knowledge rollups use validity proofs where transactions calculations are computed offchain, and then this data is then supplied to Ethereum Mainnet with a proof of their validity.", "page-layer-2-learn-rollupCards-zk-childSentence": "More on zk-rollups", "page-layer-2-learn-dyor-title": "Do your own research: Risks of layer 2", "page-layer-2-learn-dyor-1": "Because layer 2 chains inherit security from Ethereum, in an ideal world, they are as safe as L1 Ethereum. However, many of the projects are still young and somewhat experimental. After years of R&D, many of the L2 technologies that will scale Ethereum went live in 2021. This is not to say these L2s are not secure, only that no layer 2 is as battle tested as Ethereum Mainnet. Always do your own research and decide if you're comfortable with any risks involved.", diff --git a/src/intl/en/page-roadmap-vision.json b/src/intl/en/page-roadmap-vision.json index a58f789226c..0b8698e1262 100644 --- a/src/intl/en/page-roadmap-vision.json +++ b/src/intl/en/page-roadmap-vision.json @@ -14,7 +14,7 @@ "page-roadmap-vision-problems": "Today's problems", "page-roadmap-vision-scalability": "Scalability", "page-roadmap-vision-scalability-desc": "Ethereum needs to be able to handle more transactions per second without increasing the size of the nodes in the network. Nodes are vital network participants who store and run the blockchain. Increasing node size isn't practical because only those with powerful and expensive computers could do it. To scale, Ethereum needs more transactions per second, coupled with more nodes. More nodes means more security.", - "page-roadmap-vision-scalability-desc-3": "Layer 2 rollups scale Ethereum by moving transactions off-chain and only posting summary data to Ethereum. This batching increases Ethereum's throughput while drastically reducing costs for users.", + "page-roadmap-vision-scalability-desc-3": "Layer 2 rollups scale Ethereum by moving transactions offchain and only posting summary data to Ethereum. This batching increases Ethereum's throughput while drastically reducing costs for users.", "page-roadmap-vision-scalability-desc-4": "Rollups need low-cost storage on layer 1 to make transactions as cheap as possible for users. This will be provided in the form of blobs attached to Ethereum blocks. Eventually, many blobs will be attached to Ethereum blocks, providing cheap storage for many rollups.", "page-roadmap-vision-security": "Security", "page-roadmap-vision-security-desc": "The planned upgrades improve Ethereum's security against coordinated attacks.", diff --git a/src/intl/en/page-staking.json b/src/intl/en/page-staking.json index ed2b6ae241d..6854bbfe4f1 100644 --- a/src/intl/en/page-staking.json +++ b/src/intl/en/page-staking.json @@ -10,7 +10,7 @@ "comp-withdrawal-comparison-new-link": "Visit Staking Launchpad", "comp-withdrawal-credentials-placeholder": "Validator index", "comp-withdrawal-credentials-error": "Oops! Double check validator index number and try again.", - "comp-withdrawal-credentials-upgraded-1": "Validator index {{validatorIndex}} is ready to start receiving rewards!", + "comp-withdrawal-credentials-upgraded-1": "Validator index {validatorIndex} is ready to start receiving rewards!", "comp-withdrawal-credentials-upgraded-2": "Withdrawal credentials linked to execution address:", "comp-withdrawal-credentials-not-upgraded-1": "This validator needs to be upgraded.", "comp-withdrawal-credentials-not-upgraded-1-testnet": "This Holesky testnet validator needs to be upgraded.", diff --git a/src/intl/en/page-upgrades-index.json b/src/intl/en/page-upgrades-index.json index 6c0de035828..d8f087c7243 100644 --- a/src/intl/en/page-upgrades-index.json +++ b/src/intl/en/page-upgrades-index.json @@ -97,7 +97,7 @@ "page-upgrades-question-6-answer-5": "You can also join the discussion on Ethereum research and development at ethresear.ch.", "page-upgrades-question-6-title": "What do I need to do with my dapp?", "page-upgrades-question-6-desc": "The Merge was designed to have minimal impact on dapp developers, though there were a couple of small changes worth noting.", - "page-upgrades-question-6-answer-1": "Dapp developers familiar with pre-merge Ethereum should be aware of some changes. These changes include block structure and timing, a few opcode changes, sources of on-chain randomness and the concept of epoch finalization.", + "page-upgrades-question-6-answer-1": "Dapp developers familiar with pre-merge Ethereum should be aware of some changes. These changes include block structure and timing, a few opcode changes, sources of onchain randomness and the concept of epoch finalization.", "page-upgrades-question-6-answer-1-link": "How The Merge Impacted Ethereum's Application Layer", "page-upgrades-question-6-answer-2": "Applications were almost entirely unaffected.", "page-upgrades-question-7-desc": "Many different teams from all over the community are working on the various Ethereum upgrades.", diff --git a/src/intl/es/glossary-tooltip.json b/src/intl/es/glossary-tooltip.json index 4520386c78b..1e338427134 100644 --- a/src/intl/es/glossary-tooltip.json +++ b/src/intl/es/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Un cliente de software que participa en la red. Más sobre nodos y clientes.", "ommer-term": "Bloque Ommer (tío)", "ommer-definition": "Cuando un minero de prueba de trabajo encuentra un bloque válido, otro minero puede haber publicado un bloque en competencia que se agrega primero a la punta de la cadena de bloques. Este bloque válido, pero estancado, puede ser incluido por bloques más nuevos como ommers y recibir una recompensa de bloque parcial. El término \"ommer\" es el término de género neutral preferido para el hermano de un bloque padre (principal), pero a veces también se lo conoce como \"tío\" (uncle). Esto era común para Ethereum cuando era una red de prueba de trabajo. Ahora que Ethereum utiliza prueba de participación, solo se selecciona un proponente de bloques por ranura.", - "on-chain-term": "En cadena", - "on-chain-definition": "Se refiere a las acciones o transacciones que ocurren en la cadena de bloques y están disponibles públicamente.", + "onchain-term": "En cadena", + "onchain-definition": "Se refiere a las acciones o transacciones que ocurren en la cadena de bloques y están disponibles públicamente.", "optimistic-rollup-term": "Acumulaciones optimistas (Optimistic rollups)", "optimistic-rollup-definition": "Un Rollup Optimista es una solución de Capa 2 que acelera las transacciones en Ethereum, asumiendo que son válidas por defecto, a menos que se las cuestione o ponga en duda. Más información acerca de los Rollups Optimistas.", "peer-to-peer-network-term": "Red entre pares (o peer-to-peer)", diff --git a/src/intl/es/glossary.json b/src/intl/es/glossary.json index 0d47f90f9b6..96021ab51e1 100644 --- a/src/intl/es/glossary.json +++ b/src/intl/es/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Un cliente de software que participa en la red. Más sobre nodos y clientes.", "nonce-term": "Nonce", "nonce-definition": "En criptografía, un valor que solo se puede usar una vez. Un nonce de cuenta es un contador de transacciones en cada cuenta que se utiliza para evitar ataques de repetición.", - "off-chain-term": "Fuera de la cadena", - "off-chain-definition": "Fuera de la cadena significa cualquier transacción o dato que exista fuera de la cadena de bloques. Debido a que la comisión de cada transacción en cadena puede ser costosa e ineficiente, herramientas de terceros, como los oráculos que manejan datos de precios, o las soluciones de capa 2 que tienen un mayor rendimiento de transacciones, manejan gran parte del trabajo de procesamiento fuera de la cadena y envían información a la cadena a intervalos menos frecuentes.", + "offchain-term": "Fuera de la cadena", + "offchain-definition": "Fuera de la cadena significa cualquier transacción o dato que exista fuera de la cadena de bloques. Debido a que la comisión de cada transacción en cadena puede ser costosa e ineficiente, herramientas de terceros, como los oráculos que manejan datos de precios, o las soluciones de capa 2 que tienen un mayor rendimiento de transacciones, manejan gran parte del trabajo de procesamiento fuera de la cadena y envían información a la cadena a intervalos menos frecuentes.", "ommer-term": "Bloque Ommer (tío)", "ommer-definition": "Cuando un minero de prueba de trabajo encuentra un bloque válido, otro minero puede haber publicado un bloque en competencia que se agrega primero a la punta de la cadena de bloques. Este bloque válido, pero estancado, puede ser incluido por bloques más nuevos como ommers y recibir una recompensa de bloque parcial. El término \"ommer\" es el término de género neutral preferido para el hermano de un bloque padre (principal), pero a veces también se lo conoce como \"tío\" (uncle). Esto era común para Ethereum cuando era una red de prueba de trabajo. Ahora que Ethereum utiliza prueba de participación, solo se selecciona un proponente de bloques por ranura.", - "on-chain-term": "En cadena", - "on-chain-definition": "Se refiere a acciones o transacciones que ocurren en la cadena de bloques y que están disponibles públicamente.

Piénselo como escribir algo en un gran cuaderno compartido que todo el mundo puede ver y comprobar, asegurándose de que lo que se escribe (como enviar dinero digital o hacer un contrato) es permanente y no se puede cambiar ni borrar.", + "onchain-term": "En cadena", + "onchain-definition": "Se refiere a acciones o transacciones que ocurren en la cadena de bloques y que están disponibles públicamente.

Piénselo como escribir algo en un gran cuaderno compartido que todo el mundo puede ver y comprobar, asegurándose de que lo que se escribe (como enviar dinero digital o hacer un contrato) es permanente y no se puede cambiar ni borrar.", "optimistic-rollup-term": "Acumulaciones optimistas (Optimistic rollups)", "optimistic-rollup-definition": "Un Rollup Optimista es una solución de Capa 2 que acelera las transacciones en Ethereum, asumiendo que son válidas por defecto, a menos que se las cuestione o ponga en duda. Más información acerca de los Rollups Optimistas.", "oracle-term": "Oráculo", diff --git a/src/intl/fa/glossary-tooltip.json b/src/intl/fa/glossary-tooltip.json index f9e9883dfad..763bea8aac4 100644 --- a/src/intl/fa/glossary-tooltip.json +++ b/src/intl/fa/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "یک کلاینت نرم افزاری که در شبکه شرکت می کند. اطلاعات بیشتر در مورد گره ها و کلاینت ها.", "ommer-term": "بلوک Ommer (عمو)", "ommer-definition": "وقتی یک miner اثبات کار، یک بلوک معتبر پیدا می‌کند، ممکن است معدنچی دیگری منتشر کرده باشد. یک بلوک رقیب که ابتدا به نوک بلاکچین اضافه می شود. این بلوک معتبر، اما قدیمی، می‌تواند توسط بلوک‌های جدیدتر به‌عنوان ommers گنجانده شود و یک پاداش بلوک جزئی دریافت کند. اصطلاح \"ommer\" اصطلاح ترجیحی از نظر جنسیتی خنثی برای خواهر یا برادر بلوک والدین است، اما گاهی اوقات به آن \"عمو\" نیز گفته می شود. زمانی که اتریوم یک شبکه اثبات کار بود، این برای اتریوم رایج بود. اکنون که اتریوم از اثبات سهام استفاده می‌کند، تنها یک پیشنهاد دهنده بلوک در هر اسلات انتخاب می‌شود.", - "on-chain-term": "روی زنجیره", - "on-chain-definition": "به اقدامات یا تراکنش‌هایی اشاره دارد که روی بلاکچین اتفاق می‌افتند و در دسترس عموم هستند.", + "onchain-term": "روی زنجیره", + "onchain-definition": "به اقدامات یا تراکنش‌هایی اشاره دارد که روی بلاکچین اتفاق می‌افتند و در دسترس عموم هستند.", "optimistic-rollup-term": "رول آپ خوش بینانه", "optimistic-rollup-definition": "رول‌آپ خوش‌بینانه یک راه حل لایه 2 است که به تراکنش ها در اتریوم سرعت می بخشد، با این فرض که به طور پیش فرض معتبر هستند مگر اینکه به چالش کشیده شوند. اطلاعات بیشتر در مورد رول‌آپ خوش‌بینانه.", "peer-to-peer-network-term": "شبکه همتا به همتا", diff --git a/src/intl/fa/glossary.json b/src/intl/fa/glossary.json index 9dc86ef8a85..19736afd0f2 100644 --- a/src/intl/fa/glossary.json +++ b/src/intl/fa/glossary.json @@ -257,12 +257,12 @@ "node-definition": "یک کلاینت نرم افزاری که در شبکه شرکت می کند. اطلاعات بیشتر در مورد گره ها و کلاینت ها.", "nonce-term": "Nonce", "nonce-definition": "در مبحث رمزنگاری، مقداری که فقط یک بار قابل استفاده است. نانس یک حساب یک شمارنده تراکنش در هر حساب است که برای جلوگیری از حملات مجدد استفاده می شود.", - "off-chain-term": "برون‌زنجیره‌ای", - "off-chain-definition": "برون‌زنجیره ای یا آف‌چین به معنای هر تراکنش یا داده‌ای است که خارج از بلاکچین وجود دارد. از آنجایی که انجام هر تراکنش در زنجیره می تواند گران و ناکارآمد باشد، ابزارهای شخص ثالث مانند اوراکل ها که داده های قیمت گذاری را مدیریت می کنند، یا راهکارهای لایه2 که توان عملیاتی بالاتری از تراکنش‌ها را انجام می‌دهند، بخش عمده‌ای از کارهای پردازشی را خارج از زنجیره انجام می‌دهند و اطلاعات آنچین را در فواصل زمانی کمتر ارسال می‌کنند.", + "offchain-term": "برون‌زنجیره‌ای", + "offchain-definition": "برون‌زنجیره ای یا آف‌چین به معنای هر تراکنش یا داده‌ای است که خارج از بلاکچین وجود دارد. از آنجایی که انجام هر تراکنش در زنجیره می تواند گران و ناکارآمد باشد، ابزارهای شخص ثالث مانند اوراکل ها که داده های قیمت گذاری را مدیریت می کنند، یا راهکارهای لایه2 که توان عملیاتی بالاتری از تراکنش‌ها را انجام می‌دهند، بخش عمده‌ای از کارهای پردازشی را خارج از زنجیره انجام می‌دهند و اطلاعات آنچین را در فواصل زمانی کمتر ارسال می‌کنند.", "ommer-term": "بلوک Ommer (عمو)", "ommer-definition": "وقتی یک miner اثبات کار، یک بلوک معتبر پیدا می‌کند، ممکن است معدنچی دیگری منتشر کرده باشد. یک بلوک رقیب که ابتدا به نوک بلاکچین اضافه می شود. این بلوک معتبر، اما قدیمی، می‌تواند توسط بلوک‌های جدیدتر به‌عنوان ommers گنجانده شود و یک پاداش بلوک جزئی دریافت کند. اصطلاح \"ommer\" اصطلاح ترجیحی از نظر جنسیتی خنثی برای خواهر یا برادر بلوک والدین است، اما گاهی اوقات به آن \"عمو\" نیز گفته می شود. زمانی که اتریوم یک شبکه اثبات کار بود، این برای اتریوم رایج بود. اکنون که اتریوم از اثبات سهام استفاده می‌کند، تنها یک پیشنهاد دهنده بلوک در هر اسلات انتخاب می‌شود.", - "on-chain-term": "آنچین", - "on-chain-definition": "به اقدامات یا تراکنش‌هایی اشاره دارد که روی بلاک چین اتفاق می‌افتند و به صورت عمومی در دسترس هستند.

فکر کنید چیزی در یک دفترچه یادداشت مشترک و بزرگ می‌نویسید که همه می‌توانند ببینند و بررسی کنند، و مطمئن شوید که هر چیزی نوشته شده است (مانند ارسال پول دیجیتال یا بستن قرارداد) دائمی است و قابل تغییر یا پاک کردن نیست.", + "onchain-term": "آنچین", + "onchain-definition": "به اقدامات یا تراکنش‌هایی اشاره دارد که روی بلاک چین اتفاق می‌افتند و به صورت عمومی در دسترس هستند.

فکر کنید چیزی در یک دفترچه یادداشت مشترک و بزرگ می‌نویسید که همه می‌توانند ببینند و بررسی کنند، و مطمئن شوید که هر چیزی نوشته شده است (مانند ارسال پول دیجیتال یا بستن قرارداد) دائمی است و قابل تغییر یا پاک کردن نیست.", "optimistic-rollup-term": "رول آپ خوش بینانه", "optimistic-rollup-definition": "رول‌آپ خوش‌بینانه یک راه حل لایه 2 است که به تراکنش ها در اتریوم سرعت می بخشد، با این فرض که به طور پیش فرض معتبر هستند مگر اینکه به چالش کشیده شوند. اطلاعات بیشتر در مورد رول‌آپ خوش‌بینانه.", "oracle-term": "اوراکل", diff --git a/src/intl/fr/glossary-tooltip.json b/src/intl/fr/glossary-tooltip.json index 97a20387b15..4e62f394913 100644 --- a/src/intl/fr/glossary-tooltip.json +++ b/src/intl/fr/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Un client logiciel qui participe au réseau. En savoir plus sur les nœuds et les clients.", "ommer-term": "Bloc oncle (ommer)", "ommer-definition": "Lorsqu'un mineur en preuve de travail trouve un bloc valide, un autre mineur peut avoir publié un bloc concurrent qui est ajouté en premier à l'extrémité de la blockchain. Ce bloc valide, mais périmé, peut être inclus par des blocs plus récents en tant qu'ommers et recevoir une récompense de bloc partielle. Le terme « ommer » est le terme de genre neutre préféré pour désigner le frère ou la sœur d'un bloc parent, mais il est parfois également appelé « oncle ». Cela était frequent pour Ethereum lorsqu'il s'agissait d'un réseau basé sur la preuve de travail. Maintenant qu'Ethereum utilise la preuve d'enjeu, un seul proposeur de bloc est sélectionné par créneau.", - "on-chain-term": "En chaîne", - "on-chain-definition": "Fait référence aux actions ou transactions qui se produisent sur la blockchain et qui sont accessibles au public.", + "onchain-term": "En chaîne", + "onchain-definition": "Fait référence aux actions ou transactions qui se produisent sur la blockchain et qui sont accessibles au public.", "optimistic-rollup-term": "Rollup optimisé", "optimistic-rollup-definition": "Le rollup optimiste est une solution de couche 2 qui accélère les transactions sur Ethereum, en supposant qu’elles soient valides par défaut, sauf si elles sont contestées. En savoir plus sur les rollups optimistes.", "peer-to-peer-network-term": "Réseaux Pair-à-Pair", diff --git a/src/intl/fr/glossary.json b/src/intl/fr/glossary.json index afa87855cc4..4ab4fb9e3b8 100644 --- a/src/intl/fr/glossary.json +++ b/src/intl/fr/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Un client logiciel qui participe au réseau. En savoir plus sur les nœuds et les clients.", "nonce-term": "Nonce", "nonce-definition": "En cryptographie, une valeur qui ne peut être utilisée qu'une seule fois. Un nonce de compte est un compteur de transactions dans chaque compte, qui est utilisé pour empêcher les attaques par rejeu.", - "off-chain-term": "Hors-chaine", - "off-chain-definition": "Hors-chaine se réfère à toute transaction ou donnée qui existe en dehors de la blockchain. Parce que la validation de chaque transaction sur la chaîne peut être coûteuse et inefficace, des outils tiers tels que des oracles qui gèrent les données de tarification, ou des solutions de couche 2 qui exécutent un débit de transactions plus élevé, gèrent une grande partie du travail de traitement hors chaîne et présentera des renseignements sur la chaîne à des intervalles moins fréquents.", + "offchain-term": "Hors-chaine", + "offchain-definition": "Hors-chaine se réfère à toute transaction ou donnée qui existe en dehors de la blockchain. Parce que la validation de chaque transaction sur la chaîne peut être coûteuse et inefficace, des outils tiers tels que des oracles qui gèrent les données de tarification, ou des solutions de couche 2 qui exécutent un débit de transactions plus élevé, gèrent une grande partie du travail de traitement hors chaîne et présentera des renseignements sur la chaîne à des intervalles moins fréquents.", "ommer-term": "Bloc oncle (ommer)", "ommer-definition": "Lorsqu'un mineur en preuve de travail trouve un bloc valide, un autre mineur peut avoir publié un bloc concurrent qui est ajouté en premier à l'extrémité de la blockchain. Ce bloc valide, mais périmé, peut être inclus par des blocs plus récents en tant qu'ommers et recevoir une récompense de bloc partielle. Le terme « ommer » est le terme de genre neutre préféré pour désigner le frère ou la sœur d'un bloc parent, mais il est parfois également appelé « oncle ». Cela était frequent pour Ethereum lorsqu'il s'agissait d'un réseau basé sur la preuve de travail. Maintenant qu'Ethereum utilise la preuve d'enjeu, un seul proposeur de bloc est sélectionné par créneau.", - "on-chain-term": "Sur la chaîne", - "on-chain-definition": "Fait référence aux actions ou transactions qui se produisent sur la blockchain et sont accessibles au public.

Voyez cela comme le fait d'écrire quelque chose dans un carnet partagé que tout le monde peut voir et vérifier, en vous assurant que tout ce qui est écrit (comme envoyer de l’argent numérique ou conclure un contrat) est permanent et ne peut pas être modifié ou effacé.", + "onchain-term": "Sur la chaîne", + "onchain-definition": "Fait référence aux actions ou transactions qui se produisent sur la blockchain et sont accessibles au public.

Voyez cela comme le fait d'écrire quelque chose dans un carnet partagé que tout le monde peut voir et vérifier, en vous assurant que tout ce qui est écrit (comme envoyer de l’argent numérique ou conclure un contrat) est permanent et ne peut pas être modifié ou effacé.", "optimistic-rollup-term": "Rollup optimisé", "optimistic-rollup-definition": "Le rollup optimiste est une solution de couche 2 qui accélère les transactions sur Ethereum, en supposant qu’elles soient valides par défaut, sauf si elles sont contestées. En savoir plus sur les rollups optimistes.", "oracle-term": "Oracle", diff --git a/src/intl/hu/glossary-tooltip.json b/src/intl/hu/glossary-tooltip.json index 374751649b7..5a06ed53fd8 100644 --- a/src/intl/hu/glossary-tooltip.json +++ b/src/intl/hu/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Egy szoftverkliens, mely részt vesz a hálózatban. Bővebben a csomópontokról és a kliensekről.", "ommer-term": "Ommer (nagybácsi) blokk", "ommer-definition": "Amikor egy proof-of-work (munkaigazolás) mechanizmus bányásza talált egy érvényes blokkot, egy másik bányász talán beküldött egy ezzel versenyző blokkot, amelyet először tettek hozzá a blokklánc elejéhez. Ez az érvényes, de elévült blokk bekerülhet az újabb blokkokba ommer-ként (a szülőblokk testvére) és részleges blokkjutalmat lehet érte kapni. Ez a kifejezés a semleges megfogalmazása a szülőblokk testvérére vonatkozóan, de néha nagybácsinak (uncle) is nevezik. Ez általános volt az Ethereum esetében, amikor még proof-of-work-alapú hálózat volt. Most, hogy az Ethereum proof-of-stake alapra váltott, helyenként csak egy blokkjavaslat van kiválasztva.", - "on-chain-term": "Láncon belüli", - "on-chain-definition": "Olyan műveletekre vagy tranzakciókra utal, amelyek a blokkláncon történnek és nyilvánosan elérhetőek.", + "onchain-term": "Láncon belüli", + "onchain-definition": "Olyan műveletekre vagy tranzakciókra utal, amelyek a blokkláncon történnek és nyilvánosan elérhetőek.", "optimistic-rollup-term": "Optimista típusú összevont tranzakciók", "optimistic-rollup-definition": "Az optimista összesítés egy 2. rétegű megoldás, amely felgyorsítja a tranzakciókat az Ethereumon, azt feltételezve, hogy alapértelmezés szerint érvényesek, hacsak nem támadják meg őket. További információk az optimista összesítésekről.", "peer-to-peer-network-term": "Közvetítőmentes (peer-to-peer) hálózat", diff --git a/src/intl/hu/glossary.json b/src/intl/hu/glossary.json index ff35482c0bb..1a2db299bb4 100644 --- a/src/intl/hu/glossary.json +++ b/src/intl/hu/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Egy szoftverkliens, mely részt vesz a hálózatban. Bővebben a csomópontokról és a kliensekről.", "nonce-term": "Nonce", "nonce-definition": "A kriptográfiában egy olyan érték, melyet acsak egyszer lehet használni. Egy számla nonce az egy tranzakciószámláló minden számlánál, amellyel meg lehet akadályozni az újrajátszási támadásokat.", - "off-chain-term": "Láncon kívüli", - "off-chain-definition": "A láncon kívüli olyan tranzakcióra vagy adatra vonatkozik, amely a blokkláncon kívül létezik. Mivel minden tranzakció lácon belüli kezelése költséges és nem feltétlen hatékony, a harmadik féltől származó eszközök, például az áradatokat szolgáltató oracle-ök, vagy a nagyobb tranzakcióátvitelre képes második blokkláncrétegbeli (L2) megoldások a feldolgozás nagy részét a blokkláncon kívül végzik, és ritkábban küldik be az információkat a blokkláncra.", + "offchain-term": "Láncon kívüli", + "offchain-definition": "A láncon kívüli olyan tranzakcióra vagy adatra vonatkozik, amely a blokkláncon kívül létezik. Mivel minden tranzakció lácon belüli kezelése költséges és nem feltétlen hatékony, a harmadik féltől származó eszközök, például az áradatokat szolgáltató oracle-ök, vagy a nagyobb tranzakcióátvitelre képes második blokkláncrétegbeli (L2) megoldások a feldolgozás nagy részét a blokkláncon kívül végzik, és ritkábban küldik be az információkat a blokkláncra.", "ommer-term": "Ommer (nagybácsi) blokk", "ommer-definition": "Amikor egy proof-of-work (munkaigazolás) mechanizmus bányásza talált egy érvényes blokkot, egy másik bányász talán beküldött egy ezzel versenyző blokkot, amelyet először tettek hozzá a blokklánc elejéhez. Ez az érvényes, de elévült blokk bekerülhet az újabb blokkokba ommer-ként (a szülőblokk testvére) és részleges blokkjutalmat lehet érte kapni. Ez a kifejezés a semleges megfogalmazása a szülőblokk testvérére vonatkozóan, de néha nagybácsinak (uncle) is nevezik. Ez általános volt az Ethereum esetében, amikor még proof-of-work-alapú hálózat volt. Most, hogy az Ethereum proof-of-stake alapra váltott, helyenként csak egy blokkjavaslat van kiválasztva.", - "on-chain-term": "Láncon belüli", - "on-chain-definition": "A láncon belüli olyan műveletekre vagy tranzakciókra utal, amelyek a blokkláncon történnek, és nyilvánosan elérhetőek.

Gondoljon rá úgy, mintha egy nagy, közös jegyzetfüzetbe írna valamit, amit mindenki láthat és ellenőrizhet, ezel biztosítva, hogy Ön bármit is ír (például digitális pénzt küld vagy szerződést köt), az végleges legyen, és ne lehessen megváltoztatni vagy törölni.", + "onchain-term": "Láncon belüli", + "onchain-definition": "A láncon belüli olyan műveletekre vagy tranzakciókra utal, amelyek a blokkláncon történnek, és nyilvánosan elérhetőek.

Gondoljon rá úgy, mintha egy nagy, közös jegyzetfüzetbe írna valamit, amit mindenki láthat és ellenőrizhet, ezel biztosítva, hogy Ön bármit is ír (például digitális pénzt küld vagy szerződést köt), az végleges legyen, és ne lehessen megváltoztatni vagy törölni.", "optimistic-rollup-term": "Optimista típusú összevont tranzakciók", "optimistic-rollup-definition": "Az optimista összesítés egy 2. rétegű megoldás, amely felgyorsítja a tranzakciókat az Ethereumon, azt feltételezve, hogy alapértelmezés szerint érvényesek, hacsak nem támadják meg őket. További információk az optimista összesítésekről.", "oracle-term": "Orákulum", diff --git a/src/intl/it/glossary-tooltip.json b/src/intl/it/glossary-tooltip.json index 3a7f6565a3b..9e4149089ca 100644 --- a/src/intl/it/glossary-tooltip.json +++ b/src/intl/it/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Un client software che partecipa alla rete. Maggiori informazioni sui nodi e i client.", "ommer-term": "Blocco ommer (zio)", "ommer-definition": "Quando un miner di proof-of-work trova un blocco valido, un altro miner potrebbe aver pubblicato un blocco concorrente che viene aggiunto prima alla testa della catena. Questo blocco valido, ma obsoleto, può essere incluso in blocchi più recenti come ommer e ricevere una ricompensa parziale del blocco. Il termine \"ommer\" è il termine preferito, neutro dal punto di vista di genere, per lo stesso livello di un blocco genitore, ma talvolta è anche indicato come \"zio\". Questo era comune per Ethereum quando era una rete di proof-of-work. Ora che Ethereum utilizza il proof-of-stake, viene selezionato soltanto un propositore del blocco per slot.", - "on-chain-term": "Sulla catena", - "on-chain-definition": "Si riferisce alle azioni o transazioni che si verificano sulla blockchain e sono disponibili pubblicamente.", + "onchain-term": "Sulla catena", + "onchain-definition": "Si riferisce alle azioni o transazioni che si verificano sulla blockchain e sono disponibili pubblicamente.", "optimistic-rollup-term": "Optimistic rollup", "optimistic-rollup-definition": "Un rollup ottimistico è una soluzione del Livello 2 che velocizza le transazioni su Ethereum, supponendo che siano valide di default se non contestate. Maggiori informazioni sui rollup ottimistici.", "peer-to-peer-network-term": "Rete peer-to-peer", diff --git a/src/intl/it/glossary.json b/src/intl/it/glossary.json index 33d3cfc36fa..138a5ccc6eb 100644 --- a/src/intl/it/glossary.json +++ b/src/intl/it/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Un client software che partecipa alla rete. Maggiori informazioni sui nodi e i client.", "nonce-term": "Nonce", "nonce-definition": "In crittografia, un valore utilizzabile una sola volta. Il nonce di un conto è un contatore di transazioni in ogni conto, utilizzato per impedire gli attacchi di riproduzione.", - "off-chain-term": "Esterno alla catena", - "off-chain-definition": "Esterno alla catena si riferisce a qualsiasi transazione o dato che esiste al di fuori della blockchain. Poiché effettuare il commit di ogni transazione su catena può essere costoso e inefficiente, strumenti di terze parti come gli oracoli che gestiscono i dati sui prezzi, o le soluzioni di livello 2 che eseguono un volume maggiore di transazioni, gestiscono molto del lavoro di elaborazione all'esterno della catena, e invieranno le informazioni sulla catena a intervalli meno frequenti.", + "offchain-term": "Esterno alla catena", + "offchain-definition": "Esterno alla catena si riferisce a qualsiasi transazione o dato che esiste al di fuori della blockchain. Poiché effettuare il commit di ogni transazione su catena può essere costoso e inefficiente, strumenti di terze parti come gli oracoli che gestiscono i dati sui prezzi, o le soluzioni di livello 2 che eseguono un volume maggiore di transazioni, gestiscono molto del lavoro di elaborazione all'esterno della catena, e invieranno le informazioni sulla catena a intervalli meno frequenti.", "ommer-term": "Blocco ommer (zio)", "ommer-definition": "Quando un miner di proof-of-work trova un blocco valido, un altro miner potrebbe aver pubblicato un blocco concorrente che viene aggiunto prima alla testa della catena. Questo blocco valido, ma obsoleto, può essere incluso in blocchi più recenti come ommer e ricevere una ricompensa parziale del blocco. Il termine \"ommer\" è il termine preferito, neutro dal punto di vista di genere, per lo stesso livello di un blocco genitore, ma talvolta è anche indicato come \"zio\". Questo era comune per Ethereum quando era una rete di proof-of-work. Ora che Ethereum utilizza il proof-of-stake, viene selezionato soltanto un propositore del blocco per slot.", - "on-chain-term": "Sulla catena", - "on-chain-definition": "Si riferisce alle azioni o transazioni che si verificano sulla blockchain e sono disponibili pubblicamente.

Immaginalo come scrivere qualcosa su un grande taccuino condiviso che tutti possono leggere e controllare, assicurandosi che qualsiasi cosa sia stata scritta (come inviare moneta digitale o stipulare un contratto) sia permanente e non possa essere modificata o cancellata.", + "onchain-term": "Sulla catena", + "onchain-definition": "Si riferisce alle azioni o transazioni che si verificano sulla blockchain e sono disponibili pubblicamente.

Immaginalo come scrivere qualcosa su un grande taccuino condiviso che tutti possono leggere e controllare, assicurandosi che qualsiasi cosa sia stata scritta (come inviare moneta digitale o stipulare un contratto) sia permanente e non possa essere modificata o cancellata.", "optimistic-rollup-term": "Optimistic rollup", "optimistic-rollup-definition": "Un rollup ottimistico è una soluzione del Livello 2 che velocizza le transazioni su Ethereum, supponendo che siano valide di default se non contestate. Maggiori informazioni sui rollup ottimistici.", "oracle-term": "Oracolo", diff --git a/src/intl/ja/glossary-tooltip.json b/src/intl/ja/glossary-tooltip.json index 2bb4066a87d..73f0353afd7 100644 --- a/src/intl/ja/glossary-tooltip.json +++ b/src/intl/ja/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "ネットワークに参加するソフトウェアクライアント。詳細は、ノードとクライアントをご覧ください。", "ommer-term": "オマー(アンクル)ブロック", "ommer-definition": "プルーフ・オブ・ワークのマイナーが有効なブロックを見つけた時に、別のマイナーが先に、ブロックチェーンの先端に競合しているブロックを公開している場合があります。この有効ではあるが、古いブロックはオマーとして新しいブロックに含むことができ、ブロック報酬の一部を受け取ることができます。「オマー」という用語は、親ブロックの兄弟を表す性別に依存しない用語として好まれます。時には、「アンクル」と呼ばれることもあります。 イーサリアムが プルーフ・オブ・ワーク ネットワークだった頃にこの呼び名が一般的でした。現在、イーサリアムは プルーフ・オブ・ステーク を使用するため、スロットごとに1つのブロック提案者のみが選択されます。", - "on-chain-term": "オンチェーン", - "on-chain-definition": "ブロックチェーン上で行われたアクションやトランザクションを意味し、公開され参照可能であることです。", + "onchain-term": "オンチェーン", + "onchain-definition": "ブロックチェーン上で行われたアクションやトランザクションを意味し、公開され参照可能であることです。", "optimistic-rollup-term": "オプティミスティック・ロールアップ", "optimistic-rollup-definition": "オプティミスティック・ロールアップは、レイヤー2ソリューションでイーサリアムのトランザクションの速度を上げます。トランザクションは、異議申し立てが行われない限り、デフォルトでは有効であると仮定されます。詳細はオプティミスティック・ロールアップをご覧ください。", "peer-to-peer-network-term": "ピアツーピアネットワーク", diff --git a/src/intl/ja/glossary.json b/src/intl/ja/glossary.json index 9ccec6e1ab9..67e8e1e04c4 100644 --- a/src/intl/ja/glossary.json +++ b/src/intl/ja/glossary.json @@ -257,12 +257,12 @@ "node-definition": "ネットワークに参加するソフトウェアクライアント。詳細は、ノードとクライアントをご覧ください。", "nonce-term": "ノンス", "nonce-definition": "暗号技術において、ただ一度だけ使える値。アカウントノンスは、各アカウントのトランザクションのカウンターで、リプレイ攻撃を防ぐために使用されます。", - "off-chain-term": "オフチェーン", - "off-chain-definition": "オフチェーンは、トランザクションまたはデータがブロックチェーンの外にあることを指します。すべてのトランザクションをオンチェーンでコミットするのは高額で非効率な場合があるため、価格データを扱うオラクルのようなサードパーティーツールや、より高いスループットを実行するレイヤー2ソリューションがオフチェーンで大量の計算を扱い、少ない頻度で情報をオンチェーンに送信します。", + "offchain-term": "オフチェーン", + "offchain-definition": "オフチェーンは、トランザクションまたはデータがブロックチェーンの外にあることを指します。すべてのトランザクションをオンチェーンでコミットするのは高額で非効率な場合があるため、価格データを扱うオラクルのようなサードパーティーツールや、より高いスループットを実行するレイヤー2ソリューションがオフチェーンで大量の計算を扱い、少ない頻度で情報をオンチェーンに送信します。", "ommer-term": "オマー(アンクル)ブロック", "ommer-definition": "プルーフ・オブ・ワークのマイナーが有効なブロックを見つけた時に、別のマイナーが先に、ブロックチェーンの先端に競合しているブロックを公開している場合があります。この有効ではあるが、古いブロックはオマーとして新しいブロックに含むことができ、ブロック報酬の一部を受け取ることができます。「オマー」という用語は、親ブロックの兄弟を表す性別に依存しない用語として好まれます。時には、「アンクル」と呼ばれることもあります。 イーサリアムが プルーフ・オブ・ワーク ネットワークだった頃にこの呼び名が一般的でした。現在、イーサリアムは プルーフ・オブ・ステーク を使用するため、スロットごとに1つのブロック提案者のみが選択されます。", - "on-chain-term": "オンチェーン", - "on-chain-definition": "ブロックチェーンで発生した公開されているアクションやトランザクションを指します。

誰もが閲覧してチェックできる、共有の大きなノートブックに何かを書くことを想像してみてください。これにより、書かれたもの(デジタルマネーの送信やコントラクトの作成など)が何であれ、永続的で変更または消去できないことが確実になります。", + "onchain-term": "オンチェーン", + "onchain-definition": "ブロックチェーンで発生した公開されているアクションやトランザクションを指します。

誰もが閲覧してチェックできる、共有の大きなノートブックに何かを書くことを想像してみてください。これにより、書かれたもの(デジタルマネーの送信やコントラクトの作成など)が何であれ、永続的で変更または消去できないことが確実になります。", "optimistic-rollup-term": "オプティミスティック・ロールアップ", "optimistic-rollup-definition": "オプティミスティック・ロールアップは、レイヤー2ソリューションでイーサリアムのトランザクションの速度を上げます。トランザクションは、異議申し立てが行われない限り、デフォルトでは有効であると仮定されます。詳細はオプティミスティック・ロールアップをご覧ください。", "oracle-term": "オラクル", diff --git a/src/intl/pt-br/glossary-tooltip.json b/src/intl/pt-br/glossary-tooltip.json index 160ab70524c..cd5df921f60 100644 --- a/src/intl/pt-br/glossary-tooltip.json +++ b/src/intl/pt-br/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Um cliente de software que participa da rede. Mais sobre nós e clientes.", "ommer-term": "Bloco ommer (tio)", "ommer-definition": "Quando um minerador de prova de trabalho encontra um bloco válido, outro minerador pode ter publicado um bloco concorrente que é adicionado à ponta da blockchain primeiro. Este bloco válido, mas obsoleto, pode ser incluído por blocos mais novos como ommers e receber uma recompensa de bloco parcial. O termo \"ommer\" é o termo neutro de gênero preferido para o irmão de um bloco pai, mas às vezes também é chamado de \"tio\". Isso era comum para o Ethereum quando era uma rede de prova de trabalho. Agora que o Ethereum usa prova de participação, apenas um proponente de bloco é selecionado por slot.", - "on-chain-term": "On-chain", - "on-chain-definition": "Refere-se a ações ou transações que ocorrem na blockchain e estão disponíveis publicamente.", + "onchain-term": "On-chain", + "onchain-definition": "Refere-se a ações ou transações que ocorrem na blockchain e estão disponíveis publicamente.", "optimistic-rollup-term": "Acúmulo otimista", "optimistic-rollup-definition": "O Optimistic Rollup é uma solução de Camada 2 que acelera as transações no Ethereum, assumindo que elas são válidas por padrão, a menos que sejam contestadas. Mais sobre Optimistic rollups.", "peer-to-peer-network-term": "Rede ponto a ponto", diff --git a/src/intl/pt-br/glossary.json b/src/intl/pt-br/glossary.json index 803b6b332f7..ed748e25622 100644 --- a/src/intl/pt-br/glossary.json +++ b/src/intl/pt-br/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Um cliente de software que participa da rede. Mais sobre nós e clientes.", "nonce-term": "Nonce", "nonce-definition": "Em criptografia, um valor que só pode ser usado uma vez. Um nonce de conta é um contador de transações em cada conta, que é usado para evitar ataques de repetição.", - "off-chain-term": "Off-Chain", - "off-chain-definition": "Off-chain significa qualquer transação ou dado que exista fora da blockchain. Como o comprometimento de cada transação na cadeia pode ser caro e ineficiente, ferramentas de terceiros, como oráculos que lidam com dados de preços, ou soluções de camada 2 que executam um maior volume de transações, lidam com a maior parte do trabalho de processamento fora da cadeia e enviam informações para a cadeia em intervalos menos frequentes.", + "offchain-term": "Off-Chain", + "offchain-definition": "Off-chain significa qualquer transação ou dado que exista fora da blockchain. Como o comprometimento de cada transação na cadeia pode ser caro e ineficiente, ferramentas de terceiros, como oráculos que lidam com dados de preços, ou soluções de camada 2 que executam um maior volume de transações, lidam com a maior parte do trabalho de processamento fora da cadeia e enviam informações para a cadeia em intervalos menos frequentes.", "ommer-term": "Bloco ommer (tio)", "ommer-definition": "Quando um minerador de prova de trabalho encontra um bloco válido, outro minerador pode ter publicado um bloco concorrente que é adicionado à ponta da blockchain primeiro. Este bloco válido, mas obsoleto, pode ser incluído por blocos mais novos como ommers e receber uma recompensa de bloco parcial. O termo \"ommer\" é o termo neutro de gênero preferido para o irmão de um bloco pai, mas às vezes também é chamado de \"tio\". Isso era comum para o Ethereum quando era uma rede de prova de trabalho. Agora que o Ethereum usa prova de participação, apenas um proponente de bloco é selecionado por slot.", - "on-chain-term": "On-Chain", - "on-chain-definition": "Refere-se a ações ou transações que ocorrem no blockchain e estão disponíveis publicamente.

Pense nisso como se estivesse escrevendo algo em um caderno grande e compartilhado que todos podem ver e verificar, certificando-se de que tudo o que está escrito (como enviar dinheiro digital ou fazer um contrato) é permanente e não pode ser alterado ou apagado.", + "onchain-term": "On-Chain", + "onchain-definition": "Refere-se a ações ou transações que ocorrem no blockchain e estão disponíveis publicamente.

Pense nisso como se estivesse escrevendo algo em um caderno grande e compartilhado que todos podem ver e verificar, certificando-se de que tudo o que está escrito (como enviar dinheiro digital ou fazer um contrato) é permanente e não pode ser alterado ou apagado.", "optimistic-rollup-term": "Acúmulo otimista", "optimistic-rollup-definition": "O Optimistic Rollup é uma solução de Camada 2 que acelera as transações no Ethereum, assumindo que elas são válidas por padrão, a menos que sejam contestadas. Mais sobre Optimistic rollups.", "oracle-term": "Oráculo", diff --git a/src/intl/tr/glossary-tooltip.json b/src/intl/tr/glossary-tooltip.json index 5a06e815ecb..64dff2f6641 100644 --- a/src/intl/tr/glossary-tooltip.json +++ b/src/intl/tr/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "Ağa katılan bir yazılım istemcisidir. Düğümler ve istemciler hakkında daha fazla bilgi.", "ommer-term": "Ommer (amca) bloğu", "ommer-definition": "Bir iş ispatı madencisi geçerli bir blok bulduğunda, başka bir madenci ondan önce blokzincirin ucuna eklenen rakip bir blok yayınlamış olabilir. Bu geçerli ancak eski blok, ommer olarak daha yeni bloklara dahil edilebilir ve kısmi bir blok ödülü alabilir. \"Ommer\" terimi, bir ebeveyn bloğunun kardeşi için tercih edilen cinsiyet ayrımı gözetmeyen bir terimdir ancak buna bazen \"amca\" da denir. Bu, bir iş ispatı ağıyken Ethereum için yaygındı. Ethereum artık hisse ispatı kullandığından, yuva başına yalnızca bir blok önerici seçilir.", - "on-chain-term": "Zincir üstünde", - "on-chain-definition": "Blokzincir üstünde gerçekleşen ve herkese açık olan eylemleri veya işlemleri ifade eder.", + "onchain-term": "Zincir üstünde", + "onchain-definition": "Blokzincir üstünde gerçekleşen ve herkese açık olan eylemleri veya işlemleri ifade eder.", "optimistic-rollup-term": "İyimser toplama", "optimistic-rollup-definition": "İyimser Toplama, Ethereum üzerindeki işlemlerin itiraz edilmediği sürece varsayılan olarak doğru olduğunu kabul eden ve onları hızlandıran bir Katman 2 çözümüdür. İyimser toplamalar hakkında daha fazla bilgi.", "peer-to-peer-network-term": "Eşler arası ağ", diff --git a/src/intl/tr/glossary.json b/src/intl/tr/glossary.json index ea6cccef22a..498d719972f 100644 --- a/src/intl/tr/glossary.json +++ b/src/intl/tr/glossary.json @@ -257,12 +257,12 @@ "node-definition": "Ağa katılan bir yazılım istemcisidir. Düğümler ve istemciler hakkında daha fazla bilgi.", "nonce-term": "Nonce", "nonce-definition": "Kriptografide, yalnızca bir kez kullanılabilen bir değerdir. Hesap nonce'ı, tekrar saldırılarını önlemek için her hesapta kullanılan bir işlem sayacıdır.", - "off-chain-term": "Zincir Dışında", - "off-chain-definition": "Zincir dışında, blokzincirin dışında var olan herhangi bir işlem veya veri anlamına gelir. Her işlemi zincir üstünde gerçekleştirmek pahalı ve verimsiz olabileceğinden, fiyatlandırma verilerini işleyen kâhinler veya daha yüksek işlem hacmi yürüten katman 2 çözümleri gibi üçüncü taraf araçlar, işleme işinin büyük bir kısmını zincir dışında gerçekleştirir ve zincir üstünde daha az sıklıkta bilgi gönderir.", + "offchain-term": "Zincir Dışında", + "offchain-definition": "Zincir dışında, blokzincirin dışında var olan herhangi bir işlem veya veri anlamına gelir. Her işlemi zincir üstünde gerçekleştirmek pahalı ve verimsiz olabileceğinden, fiyatlandırma verilerini işleyen kâhinler veya daha yüksek işlem hacmi yürüten katman 2 çözümleri gibi üçüncü taraf araçlar, işleme işinin büyük bir kısmını zincir dışında gerçekleştirir ve zincir üstünde daha az sıklıkta bilgi gönderir.", "ommer-term": "Ommer (amca) bloğu", "ommer-definition": "Bir iş ispatı madencisi geçerli bir blok bulduğunda, başka bir madenci ondan önce blokzincirin ucuna eklenen rakip bir blok yayınlamış olabilir. Bu geçerli ancak eski blok, ommer olarak daha yeni bloklara dahil edilebilir ve kısmi bir blok ödülü alabilir. \"Ommer\" terimi, bir ebeveyn bloğunun kardeşi için tercih edilen cinsiyet ayrımı gözetmeyen bir terimdir ancak buna bazen \"amca\" da denir. Bu, bir iş ispatı ağıyken Ethereum için yaygındı. Ethereum artık hisse ispatı kullandığından, yuva başına yalnızca bir blok önerici seçilir.", - "on-chain-term": "Zincir Üstünde", - "on-chain-definition": "Blokzincirde gerçekleşen ve halka açık olan eylem veya işlemleri ifade eder.

Bunu, herkesin görebileceği ve kontrol edebileceği büyük, paylaşılan bir not defterine bir şeyler yazmak gibi düşünün. Yazılanların (örneğin dijital para göndermek veya sözleşme yapmak) hem kalıcı hem de değiştirilemez veya silinemez olmasını sağlayın.", + "onchain-term": "Zincir Üstünde", + "onchain-definition": "Blokzincirde gerçekleşen ve halka açık olan eylem veya işlemleri ifade eder.

Bunu, herkesin görebileceği ve kontrol edebileceği büyük, paylaşılan bir not defterine bir şeyler yazmak gibi düşünün. Yazılanların (örneğin dijital para göndermek veya sözleşme yapmak) hem kalıcı hem de değiştirilemez veya silinemez olmasını sağlayın.", "optimistic-rollup-term": "İyimser toplama", "optimistic-rollup-definition": "İyimser Toplama, Ethereum üzerindeki işlemlerin itiraz edilmediği sürece varsayılan olarak doğru olduğunu kabul eden ve onları hızlandıran bir Katman 2 çözümüdür. İyimser toplamalar hakkında daha fazla bilgi.", "oracle-term": "Kâhin", diff --git a/src/intl/zh-tw/glossary-tooltip.json b/src/intl/zh-tw/glossary-tooltip.json index e4ea8072f97..5ff8f15e3f1 100644 --- a/src/intl/zh-tw/glossary-tooltip.json +++ b/src/intl/zh-tw/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "參與網路的軟體用戶端。更多關於節點和用戶端的資訊。", "ommer-term": "Ommer(叔)區塊", "ommer-definition": "當工作量證明礦工發現有效的區塊時,另一個礦工可能已經發布了首先新增到區塊鏈頂端的競爭區塊。這個有效但過時的區塊可以作為 ommer 被新區塊包含,並獲得部分區塊獎勵。術語「ommer」是對父塊的兄弟姐妹區塊的首選中性術語,但有時也被稱為「叔」。當以太坊仍是工作證明網路時,這對於以太坊來說很常見。現在以太坊使用權益證明,每個時隙只會選擇一個區塊提議者。", - "on-chain-term": "鏈上", - "on-chain-definition": "指在區塊鏈上發生且公開的操作或交易。", + "onchain-term": "鏈上", + "onchain-definition": "指在區塊鏈上發生且公開的操作或交易。", "optimistic-rollup-term": "樂觀卷軸", "optimistic-rollup-definition": "樂觀卷軸是一種二層網路解決方案,可以加速以太坊上的交易,假設除非受到挑戰,否則預設交易都是有效的。更多關於樂觀卷軸的資訊。", "peer-to-peer-network-term": "點對點網路", diff --git a/src/intl/zh-tw/glossary.json b/src/intl/zh-tw/glossary.json index 3c33752574d..b92580ef626 100644 --- a/src/intl/zh-tw/glossary.json +++ b/src/intl/zh-tw/glossary.json @@ -257,12 +257,12 @@ "node-definition": "參與網路的軟體用戶端。更多關於節點和用戶端的資訊。", "nonce-term": "隨機數", "nonce-definition": "在密碼學裏,只能使用一次的值。帳戶隨機數是每個帳戶中的交易計數器,用於防止重播攻擊。", - "off-chain-term": "鏈下", - "off-chain-definition": "鏈下是指存在於區塊鏈以外的任何交易或資料。由於在鏈上提交每筆交易可能成本高昂且效率低下,因此第三方工具(例如處理定價資料的預言機)或執行更高吞吐量交易的二層網路解決方案,在鏈下處理大量工作並會以較低的頻率提交資訊到鏈上。", + "offchain-term": "鏈下", + "offchain-definition": "鏈下是指存在於區塊鏈以外的任何交易或資料。由於在鏈上提交每筆交易可能成本高昂且效率低下,因此第三方工具(例如處理定價資料的預言機)或執行更高吞吐量交易的二層網路解決方案,在鏈下處理大量工作並會以較低的頻率提交資訊到鏈上。", "ommer-term": "Ommer(叔)區塊", "ommer-definition": "當工作量證明礦工發現有效的區塊時,另一個礦工可能已經發布了首先新增到區塊鏈頂端的競爭區塊。這個有效但過時的區塊可以作為 ommer 被新區塊包含,並獲得部分區塊獎勵。術語「ommer」是對父塊的兄弟姐妹區塊的首選中性術語,但有時也被稱為「叔」。當以太坊仍是工作證明網路時,這對於以太坊來說很常見。現在以太坊使用權益證明,每個時隙只會選擇一個區塊提議者。", - "on-chain-term": "鏈上", - "on-chain-definition": "指在區塊鏈上發生且公開的操作或交易。

可以將其視為在一個共享大筆記本中寫一些東西,每個人都可以看到和檢查,確保所寫的內容(例如傳送數位貨幣或簽訂合約)是永久性的並且無法更改或刪除。", + "onchain-term": "鏈上", + "onchain-definition": "指在區塊鏈上發生且公開的操作或交易。

可以將其視為在一個共享大筆記本中寫一些東西,每個人都可以看到和檢查,確保所寫的內容(例如傳送數位貨幣或簽訂合約)是永久性的並且無法更改或刪除。", "optimistic-rollup-term": "樂觀卷軸", "optimistic-rollup-definition": "樂觀卷軸是一種二層網路解決方案,可以加速以太坊上的交易,假設除非受到挑戰,否則預設交易都是有效的。更多關於樂觀卷軸的資訊。", "oracle-term": "預言機", diff --git a/src/intl/zh/glossary-tooltip.json b/src/intl/zh/glossary-tooltip.json index c0a7004d7a2..64e47a9e30c 100644 --- a/src/intl/zh/glossary-tooltip.json +++ b/src/intl/zh/glossary-tooltip.json @@ -101,8 +101,8 @@ "node-definition": "参与网络的软件客户端。了解有关节点和客户端的更多信息。", "ommer-term": "叔块", "ommer-definition": "当工作量证明矿工发现有效的区块时,另一个矿工可能已经发布了首先添加到区块链顶端的竞争区块。这个有效但过时的区块可以作为叔块包含在新区块内,并获得部分区块奖励。术语“ommer”是指代父块同胞的首选中性术语,但有时也称为“uncle”。当以太坊曾经是一个工作量证明网络时,这对于以太坊来说很常见。现在以太坊使用权益证明,每个时隙只选择一个区块提议者。", - "on-chain-term": "链上", - "on-chain-definition": "是指发生在区块链上并且公开的操作或交易。", + "onchain-term": "链上", + "onchain-definition": "是指发生在区块链上并且公开的操作或交易。", "optimistic-rollup-term": "乐观卷叠", "optimistic-rollup-definition": "乐观卷叠是一种二层网络解决方案,可以加速以太坊上的交易,假设交易默认有效,除非受到质疑。了解有关乐观卷叠的更多信息。", "peer-to-peer-network-term": "对等网络", diff --git a/src/intl/zh/glossary.json b/src/intl/zh/glossary.json index aba62911eb0..130b98fcaca 100644 --- a/src/intl/zh/glossary.json +++ b/src/intl/zh/glossary.json @@ -257,12 +257,12 @@ "node-definition": "参与网络的软件客户端。了解有关节点和客户端的更多信息。", "nonce-term": "Nonce", "nonce-definition": "在密码学中,只能使用一次的值。帐户随机数是每个帐户中的交易计数器,用于防止重放攻击。", - "off-chain-term": "链下", - "off-chain-definition": "链下是指存在于区块链之外的任何交易或数据。由于在链上进行每笔交易可能成本高昂且效率低下,因此第三方工具(例如处理定价数据的预言机)或执行较高吞吐量交易的二层网络解决方案在链下执行大量处理工作,并以更低的频率在链上提交信息。", + "offchain-term": "链下", + "offchain-definition": "链下是指存在于区块链之外的任何交易或数据。由于在链上进行每笔交易可能成本高昂且效率低下,因此第三方工具(例如处理定价数据的预言机)或执行较高吞吐量交易的二层网络解决方案在链下执行大量处理工作,并以更低的频率在链上提交信息。", "ommer-term": "叔块", "ommer-definition": "当工作量证明矿工发现有效的区块时,另一个矿工可能已经发布了首先添加到区块链顶端的竞争区块。这个有效但过时的区块可以作为叔块包含在新区块内,并获得部分区块奖励。术语“ommer”是指代父块同胞的首选中性术语,但有时也称为“uncle”。当以太坊曾经是一个工作量证明网络时,这对于以太坊来说很常见。现在以太坊使用权益证明,每个时隙只选择一个区块提议者。", - "on-chain-term": "链上", - "on-chain-definition": "指区块链上发生的公开操作或交易。

将其视为在一个共享大笔记本中写一些东西,每个人都可以看到和检查,确保所写的任何内容(例如发送数字货币或签订合约)是永久性的,无法更改或删除。", + "onchain-term": "链上", + "onchain-definition": "指区块链上发生的公开操作或交易。

将其视为在一个共享大笔记本中写一些东西,每个人都可以看到和检查,确保所写的任何内容(例如发送数字货币或签订合约)是永久性的,无法更改或删除。", "optimistic-rollup-term": "乐观卷叠", "optimistic-rollup-definition": "乐观卷叠是一种二层网络解决方案,可以加速以太坊上的交易,假设交易默认有效,除非受到质疑。了解有关乐观卷叠的更多信息。", "oracle-term": "预言机", diff --git a/src/layouts/Docs.tsx b/src/layouts/Docs.tsx index a4e521886b9..c9abf47bf2e 100644 --- a/src/layouts/Docs.tsx +++ b/src/layouts/Docs.tsx @@ -1,12 +1,9 @@ -import { useRouter } from "next/router" import type { HTMLAttributes } from "react" -import { Badge } from "@chakra-ui/react" import { ChildOnlyProp } from "@/lib/types" import type { DocsFrontmatter, MdPageContent } from "@/lib/interfaces" import BannerNotification from "@/components/Banners/BannerNotification" -import { ButtonLink } from "@/components/Buttons" import CallToContribute from "@/components/CallToContribute" import Card from "@/components/Card" import Codeblock from "@/components/Codeblock" @@ -28,6 +25,7 @@ import SideNav from "@/components/SideNav" import SideNavMobile from "@/components/SideNavMobile" import TableOfContents from "@/components/TableOfContents" import Translation from "@/components/Translation" +import { ButtonLink } from "@/components/ui/buttons/Button" import { Divider } from "@/components/ui/divider" import InlineLink from "@/components/ui/Link" import { mdxTableComponents } from "@/components/ui/table" @@ -36,6 +34,8 @@ import YouTube from "@/components/YouTube" import { cn } from "@/lib/utils/cn" import { getEditPath } from "@/lib/utils/editPath" +import { usePathname } from "@/i18n/routing" + const baseHeadingClasses = "font-mono uppercase font-bold scroll-mt-40 break-words" @@ -81,7 +81,6 @@ export const docsComponents = { h4: H4, pre: Codeblock, ...mdxTableComponents, - Badge, ButtonLink, Card, CallToContribute, @@ -115,12 +114,12 @@ export const DocsLayout = ({ contentNotTranslated, }: DocsLayoutProps) => { const isPageIncomplete = !!frontmatter.incomplete - const { asPath: relativePath } = useRouter() - const absoluteEditPath = getEditPath(relativePath) + const pathname = usePathname() + const absoluteEditPath = getEditPath(pathname) return (
- + {isPageIncomplete && ( @@ -130,7 +129,7 @@ export const DocsLayout = ({ className="flex justify-between bg-background-highlight lg:pe-8" dir={contentNotTranslated ? "ltr" : "unset"} > - +

{frontmatter.title}

) => ( @@ -86,13 +87,14 @@ export const StaticLayout = ({ lastEditLocaleTimestamp, contentNotTranslated, }: StaticLayoutProps) => { - const { locale, asPath } = useRouter() + const locale = useLocale() + const pathname = usePathname() const absoluteEditPath = getEditPath(slug) return (
- + - {!asPath.includes("/whitepaper") && ( + {!pathname.includes("/whitepaper") && (

) => ( { - const { asPath: relativePath } = useRouter() - const absoluteEditPath = getEditPath(relativePath) + const pathname = usePathname() + const absoluteEditPath = getEditPath(pathname) return (

diff --git a/src/layouts/md/Roadmap.tsx b/src/layouts/md/Roadmap.tsx index 84e434033eb..9a38cdcf7ed 100644 --- a/src/layouts/md/Roadmap.tsx +++ b/src/layouts/md/Roadmap.tsx @@ -1,5 +1,3 @@ -import { useTranslation } from "next-i18next" - import type { ChildOnlyProp } from "@/lib/types" import type { MdPageContent, RoadmapFrontmatter } from "@/lib/interfaces" @@ -10,6 +8,7 @@ import RoadmapImageContent from "@/components/Roadmap/RoadmapImageContent" import { ContentLayout } from "../ContentLayout" +import { useTranslation } from "@/hooks/useTranslation" import RoadmapHubHeroImage from "@/public/images/heroes/roadmap-hub-hero.jpg" const CardGrid = (props: ChildOnlyProp) => ( diff --git a/src/layouts/md/Staking.tsx b/src/layouts/md/Staking.tsx index f6a85b14112..f5c6efeea43 100644 --- a/src/layouts/md/Staking.tsx +++ b/src/layouts/md/Staking.tsx @@ -1,5 +1,4 @@ import { HTMLAttributes } from "react" -import { useTranslation } from "next-i18next" import type { ChildOnlyProp } from "@/lib/types" import type { MdPageContent, StakingFrontmatter } from "@/lib/interfaces" @@ -26,6 +25,8 @@ import UpgradeStatus from "@/components/UpgradeStatus" import { ContentLayout } from "../ContentLayout" +import { useTranslation } from "@/hooks/useTranslation" + const Heading1 = (props: HTMLAttributes) => ( ) diff --git a/src/layouts/md/Translatathon.tsx b/src/layouts/md/Translatathon.tsx index a52ad42e7ce..24b6ba50eac 100644 --- a/src/layouts/md/Translatathon.tsx +++ b/src/layouts/md/Translatathon.tsx @@ -4,7 +4,7 @@ import type { MdPageContent, SharedFrontmatter } from "@/lib/interfaces" import { List as ButtonDropdownList } from "@/components/ButtonDropdown" import Card from "@/components/Card" import { ContentHero, ContentHeroProps } from "@/components/Hero" -import { TwImage as Image } from "@/components/Image" +import { Image } from "@/components/Image" import { ApplyNow } from "@/components/Translatathon/ApplyNow" import { APPLICATION_URL } from "@/components/Translatathon/constants" import { DatesAndTimeline } from "@/components/Translatathon/DatesAndTimeline" diff --git a/src/layouts/md/Upgrade.tsx b/src/layouts/md/Upgrade.tsx index d48f2261097..40128e528f2 100644 --- a/src/layouts/md/Upgrade.tsx +++ b/src/layouts/md/Upgrade.tsx @@ -1,5 +1,3 @@ -import { useTranslation } from "next-i18next" - import type { ChildOnlyProp } from "@/lib/types" import type { MdPageContent, UpgradeFrontmatter } from "@/lib/interfaces" @@ -14,6 +12,8 @@ import { getSummaryPoints } from "@/lib/utils/getSummaryPoints" import { ContentLayout } from "../ContentLayout" +import { useTranslation } from "@/hooks/useTranslation" + // Upgrade layout components export const upgradeComponents = { MergeArticleList, @@ -42,7 +42,7 @@ export const UpgradeLayout = ({ const dropdownLinks: ButtonDropdownList = { text: t("page-upgrades-upgrades-guide"), - ariaLabel: t("page-upgrades-upgrades-aria-label"), + ariaLabel: t("page-upgrades-index:page-upgrades-upgrades-aria-label"), items: [ { text: t("page-upgrades-upgrades-beacon-chain"), diff --git a/src/layouts/md/UseCases.tsx b/src/layouts/md/UseCases.tsx index 828459d71c8..665608498fe 100644 --- a/src/layouts/md/UseCases.tsx +++ b/src/layouts/md/UseCases.tsx @@ -1,6 +1,3 @@ -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" - import type { ChildOnlyProp } from "@/lib/types" import type { MdPageContent, UseCasesFrontmatter } from "@/lib/interfaces" @@ -8,7 +5,7 @@ import BannerNotification from "@/components/Banners/BannerNotification" import { List as ButtonDropdownList } from "@/components/ButtonDropdown" import Emoji from "@/components/Emoji" import { ContentHero } from "@/components/Hero" -import InlineLink from "@/components/Link" +import InlineLink from "@/components/ui/Link" import { List, ListItem } from "@/components/ui/list" import { getEditPath } from "@/lib/utils/editPath" @@ -16,6 +13,9 @@ import { getSummaryPoints } from "@/lib/utils/getSummaryPoints" import { ContentLayout } from "../ContentLayout" +import { useTranslation } from "@/hooks/useTranslation" +import { usePathname } from "@/i18n/routing" + // UseCases layout components export const useCasesComponents = { // Export empty object if none needed @@ -32,12 +32,12 @@ export const UseCasesLayout = ({ tocItems, contentNotTranslated, }: UseCasesLayoutProps) => { - const { asPath: relativePath } = useRouter() + const pathname = usePathname() const { t } = useTranslation("template-usecase") const summaryPoints = getSummaryPoints(frontmatter) - const absoluteEditPath = getEditPath(relativePath) + const absoluteEditPath = getEditPath(pathname) const dropdownLinks: ButtonDropdownList = { text: t("template-usecase:template-usecase-dropdown"), diff --git a/src/layouts/stories/BaseLayout.stories.tsx b/src/layouts/stories/BaseLayout.stories.tsx index 832795c4255..c0079c8248e 100644 --- a/src/layouts/stories/BaseLayout.stories.tsx +++ b/src/layouts/stories/BaseLayout.stories.tsx @@ -1,6 +1,7 @@ -import { Center } from "@chakra-ui/react" import type { Meta, StoryObj } from "@storybook/react" +import { Center } from "@/components/ui/flex" + import { langViewportModes } from "../../../.storybook/modes" import { BaseLayout as BaseLayoutComponent } from "../BaseLayout" @@ -14,6 +15,9 @@ const meta = { ...langViewportModes, }, }, + nextjs: { + appDirectory: true, + }, }, argTypes: { children: { @@ -34,7 +38,7 @@ export default meta export const BaseLayout: StoryObj = { args: { children: ( -
+
Content Here
), diff --git a/src/layouts/stories/ContentLayout.stories.tsx b/src/layouts/stories/ContentLayout.stories.tsx index 64789322754..44b16b08087 100644 --- a/src/layouts/stories/ContentLayout.stories.tsx +++ b/src/layouts/stories/ContentLayout.stories.tsx @@ -1,6 +1,7 @@ -import { Center } from "@chakra-ui/react" import type { Meta, StoryObj } from "@storybook/react" +import { Center } from "@/components/ui/flex" + import { langViewportModes } from "../../../.storybook/modes" import { ContentLayout as ContentLayoutComponent } from "../ContentLayout" @@ -29,7 +30,7 @@ export default meta export const ContentLayout: StoryObj = { args: { children: ( -
+
Content Here
), @@ -61,7 +62,7 @@ export const ContentLayout: StoryObj = { }, maxDepth: 2, heroSection: ( -
+
Hero section
), diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 83fc01c9863..4149b2465c9 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -6,7 +6,7 @@ import i18nConfig from "../../i18n.config.json" import type { CommunityBlog } from "./types" -export const OLD_CONTENT_DIR = "src/content" +export const OLD_CONTENT_DIR = "src/content" // For old git commit history -- do not remove export const CONTENT_DIR = "public/content" export const TRANSLATIONS_DIR = "public/content/translations" export const TRANSLATED_IMAGES_DIR = "/content/translations" @@ -19,7 +19,7 @@ export const NULL_VALUE = "—" export const DEFAULT_LOCALE = "en" export const FAKE_LOCALE = "default" // Sorted list of supported locales codes, defined in `i18n.config.json` -const BUILD_LOCALES = process.env.BUILD_LOCALES +const BUILD_LOCALES = process.env.NEXT_PUBLIC_BUILD_LOCALES export const LOCALES_CODES = BUILD_LOCALES ? BUILD_LOCALES.split(",") : i18nConfig.map(({ code }) => code) diff --git a/src/lib/types.ts b/src/lib/types.ts index f79699248e2..7557f139428 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -2,7 +2,6 @@ import type { Options } from "mdast-util-toc" import type { NextPage } from "next" import type { AppProps } from "next/app" import type { StaticImageData } from "next/image" -import type { SSRConfig } from "next-i18next" import type { ReactElement, ReactNode } from "react" import type { ColumnDef } from "@tanstack/react-table" @@ -28,7 +27,7 @@ import allQuestionData from "@/data/quizzes/questionBank" import { screens } from "./utils/screen" import { WALLETS_FILTERS_DEFAULT } from "./constants" -import { layoutMapping } from "@/pages/[...slug]" +import { layoutMapping } from "@/pages/[locale]/[...slug]" // Credit: https://stackoverflow.com/a/52331580 export type Unpacked = T extends (infer U)[] ? U : T @@ -55,8 +54,14 @@ export type Root = { lastDeployLocaleTimestamp: string } -export type BasePageProps = SSRConfig & - Pick +export type BasePageProps = Pick< + Root, + "contentNotTranslated" | "lastDeployLocaleTimestamp" +> + +export type Params = { + locale: string +} export type Frontmatter = RoadmapFrontmatter & UpgradeFrontmatter & diff --git a/src/lib/utils/editPath.ts b/src/lib/utils/editPath.ts index 5129016e4df..11863f1acc8 100644 --- a/src/lib/utils/editPath.ts +++ b/src/lib/utils/editPath.ts @@ -2,5 +2,10 @@ import { join } from "path" import { CONTENT_DIR, EDIT_CONTENT_URL } from "@/lib/constants" +import { cleanPath } from "./url" + export const getEditPath = (relativePath: string): string => - new URL(join(CONTENT_DIR, relativePath, "index.md"), EDIT_CONTENT_URL).href + new URL( + join(CONTENT_DIR, cleanPath(relativePath), "index.md"), + EDIT_CONTENT_URL + ).href diff --git a/src/lib/utils/md.ts b/src/lib/utils/md.ts index 7497e70a135..08dd074f9f8 100644 --- a/src/lib/utils/md.ts +++ b/src/lib/utils/md.ts @@ -16,308 +16,44 @@ import { CONTENT_DIR, DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" import { toPosixPath } from "./relativePath" -import { ITutorial } from "@/pages/developers/tutorials" +import { ITutorial } from "@/pages/[locale]/developers/tutorials" -function getCurrentDir() { +function getContentRoot() { return join(process.cwd(), CONTENT_DIR) } const getPostSlugs = (dir: string, files: string[] = []) => { - const currentDir = getCurrentDir() - const contentDir = join(currentDir, dir) - // Temporal list of content pages allowed to be compiled - // When a content page is migrated (and he components being used), should be added to this list - const temporalAllowedPages = [ - // Use cases (8/8) ✅ - "/dao", - "/decentralized-identity", - "/defi", - "/desci", - "/nft", - "/payments", - "/refi", - "/social-networks", - // Staking (4/4) ✅ - "/staking/pools", - "/staking/saas", - "/staking/solo", - "/staking/withdrawals", - // Roadmap (5/5) ✅ - "/roadmap", - "/roadmap/future-proofing", - "/roadmap/scaling", - "/roadmap/security", - "/roadmap/user-experience", - // Upgrade (2/2) ✅ - "/roadmap/beacon-chain", - "/roadmap/merge", - // Developer docs (0/95) - "/developers/docs/", - "/developers/docs/accounts", - "/developers/docs/apis/backend", - "/developers/docs/apis/javascript", - "/developers/docs/apis/json-rpc", - "/developers/docs/blocks", - "/developers/docs/bridges", - "/developers/docs/consensus-mechanisms", - "/developers/docs/consensus-mechanisms/poa", - "/developers/docs/consensus-mechanisms/pos", - "/developers/docs/consensus-mechanisms/pos/attack-and-defense", - "/developers/docs/consensus-mechanisms/pos/attestations", - "/developers/docs/consensus-mechanisms/pos/block-proposal", - "/developers/docs/consensus-mechanisms/pos/faqs", - "/developers/docs/consensus-mechanisms/pos/gasper", - "/developers/docs/consensus-mechanisms/pos/keys", - "/developers/docs/consensus-mechanisms/pos/pos-vs-pow", - "/developers/docs/consensus-mechanisms/pos/rewards-and-penalties", - "/developers/docs/consensus-mechanisms/pos/weak-subjectivity", - "/developers/docs/consensus-mechanisms/pow/", - "/developers/docs/consensus-mechanisms/pow/mining", - "/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms", - "/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/dagger-hashimoto", - "/developers/docs/consensus-mechanisms/pow/mining/mining-algorithms/ethash", - "/developers/docs/dapps", - "/developers/docs/data-and-analytics", - "/developers/docs/data-and-analytics/block-explorers", - "/developers/docs/data-availability", - "/developers/docs/data-availability/blockchain-data-storage-strategies", - "/developers/docs/data-structures-and-encoding", - "/developers/docs/data-structures-and-encoding/patricia-merkle-trie", - "/developers/docs/data-structures-and-encoding/rlp", - "/developers/docs/data-structures-and-encoding/ssz", - "/developers/docs/data-structures-and-encoding/web3-secret-storage", - "/developers/docs/design-and-ux", - "/developers/docs/design-and-ux/heuristics-for-web3", - "/developers/docs/design-and-ux/dex-design-best-practice", - "/developers/docs/development-networks", - "/developers/docs/ethereum-stack", - "/developers/docs/evm", - "/developers/docs/evm/opcodes", - "/developers/docs/frameworks", - "/developers/docs/gas", - "/developers/docs/ides", - "/developers/docs/intro-to-ether", - "/developers/docs/intro-to-ethereum", - "/developers/docs/mev", - "/developers/docs/networking-layer", - "/developers/docs/networking-layer/network-addresses", - "/developers/docs/networking-layer/portal-network", - "/developers/docs/networks", - "/developers/docs/nodes-and-clients", - "/developers/docs/nodes-and-clients/archive-nodes", - "/developers/docs/nodes-and-clients/bootnodes", - "/developers/docs/nodes-and-clients/client-diversity", - "/developers/docs/nodes-and-clients/light-clients", - "/developers/docs/nodes-and-clients/node-architecture", - "/developers/docs/nodes-and-clients/nodes-as-a-service", - "/developers/docs/nodes-and-clients/run-a-node", - "/developers/docs/oracles", - "/developers/docs/programming-languages", - "/developers/docs/programming-languages/dart", - "/developers/docs/programming-languages/delphi", - "/developers/docs/programming-languages/dot-net", - "/developers/docs/programming-languages/elixir", - "/developers/docs/programming-languages/golang", - "/developers/docs/programming-languages/java", - "/developers/docs/programming-languages/javascript", - "/developers/docs/programming-languages/python", - "/developers/docs/programming-languages/ruby", - "/developers/docs/programming-languages/rust", - "/developers/docs/scaling", - "/developers/docs/scaling/optimistic-rollups", - "/developers/docs/scaling/plasma", - "/developers/docs/scaling/sidechains", - "/developers/docs/scaling/state-channels", - "/developers/docs/scaling/validium", - "/developers/docs/scaling/zk-rollups", - "/developers/docs/smart-contracts", - "/developers/docs/smart-contracts/anatomy", - "/developers/docs/smart-contracts/compiling", - "/developers/docs/smart-contracts/composability", - "/developers/docs/smart-contracts/deploying", - "/developers/docs/smart-contracts/formal-verification", - "/developers/docs/smart-contracts/languages", - "/developers/docs/smart-contracts/libraries", - "/developers/docs/smart-contracts/security", - "/developers/docs/smart-contracts/testing", - "/developers/docs/smart-contracts/upgrading", - "/developers/docs/smart-contracts/verifying", - "/developers/docs/standards", - "/developers/docs/standards/tokens", - "/developers/docs/standards/tokens/erc-20", - "/developers/docs/standards/tokens/erc-223", - "/developers/docs/standards/tokens/erc-721", - "/developers/docs/standards/tokens/erc-777", - "/developers/docs/standards/tokens/erc-1155", - "/developers/docs/standards/tokens/erc-4626", - "/developers/docs/storage", - "/developers/docs/transactions", - "/developers/docs/web2-vs-web3", - // Developer tutorials (53/53) ✅ - "/developers/tutorials/a-developers-guide-to-ethereum-part-one", - "/developers/tutorials/all-you-can-cache", - "/developers/tutorials/calling-a-smart-contract-from-javascript", - "/developers/tutorials/create-and-deploy-a-defi-app", - "/developers/tutorials/deploying-your-first-smart-contract", - "/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet", - "/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit", - "/developers/tutorials/eip-1271-smart-contract-signatures", - "/developers/tutorials/erc-721-vyper-annotated-code", - "/developers/tutorials/erc20-annotated-code", - "/developers/tutorials/erc20-with-safety-rails", - "/developers/tutorials/getting-started-with-ethereum-development-using-alchemy", - "/developers/tutorials/guide-to-smart-contract-security-tools", - "/developers/tutorials/hello-world-smart-contract", - "/developers/tutorials/hello-world-smart-contract-fullstack", - "/developers/tutorials/how-to-implement-an-erc721-market", - "/developers/tutorials/how-to-mint-an-nft", - "/developers/tutorials/how-to-mock-solidity-contracts-for-testing", - "/developers/tutorials/how-to-use-echidna-to-test-smart-contracts", - "/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs", - "/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs", - "/developers/tutorials/how-to-use-tellor-as-your-oracle", - "/developers/tutorials/how-to-view-nft-in-metamask", - "/developers/tutorials/how-to-write-and-deploy-an-nft", - "/developers/tutorials/interact-with-other-contracts-from-solidity", - "/developers/tutorials/ipfs-decentralized-ui", - "/developers/tutorials/kickstart-your-dapp-frontend-development-with-create-eth-app", - "/developers/tutorials/learn-foundational-ethereum-topics-with-sql", - "/developers/tutorials/logging-events-smart-contracts", - "/developers/tutorials/merkle-proofs-for-offline-data-integrity", - "/developers/tutorials/monitoring-geth-with-influxdb-and-grafana", - "/developers/tutorials/nft-minter", - "/developers/tutorials/optimism-std-bridge-annotated-code", - "/developers/tutorials/reverse-engineering-a-contract", - "/developers/tutorials/run-node-raspberry-pi", - "/developers/tutorials/scam-token-tricks", - "/developers/tutorials/secure-development-workflow", - "/developers/tutorials/send-token-ethersjs", - "/developers/tutorials/sending-transactions-using-web3-and-alchemy", - "/developers/tutorials/server-components", - "/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript", - "/developers/tutorials/short-abi", - "/developers/tutorials/smart-contract-security-guidelines", - "/developers/tutorials/testing-erc-20-tokens-with-waffle", - "/developers/tutorials/the-graph-fixing-web3-data-querying", - "/developers/tutorials/token-integration-checklist", - "/developers/tutorials/transfers-and-approval-of-erc-20-tokens-from-a-solidity-smart-contract", - "/developers/tutorials/understand-the-erc-20-token-smart-contract", - "/developers/tutorials/uniswap-v2-annotated-code", - "/developers/tutorials/using-websockets", - "/developers/tutorials/waffle-dynamic-mocking-and-testing-calls", - "/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers", - "/developers/tutorials/waffle-test-simple-smart-contract", - "/developers/tutorials/yellow-paper-evm", - "/developers/tutorials/creating-a-wagmi-ui-for-your-contract", - // Static (68/68) ✅ - "/about", - "/bridges", - "/community/code-of-conduct", - "/community/events", - "/community/get-involved", - "/community/grants", - "/community/language-resources", - "/community/online", - "/community/research", - "/community/support", - "/contributing", - "/contributing/adding-desci-projects", - "/contributing/adding-developer-tools", - "/contributing/adding-exchanges", - "/contributing/adding-glossary-terms", - "/contributing/adding-layer-2s", - "/contributing/adding-products", - "/contributing/adding-staking-products", - "/contributing/adding-wallets", - "/contributing/content-resources", - "/contributing/design", - "/contributing/design/adding-design-resources", - "/contributing/design-principles", - "/contributing/quizzes", - "/contributing/style-guide", - "/contributing/style-guide/content-standardization", - "/contributing/translation-program", - "/contributing/translation-program/content-buckets", - "/contributing/translation-program/faq", - "/contributing/translation-program/how-to-translate", - "/contributing/translation-program/mission-and-vision", - "/contributing/translation-program/playbook", - "/contributing/translation-program/resources", - "/contributing/translation-program/translatathon", - "/contributing/translation-program/translatathon/details", - "/contributing/translation-program/translatathon/translatathon-hubs", - "/contributing/translation-program/translatathon/terms-and-conditions", - "/contributing/translation-program/translators-guide", - "/cookie-policy", - "/eips", - "/energy-consumption", - "/enterprise", - "/enterprise/private-ethereum", - "/foundation", - "/glossary", - "/governance", - "/guides", - "/guides/how-to-create-an-ethereum-account", - "/guides/how-to-id-scam-tokens", - "/guides/how-to-revoke-token-access", - "/guides/how-to-swap-tokens", - "/guides/how-to-use-a-bridge", - "/guides/how-to-use-a-wallet", - "/history/", - "/privacy-policy", - "/roadmap/account-abstraction", - "/roadmap/danksharding", - "/roadmap/dencun", - "/roadmap/pectra", - "/roadmap/merge/issuance", - "/roadmap/pbs", - "/roadmap/secret-leader-election", - "/roadmap/single-slot-finality", - "/roadmap/statelessness", - "/roadmap/verkle-trees", - "/security", - "/smart-contracts", - "/staking/dvt", - - "/terms-of-use", - "/web3", - "/whitepaper", - "/wrapped-eth", - "/zero-knowledge-proofs", - ] + const contentRoot = getContentRoot() + const _dir = join(contentRoot, dir) // Get an array of all files and directories in the passed directory using `fs.readdirSync` - const fileList = fs.readdirSync(contentDir) + const dirContents = fs.readdirSync(_dir) // Create the full path of the file/directory by concatenating the passed directory and file/directory name - for (const file of fileList) { - const name = join(contentDir, file) + for (const fileOrDir of dirContents) { + // file = "about", "bridges".... "translations" (<-- skip that one)... + const path = join(_dir, fileOrDir) // Check if the current file/directory is a directory using fs.statSync - if (fs.statSync(name).isDirectory()) { + if (fs.statSync(path).isDirectory()) { + // Skip nested translations directory + if (fileOrDir === "translations") continue // If it is a directory, recursively call the `getPostSlugs` function with the // directory path and the files array - const nestedDir = join(dir, file) + const nestedDir = join(dir, fileOrDir) getPostSlugs(nestedDir, files) - } else { - const fileExtension = extname(name) + continue + } - if (fileExtension === ".md") { - // If it is a .md file (allowed content page), push the path to the files array - for (const page of temporalAllowedPages) { - const fullPagePath = join(currentDir, page) + // If the current file is not a markdown file, skip it + if (extname(path) !== ".md") continue - if (name.includes(fullPagePath)) { - files.push( - toPosixPath( - fullPagePath.replace(currentDir, "").replace("/index.md", "") - ) - ) - } - } - } - } + const sanitizedPath = toPosixPath( + path.replace(contentRoot, "").replace("/index.md", "") + ) + + files.push(sanitizedPath) } return files @@ -334,8 +70,8 @@ export const getContentBySlug = (slug: string) => { } } - const currentDir = getCurrentDir() - let fullPath = toPosixPath(join(currentDir, realSlug)) + const contentRoot = getContentRoot() + let fullPath = toPosixPath(join(contentRoot, realSlug)) let contentNotTranslated = false // If content is not translated, use english content fallback @@ -371,9 +107,9 @@ export const getContent = (dir: string) => { } export const getTutorialsData = (locale: string): ITutorial[] => { - const currentDir = getCurrentDir() + const contentRoot = getContentRoot() const fullPath = join( - currentDir, + contentRoot, locale !== "en" ? `translations/${locale!}` : "", "developers/tutorials" ) @@ -384,7 +120,7 @@ export const getTutorialsData = (locale: string): ITutorial[] => { tutorialData = languageTutorialFiles.map((dir) => { const filePath = join( - currentDir, + contentRoot, locale !== "en" ? `translations/${locale!}` : "", "developers/tutorials", dir, diff --git a/src/lib/utils/tutorial.ts b/src/lib/utils/tutorial.ts index 06303fd4ffa..c649e879561 100644 --- a/src/lib/utils/tutorial.ts +++ b/src/lib/utils/tutorial.ts @@ -2,7 +2,10 @@ import { Lang } from "@/lib/types" import { Skill } from "@/components/TutorialMetadata" -import { IExternalTutorial, ITutorial } from "@/pages/developers/tutorials" +import { + IExternalTutorial, + ITutorial, +} from "@/pages/[locale]/developers/tutorials" // Take all tutorials, and return a list of tutorials for a specific locale export const filterTutorialsByLang = ( diff --git a/src/lib/utils/url.ts b/src/lib/utils/url.ts index a9acae1eabe..2f332055bb3 100644 --- a/src/lib/utils/url.ts +++ b/src/lib/utils/url.ts @@ -1,4 +1,4 @@ -import { join } from "path" +import { extname, join } from "path" import { DEFAULT_LOCALE, @@ -21,6 +21,8 @@ export const isGlossary = (href: string): boolean => export const isPdf = (href: string): boolean => href.endsWith(".pdf") +export const isFile = (href: string): boolean => extname(href).length > 0 + export const sanitizeHitUrl = (url: string): string => url .replace(/^https?:\/\/[^/]+(?=\/)/, "") diff --git a/src/middleware.ts b/src/middleware.ts index 47b36dfe71c..8437cf57f9c 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,77 +1,10 @@ -import { NextRequest, NextResponse } from "next/server" +import createMiddleware from "next-intl/middleware" -import { DEFAULT_LOCALE, FAKE_LOCALE, LOCALES_CODES } from "./lib/constants" +import { routing } from "./i18n/routing" -const PUBLIC_FILE = /\.(.*)$/ - -function detectLocale(acceptLanguage: string | null) { - if (!acceptLanguage) { - return DEFAULT_LOCALE - } - - // it comes in the format of `en-US,en;q=0.9,de;q=0.8` - const locales = acceptLanguage.split(",") - - const locale = locales - .map((localeWeight) => localeWeight.split(";")[0].trim()) - .find((locale) => { - return LOCALES_CODES.includes(locale) - }) - - return locale -} +export default createMiddleware(routing) export const config = { - matcher: [ - "/", // explicit matcher for root route - /* - * Match all request paths except for the ones starting with: - * - _next/static (static files) - */ - "/((?!_next/static).*)", - ], -} - -const doubleLocaleRegex = new RegExp(`^/(${LOCALES_CODES.join("|")})/.*`, "i") - -// Middleware required to always display the locale prefix in the URL. It -// redirects to the default locale if the locale is not present in the URL -export async function middleware(req: NextRequest) { - const { pathname, locale, search } = req.nextUrl - - if ( - pathname.startsWith("/_next") || - pathname.includes("/api/") || - PUBLIC_FILE.test(pathname) - ) { - return - } - - /** - * If an URL has double langs in the URL it leads to 500 error, - * e.g.: /ja/en/eth/ - * - * It is a known bug: - * https://github.com/vercel/next.js/issues/52314 - * https://github.com/vercel/next.js/issues/52316 - */ - if (doubleLocaleRegex.test(pathname)) { - return NextResponse.redirect(new URL(`/${DEFAULT_LOCALE}/404`, req.url)) - } - - if (locale === FAKE_LOCALE) { - // Apparently, the built-in `localeDetection`from Next does not work when - // using the faked locale hack. So, we need to detect the locale manually - const localeDetected = detectLocale(req.headers.get("accept-language")) - const locale = localeDetected || DEFAULT_LOCALE - - const redirectUrl = new URL(`/${locale}${pathname}${search}`, req.url) - - // Add trailing slash if it's not present - if (!redirectUrl.pathname.endsWith("/")) { - redirectUrl.pathname = redirectUrl.pathname + "/" - } - - return NextResponse.redirect(redirectUrl, { status: 301 }) - } + // Skip all paths that should not be internationalized + matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"], } diff --git a/src/pages/404.tsx b/src/pages/404.tsx index b233605ea76..8a90b43cf29 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,18 +1,24 @@ import type { GetStaticProps } from "next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import { BasePageProps, Lang } from "@/lib/types" -import InlineLink from "@/components/Link" import MainArticle from "@/components/MainArticle" import Translation from "@/components/Translation" +import InlineLink from "@/components/ui/Link" import { existsNamespace } from "@/lib/utils/existsNamespace" import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" -export const getStaticProps = (async ({ locale }) => { +import { DEFAULT_LOCALE } from "@/lib/constants" + +import loadNamespaces from "@/i18n/loadNamespaces" + +export const getStaticProps = (async () => { + // TODO: generate 404 pages for each locale when we finish the app router migration + const locale = DEFAULT_LOCALE + const requiredNamespaces = getRequiredNamespacesForPage("/") // Want to check common namespace, so looking at requiredNamespaces[0] @@ -24,9 +30,11 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, diff --git a/src/pages/[...slug].tsx b/src/pages/[locale]/[...slug].tsx similarity index 92% rename from src/pages/[...slug].tsx rename to src/pages/[locale]/[...slug].tsx index a5e29f6f62f..eba8b57aa2e 100644 --- a/src/pages/[...slug].tsx +++ b/src/pages/[locale]/[...slug].tsx @@ -7,8 +7,6 @@ import type { GetStaticProps, InferGetStaticPropsType, } from "next/types" -import type { SSRConfig } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import { MDXRemote, type MDXRemoteSerializeResult } from "next-mdx-remote" import { serialize } from "next-mdx-remote/serialize" import { getPlaiceholder } from "plaiceholder" @@ -34,11 +32,11 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getContent, getContentBySlug } from "@/lib/utils/md" import { getLocaleTimestamp } from "@/lib/utils/time" import { remapTableOfContents } from "@/lib/utils/toc" -import { - filterRealLocales, - getRequiredNamespacesForPage, -} from "@/lib/utils/translations" +import { getRequiredNamespacesForPage } from "@/lib/utils/translations" + +import { LOCALES_CODES } from "@/lib/constants" +import loadNamespaces from "@/i18n/loadNamespaces" import { docsComponents, DocsLayout, @@ -64,6 +62,7 @@ import remarkInferToc from "@/lib/rehype/remarkInferToc" interface Params extends ParsedUrlQuery { slug: string[] + locale: string } export const layoutMapping = { @@ -88,17 +87,17 @@ const componentsMapping = { tutorial: tutorialsComponents, } as const -export const getStaticPaths = (({ locales }) => { +export const getStaticPaths = (() => { const contentFiles = getContent("/") // Generate page paths for each supported locale - const paths = filterRealLocales(locales).flatMap((locale) => + const paths = LOCALES_CODES.flatMap((locale) => contentFiles.map((file) => ({ params: { // Splitting nested paths to generate proper slug slug: file.slug.split("/").slice(1), + locale, }, - locale, })) ) @@ -108,11 +107,10 @@ export const getStaticPaths = (({ locales }) => { } }) satisfies GetStaticPaths -type Props = Omit[0], "children"> & - SSRConfig & { - mdxSource: MDXRemoteSerializeResult - gfissues: Awaited> - } +type Props = Omit[0], "children"> & { + mdxSource: MDXRemoteSerializeResult + gfissues: Awaited> +} const commitHistoryCache: CommitHistory = {} @@ -120,7 +118,7 @@ const loadData = dataLoader([["gfissues", fetchGFIs]]) export const getStaticProps = (async (context) => { const params = context.params! - const { locale } = context + const { locale } = params const markdown = getContentBySlug(`${locale}/${params.slug.join("/")}`) const frontmatter = markdown.frontmatter @@ -198,9 +196,11 @@ export const getStaticProps = (async (context) => { const [gfissues] = await loadData() + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, mdxSource, slug, frontmatter, diff --git a/src/pages/assets.tsx b/src/pages/[locale]/assets.tsx similarity index 96% rename from src/pages/assets.tsx rename to src/pages/[locale]/assets.tsx index f6e3b24d708..77c87985265 100644 --- a/src/pages/assets.tsx +++ b/src/pages/[locale]/assets.tsx @@ -1,13 +1,11 @@ import { HTMLAttributes } from "react" import type { GetStaticProps } from "next/types" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import AssetDownload from "@/components/AssetDownload" import FeedbackCard from "@/components/FeedbackCard" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import { Center, Flex } from "@/components/ui/flex" @@ -28,7 +26,11 @@ import { getLocaleTimestamp } from "@/lib/utils/time" // import leslieTheRhino from "@/public/images/upgrades/upgrade_rhino.png" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + import useColorModeValue from "@/hooks/useColorModeValue" +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import ethDiamondBlack from "@/public/images/assets/eth-diamond-black.png" import ethDiamondBlackGray from "@/public/images/assets/eth-diamond-black-gray.png" import ethDiamondBlackWhite from "@/public/images/assets/eth-diamond-black-white.jpg" @@ -96,7 +98,16 @@ const H3 = (props: ChildOnlyProp) => (

) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("assets") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -107,20 +118,21 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const AssetsPage = () => { // Ignore locale in the URL for SVG path in public directory to fix broken link // SVG path changes from /en/images => /images - const svgPathFromOrigin = - typeof window !== `undefined` ? window.location.origin : "" + const svgPathFromOrigin = "" const { t } = useTranslation("page-assets") const assetPageHeroImage = useColorModeValue( @@ -136,7 +148,7 @@ const AssetsPage = () => {
- { return b.score - a.score } -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("bug-bounty") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -240,17 +251,19 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const BugBountiesPage = () => { - const { pathname } = useRouter() + const pathname = usePathname() const { t } = useTranslation("page-bug-bounty") const consensusBountyHunters: Node[] = consensusData.sort(sortBountyHuntersFn) @@ -384,7 +397,7 @@ const BugBountiesPage = () => { description={t("page-upgrades-bug-bounty-meta-description")} /> {/* Uncomment for Bug Bounty Banner: */} - {/* */} + @@ -417,47 +430,47 @@ const BugBountiesPage = () => { {t("page-upgrades-bug-bounty-clients")} - + - + - + - + - + - - + - + - + - - + diff --git a/src/pages/community.tsx b/src/pages/[locale]/community.tsx similarity index 94% rename from src/pages/community.tsx rename to src/pages/[locale]/community.tsx index 4e345d0f1ad..cb40ef2a0e8 100644 --- a/src/pages/community.tsx +++ b/src/pages/[locale]/community.tsx @@ -1,9 +1,7 @@ import { BaseHTMLAttributes } from "react" import { GetStaticProps } from "next" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import { ICard, IGetInvolvedCard } from "@/lib/interfaces" import ActionCard from "@/components/ActionCard" @@ -12,7 +10,7 @@ import Card from "@/components/Card" import FeedbackCard from "@/components/FeedbackCard" import { HubHero } from "@/components/Hero" import type { HubHeroProps } from "@/components/Hero/HubHero" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import { ButtonLink, ButtonLinkProps } from "@/components/ui/buttons/Button" @@ -25,6 +23,10 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" // Static assets import developersEthBlockImg from "@/public/images/developers-eth-blocks.png" import dogeComputerImg from "@/public/images/doge-computer.png" @@ -38,7 +40,16 @@ import communityHeroImg from "@/public/images/heroes/community-hero.png" import upgradesCoreImg from "@/public/images/upgrades/core.png" import whatIsEthereumImg from "@/public/images/what-is-ethereum.png" -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/community") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -49,14 +60,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const CardContainer = ({ children }: ChildOnlyProp) => { return {children} @@ -222,7 +235,7 @@ const CommunityPage = () => {

- { - {
- {
- ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -67,17 +78,19 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const TranslatorAcknowledgements = () => { - const router = useRouter() + const pathname = usePathname() const { t } = useTranslation( "page-contributing-translation-program-acknowledgements" ) @@ -99,7 +112,7 @@ const TranslatorAcknowledgements = () => { /> - +

{t( "page-contributing-translation-program-acknowledgements-acknowledgement-page-title" @@ -141,7 +154,7 @@ const TranslatorAcknowledgements = () => {

{/* RIGHT COLUMN */}
- { {t("page-contributing-translation-program-acknowledgements-cert-3")} - + translator certificate diff --git a/src/pages/contributing/translation-program/contributors.tsx b/src/pages/[locale]/contributing/translation-program/contributors.tsx similarity index 82% rename from src/pages/contributing/translation-program/contributors.tsx rename to src/pages/[locale]/contributing/translation-program/contributors.tsx index 201102caeb6..aa33b7483b7 100644 --- a/src/pages/contributing/translation-program/contributors.tsx +++ b/src/pages/[locale]/contributing/translation-program/contributors.tsx @@ -1,10 +1,7 @@ import { BaseHTMLAttributes } from "react" -import { useRouter } from "next/router" import { GetStaticProps } from "next/types" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import { BasePageProps, CostLeaderboardData, Lang } from "@/lib/types" +import { BasePageProps, CostLeaderboardData, Lang, Params } from "@/lib/types" import Breadcrumbs from "@/components/Breadcrumbs" import FeedbackCard from "@/components/FeedbackCard" @@ -20,9 +17,24 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" -import allTimeData from "../../../data/translation-reports/alltime/alltime-data.json" +import allTimeData from "@/data/translation-reports/alltime/alltime-data.json" + +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" +import { usePathname } from "@/i18n/routing" + +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} -export const getStaticProps = (async ({ locale }) => { const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -35,14 +47,16 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const Content = ({ ...props }: BaseHTMLAttributes) => ( @@ -59,7 +73,7 @@ const Contributors = () => { const { t } = useTranslation( "page-contributing-translation-program-contributors" ) - const router = useRouter() + const pathname = usePathname() const translators = (allTimeData as CostLeaderboardData[]) .map((item: CostLeaderboardData) => item.username) @@ -77,7 +91,7 @@ const Contributors = () => { /> - +

{t("page-contributing-translation-program-contributors-title")}

diff --git a/src/pages/dapps.tsx b/src/pages/[locale]/dapps.tsx similarity index 96% rename from src/pages/dapps.tsx rename to src/pages/[locale]/dapps.tsx index 1bd681a8dcd..64ab7270a6c 100644 --- a/src/pages/dapps.tsx +++ b/src/pages/[locale]/dapps.tsx @@ -8,10 +8,9 @@ import React, { } from "react" import { type GetStaticProps } from "next" import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" +import { useLocale } from "next-intl" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import BoxGrid from "@/components/BoxGrid" import Callout from "@/components/Callout" @@ -21,7 +20,7 @@ import DocLink from "@/components/DocLink" import Emoji from "@/components/Emoji" import FeedbackCard from "@/components/FeedbackCard" import GhostCard from "@/components/GhostCard" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import InfoBanner from "@/components/InfoBanner" import MainArticle from "@/components/MainArticle" import PageHero from "@/components/PageHero" @@ -44,6 +43,10 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import aave from "@/public/images/dapps/aave.png" import ankr from "@/public/images/dapps/ankr.png" import api3 from "@/public/images/dapps/api3.png" @@ -126,38 +129,6 @@ const Content = (props: ChildOnlyProp) => (
) -const OptionContainer = (props: ChildOnlyProp) => ( - -) - -const Option = ( - props: Pick & { isActive: boolean } -) => { - return ( - ) })} - +
{/* Category-specific content */} {selectedCategory === CategoryType.FINANCE && ( @@ -1753,7 +1748,7 @@ const DappsPage = () => { - (
- - {title} +

{title}

{linkLabel}
) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/developers") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -137,14 +147,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps interface IDevelopersPath { emoji: string @@ -330,7 +342,7 @@ const DevelopersPage = () => { - ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage( "/developers/learning-tools" ) @@ -130,14 +141,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const LearningToolsPage = () => { const { t } = useTranslation(["page-developers-learning-tools"]) @@ -480,9 +493,7 @@ const LearningToolsPage = () => { { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage( "/developers/local-environment" ) @@ -65,15 +75,17 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, frameworksList: frameworksListData, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const LocalEnvironmentPage = ({ frameworksList, @@ -87,20 +99,9 @@ const LocalEnvironmentPage = ({ description={t("page-local-environment-setup-meta-desc")} />
- +

- +


@@ -110,14 +111,9 @@ const LocalEnvironmentPage = ({ - +

- +

@@ -143,7 +139,7 @@ const LocalEnvironmentPage = ({
- { ) } -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage( "/developers/tutorials" ) @@ -96,15 +106,17 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, internalTutorials: getTutorialsData(locale!), lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps export interface IExternalTutorial { url: string @@ -147,7 +159,7 @@ const TutorialPage = ({ internalTutorials, contentNotTranslated, }: InferGetServerSidePropsType) => { - const { locale } = useRouter() + const locale = useLocale() const filteredTutorialsByLang = useMemo( () => filterTutorialsByLang( @@ -218,21 +230,9 @@ const TutorialPage = ({ "page-developers-tutorials:page-tutorials-meta-description" )} /> - +

- +

diff --git a/src/pages/eth.tsx b/src/pages/[locale]/eth.tsx similarity index 95% rename from src/pages/eth.tsx rename to src/pages/[locale]/eth.tsx index 7a132a61422..1a68b49db57 100644 --- a/src/pages/eth.tsx +++ b/src/pages/[locale]/eth.tsx @@ -1,9 +1,7 @@ import { GetStaticProps } from "next" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import type { ComponentProps, HTMLAttributes } from "react" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import ActionCard from "@/components/ActionCard" import CalloutBanner from "@/components/CalloutBanner" @@ -13,7 +11,7 @@ import EthPriceCard from "@/components/EthPriceCard" import EthVideo from "@/components/EthVideo" import FeedbackCard from "@/components/FeedbackCard" import HorizontalCard from "@/components/HorizontalCard" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import InfoBanner from "@/components/InfoBanner" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" @@ -31,6 +29,10 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import eth from "@/public/images/eth.png" import ethCat from "@/public/images/eth-gif-cat.png" import defi from "@/public/images/finance_transparent.png" @@ -171,7 +173,16 @@ const CentralActionCard = (props: ComponentProps) => ( ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/eth") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -182,14 +193,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const EthPage = () => { const { t } = useTranslation("page-eth") @@ -306,7 +319,7 @@ const EthPage = () => { - ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/gas") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -95,14 +106,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const GasPage = () => { const { t } = useTranslation("page-gas") @@ -184,7 +197,7 @@ const GasPage = () => {
- + A robot
@@ -276,12 +289,7 @@ const GasPage = () => { ))}
- +
diff --git a/src/pages/get-eth.tsx b/src/pages/[locale]/get-eth.tsx similarity index 95% rename from src/pages/get-eth.tsx rename to src/pages/[locale]/get-eth.tsx index 547c621bc24..14f64b997e0 100644 --- a/src/pages/get-eth.tsx +++ b/src/pages/[locale]/get-eth.tsx @@ -1,9 +1,7 @@ import type { GetStaticProps, InferGetStaticPropsType } from "next/types" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import type { ReactNode } from "react" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import CalloutBanner from "@/components/CalloutBanner" import CardList, { @@ -13,7 +11,7 @@ import CentralizedExchanges from "@/components/CentralizedExchanges" import Emoji from "@/components/Emoji" import EthPriceCard from "@/components/EthPriceCard" import FeedbackCard from "@/components/FeedbackCard" -import { TwImage as Image } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import Translation from "@/components/Translation" @@ -38,7 +36,11 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + import { useBreakpointValue } from "@/hooks/useBreakpointValue" +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import uniswap from "@/public/images/dapps/uni.png" import dapps from "@/public/images/doge-computer.png" import bancor from "@/public/images/exchanges/bancor.png" @@ -74,7 +76,16 @@ type Props = BasePageProps & { lastDataUpdateDate: string } -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("get-eth") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -89,15 +100,17 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, lastDataUpdateDate, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const GetEthPage = ({ lastDataUpdateDate, diff --git a/src/pages/index.tsx b/src/pages/[locale]/index.tsx similarity index 97% rename from src/pages/index.tsx rename to src/pages/[locale]/index.tsx index 5a8b56b639e..6cb6180478c 100644 --- a/src/pages/index.tsx +++ b/src/pages/[locale]/index.tsx @@ -1,6 +1,5 @@ import { Fragment, lazy, Suspense } from "react" import type { GetStaticProps, InferGetStaticPropsType } from "next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import { FaDiscord, FaGithub } from "react-icons/fa6" import { IoMdCopy } from "react-icons/io" import { MdCheck } from "react-icons/md" @@ -10,12 +9,10 @@ import type { BasePageProps, CommunityBlog, Lang, + Params, RSSItem, } from "@/lib/types" -import SvgButtonLink, { - type SvgButtonLinkProps, -} from "@/components/Buttons/SvgButtonLink" import { ChevronNext } from "@/components/Chevron" import CodeModal from "@/components/CodeModal" import HomeHero from "@/components/Hero/HomeHero" @@ -25,11 +22,14 @@ import ValuesMarquee from "@/components/Homepage/ValuesMarquee" import AngleBrackets from "@/components/icons/angle-brackets.svg" import Calendar from "@/components/icons/calendar.svg" import CalendarAdd from "@/components/icons/calendar-add.svg" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import { TranslatathonBanner } from "@/components/Translatathon/TranslatathonBanner" import { Button, ButtonLink } from "@/components/ui/buttons/Button" +import SvgButtonLink, { + type SvgButtonLinkProps, +} from "@/components/ui/buttons/SvgButtonLink" import { Card, CardBanner, @@ -71,7 +71,9 @@ import { BLOG_FEEDS, BLOGS_WITHOUT_FEED, CALENDAR_DISPLAY_COUNT, + DEFAULT_LOCALE, GITHUB_REPO_URL, + LOCALES_CODES, RSS_DISPLAY_COUNT, } from "@/lib/constants" @@ -80,9 +82,10 @@ import { AccordionContent, AccordionItem, AccordionTrigger, -} from "../components/ui/accordion" +} from "../../components/ui/accordion" import { useClipboard } from "@/hooks/useClipboard" +import loadNamespaces from "@/i18n/loadNamespaces" import { fetchCommunityEvents } from "@/lib/api/calendarEvents" import { fetchEthPrice } from "@/lib/api/fetchEthPrice" import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie" @@ -134,7 +137,16 @@ const loadData = dataLoader( REVALIDATE_TIME * 1000 ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const [ ethPrice, totalEthStaked, @@ -184,9 +196,11 @@ export const getStaticProps = (async ({ locale }) => { })) as CommunityBlog[] blogLinks.push(...BLOGS_WITHOUT_FEED) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, calendar, contentNotTranslated, lastDeployLocaleTimestamp, @@ -194,7 +208,7 @@ export const getStaticProps = (async ({ locale }) => { rssData: { rssItems, blogLinks }, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const HomePage = ({ calendar, @@ -335,7 +349,7 @@ const HomePage = ({ {/* Activity - The strongest ecosystem */}
- + @@ -361,7 +375,7 @@ const HomePage = ({ className="md:flex-row-reverse" > - + @@ -429,7 +443,7 @@ const HomePage = ({ {/* Builders - Blockchain's biggest builder community */}
- + @@ -547,7 +561,6 @@ const HomePage = ({ {isModalOpen && ( - // TODO: Migrate CodeModal, CodeBlock from Chakra-UI to tailwind/shad-cn - + @@ -824,7 +837,7 @@ const HomePage = ({ loading="lazy" /> ) : ( - + )} diff --git a/src/pages/layer-2/index.tsx b/src/pages/[locale]/layer-2/index.tsx similarity index 92% rename from src/pages/layer-2/index.tsx rename to src/pages/[locale]/layer-2/index.tsx index 089d1e3914f..987c9727742 100644 --- a/src/pages/layer-2/index.tsx +++ b/src/pages/[locale]/layer-2/index.tsx @@ -1,13 +1,12 @@ import type { GetStaticProps } from "next/types" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { BasePageProps, GrowThePieData, Lang } from "@/lib/types" +import type { BasePageProps, GrowThePieData, Lang, Params } from "@/lib/types" import Callout from "@/components/Callout" import Card from "@/components/Card" import ExpandableCard from "@/components/ExpandableCard" import HubHero, { HubHeroProps } from "@/components/Hero/HubHero" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import { ButtonLink } from "@/components/ui/buttons/Button" @@ -16,14 +15,17 @@ import InlineLink from "@/components/ui/Link" import { dataLoader } from "@/lib/utils/data/dataLoader" import { existsNamespace } from "@/lib/utils/existsNamespace" import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" +import { networkMaturity } from "@/lib/utils/networkMaturity" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" import { layer2Data, Rollups } from "@/data/networks/networks" -import { BASE_TIME_UNIT } from "@/lib/constants" +import { BASE_TIME_UNIT, DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" +import loadNamespaces from "@/i18n/loadNamespaces" import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie" +import { fetchL2beat } from "@/lib/api/fetchL2beat" import HeroImage from "@/public/images/heroes/layer-2-hub-hero.jpg" import EthereumLogo from "@/public/images/layer-2/ethereum.png" import WalkingImage from "@/public/images/layer-2/layer-2-walking.png" @@ -34,11 +36,23 @@ import ManDogCardImage from "@/public/images/man-and-dog-playing.png" const REVALIDATE_TIME = BASE_TIME_UNIT * 24 const loadData = dataLoader( - [["growThePieData", fetchGrowThePie]], + [ + ["growThePieData", fetchGrowThePie], + ["l2beatData", fetchL2beat], + ], REVALIDATE_TIME * 1000 ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -49,28 +63,52 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) - const [growThePieData] = await loadData() + const [growThePieData, l2beatData] = await loadData() + + const getRandomL2s = () => { + let randomL2s = layer2Data.filter( + (network) => + networkMaturity(l2beatData.data.projects[network.l2beatID]) === "robust" + ) + + if (randomL2s.length === 0) { + randomL2s = layer2Data.filter( + (network) => + networkMaturity(l2beatData.data.projects[network.l2beatID]) === + "maturing" + ) + } + + return randomL2s.sort(() => 0.5 - Math.random()).slice(0, 3) + } const randomL2s = layer2Data.sort(() => 0.5 - Math.random()).slice(0, 9) + const userRandomL2s = getRandomL2s() + + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, randomL2s, + userRandomL2s, contentNotTranslated, lastDeployLocaleTimestamp, locale, growThePieData, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const Layer2Hub = ({ randomL2s, + userRandomL2s, growThePieData, locale, }: { randomL2s: Rollups + userRandomL2s: Rollups growThePieData: GrowThePieData locale: Lang }) => { @@ -161,7 +199,7 @@ const Layer2Hub = ({

- {/* Top logo */}
- {/* Bottom right logo */}
- {/* Bottom left logo */}
- {/* Top logo */}
- {/* Bottom right logo */}
- {/* Bottom left logo */}
- {/* Top logo */}
- {/* Bottom right logo */}
- {/* Bottom left logo */}
- - + Ethereum
@@ -390,7 +423,7 @@ const Layer2Hub = ({
- {randomL2s.slice(0, 3).map((l2, idx) => { + {userRandomL2s.map((l2, idx) => { return (
-
-
- + Walking

Why do we need multiple networks on Ethereum?

diff --git a/src/pages/layer-2/learn.tsx b/src/pages/[locale]/layer-2/learn.tsx similarity index 93% rename from src/pages/layer-2/learn.tsx rename to src/pages/[locale]/layer-2/learn.tsx index 01b1bc5adaf..68bc29e94b2 100644 --- a/src/pages/layer-2/learn.tsx +++ b/src/pages/[locale]/layer-2/learn.tsx @@ -1,14 +1,11 @@ import { GetStaticProps } from "next" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { BasePageProps, Lang } from "@/lib/types" +import type { BasePageProps, Lang, Params } from "@/lib/types" import Callout from "@/components/Callout" import Card from "@/components/Card" import { ContentHero, type ContentHeroProps } from "@/components/Hero" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import { StandaloneQuizWidget } from "@/components/Quiz/QuizWidget" @@ -20,6 +17,11 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import useTranslation from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" +import { usePathname } from "@/i18n/routing" import Callout2Image from "@/public/images/layer-2/learn-hero.png" import OptimisticRollupImage from "@/public/images/layer-2/optimistic_rollup.png" import RollupImage from "@/public/images/layer-2/rollup-2.png" @@ -28,7 +30,16 @@ import Callout1Image from "@/public/images/man-and-dog-playing.png" import DAOImage from "@/public/images/use-cases/dao-2.png" import WhatIsEthereumImage from "@/public/images/what-is-ethereum.png" -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -39,18 +50,20 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const Layer2Learn = () => { const { t } = useTranslation("page-layer-2-learn") - const { pathname } = useRouter() + const pathname = usePathname() const heroProps: ContentHeroProps = { breadcrumbs: { slug: pathname, startDepth: 1 }, @@ -141,7 +154,7 @@ const Layer2Learn = () => {

- { className="flex w-full flex-col gap-16 px-8 py-9 md:flex-row" >
- +
@@ -247,7 +260,7 @@ const Layer2Learn = () => {

{t("page-layer-2-learn-how-does-layer-2-work-rollups-2")}

- + {""}
@@ -261,7 +274,7 @@ const Layer2Learn = () => { key={idx} className="flex w-full flex-col gap-4 rounded-sm border border-solid border-body-light bg-background-highlight p-6 md:w-[50%]" > - + {""}

{card.title}

{card.description}

{card.childSentence} diff --git a/src/pages/layer-2/networks.tsx b/src/pages/[locale]/layer-2/networks.tsx similarity index 92% rename from src/pages/layer-2/networks.tsx rename to src/pages/[locale]/layer-2/networks.tsx index 86da260d5da..d74cbb5946f 100644 --- a/src/pages/layer-2/networks.tsx +++ b/src/pages/[locale]/layer-2/networks.tsx @@ -1,8 +1,6 @@ -import { useRouter } from "next/router" import type { GetStaticProps } from "next/types" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { BasePageProps, Lang } from "@/lib/types" +import type { BasePageProps, Lang, Params } from "@/lib/types" import Callout from "@/components/Callout" import { ContentHero, ContentHeroProps } from "@/components/Hero" @@ -21,8 +19,10 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations" import { ethereumNetworkData, layer2Data } from "@/data/networks/networks" import { walletsData } from "@/data/wallets/wallet-data" -import { BASE_TIME_UNIT } from "@/lib/constants" +import { BASE_TIME_UNIT, DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" +import loadNamespaces from "@/i18n/loadNamespaces" +import { usePathname } from "@/i18n/routing" import { fetchEthereumMarketcap } from "@/lib/api/fetchEthereumMarketcap" import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie" import { fetchGrowThePieBlockspace } from "@/lib/api/fetchGrowThePieBlockspace" @@ -45,7 +45,16 @@ const loadData = dataLoader( REVALIDATE_TIME * 1000 ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const [ ethereumMarketcapData, growThePieData, @@ -110,9 +119,11 @@ export const getStaticProps = (async ({ locale }) => { return maturityDiff }) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, locale, @@ -129,10 +140,10 @@ export const getStaticProps = (async ({ locale }) => { }, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const Layer2Networks = ({ layer2Data, locale, mainnetData }) => { - const { pathname } = useRouter() + const pathname = usePathname() const heroProps: ContentHeroProps = { breadcrumbs: { slug: pathname, startDepth: 1 }, diff --git a/src/pages/learn.tsx b/src/pages/[locale]/learn.tsx similarity index 96% rename from src/pages/learn.tsx rename to src/pages/[locale]/learn.tsx index a6eca2e9517..3bb00881083 100644 --- a/src/pages/learn.tsx +++ b/src/pages/[locale]/learn.tsx @@ -1,9 +1,13 @@ import { GetStaticProps } from "next" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import type { HTMLAttributes, ReactNode } from "react" -import type { BasePageProps, ChildOnlyProp, Lang, ToCItem } from "@/lib/types" +import type { + BasePageProps, + ChildOnlyProp, + Lang, + Params, + ToCItem, +} from "@/lib/types" import OriginalCard, { type CardProps as OriginalCardProps, @@ -12,7 +16,7 @@ import DocLink from "@/components/DocLink" import FeedbackCard from "@/components/FeedbackCard" import { HubHero } from "@/components/Hero" import type { HubHeroProps } from "@/components/Hero/HubHero" -import { type ImageProps, TwImage } from "@/components/Image" +import { Image, type ImageProps } from "@/components/Image" import LeftNavBar from "@/components/LeftNavBar" import MainArticle from "@/components/MainArticle" import { ContentContainer } from "@/components/MdComponents" @@ -27,6 +31,10 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import useTranslation from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import developersEthBlocks from "@/public/images/developers-eth-blocks.png" import dogeComputer from "@/public/images/doge-computer.png" import enterprise from "@/public/images/enterprise-eth.png" @@ -114,13 +122,22 @@ const H3 = ({ children, ...props }: HTMLAttributes) => ( ) const ImageHeight200 = ({ src, alt }: ImageProps) => ( - + {alt} ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/learn") - const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const contentNotTranslated = !existsNamespace(locale, requiredNamespaces[2]) const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( @@ -128,14 +145,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const LearnPage = () => { const { t } = useTranslation("page-learn") @@ -348,7 +367,7 @@ const LearnPage = () => {
- +
diff --git a/src/pages/quizzes.tsx b/src/pages/[locale]/quizzes.tsx similarity index 71% rename from src/pages/quizzes.tsx rename to src/pages/[locale]/quizzes.tsx index 5e690b30fb5..fbf90bfcdaa 100644 --- a/src/pages/quizzes.tsx +++ b/src/pages/[locale]/quizzes.tsx @@ -1,13 +1,9 @@ import { useMemo, useState } from "react" import { GetStaticProps, InferGetStaticPropsType, NextPage } from "next" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import { FaGithub } from "react-icons/fa" -import { Box, Flex, Icon, Stack, Text } from "@chakra-ui/react" -import { BasePageProps, Lang, QuizKey, QuizStatus } from "@/lib/types" +import { BasePageProps, Lang, Params, QuizKey, QuizStatus } from "@/lib/types" -import { ButtonLink } from "@/components/Buttons" import FeedbackCard from "@/components/FeedbackCard" import { HubHero } from "@/components/Hero" import MainArticle from "@/components/MainArticle" @@ -17,6 +13,8 @@ import QuizzesList from "@/components/Quiz/QuizzesList" import QuizzesModal from "@/components/Quiz/QuizzesModal" import QuizzesStats from "@/components/Quiz/QuizzesStats" import { useLocalQuizData } from "@/components/Quiz/useLocalQuizData" +import { ButtonLink } from "@/components/ui/buttons/Button" +import { Flex, HStack, Stack } from "@/components/ui/flex" import { existsNamespace } from "@/lib/utils/existsNamespace" import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" @@ -26,9 +24,11 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations" import { ethereumBasicsQuizzes, usingEthereumQuizzes } from "@/data/quizzes" -import { INITIAL_QUIZ } from "@/lib/constants" +import { DEFAULT_LOCALE, INITIAL_QUIZ, LOCALES_CODES } from "@/lib/constants" import { useDisclosure } from "@/hooks/useDisclosure" +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import HeroImage from "@/public/images/heroes/quizzes-hub-hero.png" const handleGHAdd = () => @@ -38,7 +38,16 @@ const handleGHAdd = () => eventName: "GH_add", }) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/quizzes") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -49,14 +58,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const QuizzesHubPage: NextPage< InferGetStaticPropsType @@ -78,7 +89,7 @@ const QuizzesHubPage: NextPage< ) return ( - + - - - - +
+ + +
- - - - - {t("want-more-quizzes")} - - - - {t("contribute")} - - +
+ +
+

{t("want-more-quizzes")}

+ +

{t("contribute")}

+
- - + + {t("add-quiz")} - +
- +
- +
- - +
+
- - +
+
) } diff --git a/src/pages/roadmap/vision.tsx b/src/pages/[locale]/roadmap/vision.tsx similarity index 76% rename from src/pages/roadmap/vision.tsx rename to src/pages/[locale]/roadmap/vision.tsx index 84af95eaf85..b01cae17597 100644 --- a/src/pages/roadmap/vision.tsx +++ b/src/pages/[locale]/roadmap/vision.tsx @@ -1,90 +1,93 @@ import { GetStaticProps } from "next" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { ComponentPropsWithRef } from "react" -import { - Box, - Flex, - type FlexProps, - Heading, - type HeadingProps, - List, - ListItem, - useToken, -} from "@chakra-ui/react" +import type { + ComponentProps, + ComponentPropsWithRef, + CSSProperties, +} from "react" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import Breadcrumbs from "@/components/Breadcrumbs" -import ButtonLink from "@/components/Buttons/ButtonLink" import Card from "@/components/Card" import Emoji from "@/components/Emoji" import FeedbackCard from "@/components/FeedbackCard" import InfoBanner from "@/components/InfoBanner" -import InlineLink from "@/components/Link" import MainArticle from "@/components/MainArticle" -import OldHeading from "@/components/OldHeading" -import Text from "@/components/OldText" import PageHero, { type ContentType as PageHeroContent, } from "@/components/PageHero" import PageMetadata from "@/components/PageMetadata" import Trilemma from "@/components/Trilemma" +import { ButtonLink } from "@/components/ui/buttons/Button" import { Divider } from "@/components/ui/divider" +import { Flex, type FlexProps, VStack } from "@/components/ui/flex" +import InlineLink from "@/components/ui/Link" +import { List, ListItem } from "@/components/ui/list" +import { cn } from "@/lib/utils/cn" import { existsNamespace } from "@/lib/utils/existsNamespace" import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" +import { screens } from "@/lib/utils/screen" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import useTranslation from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" +import { usePathname } from "@/i18n/routing" import oldship from "@/public/images/upgrades/oldship.png" +/** + * TODO: Consider replacing this with a global style for the `p` element + */ +const Text = (props: Omit, "className">) => ( +

+) + const Page = (props: ChildOnlyProp) => ( - + + + ) const PageContent = (props: ChildOnlyProp) => ( - + ) -const H2 = (props: HeadingProps) => ( - ) => ( +

) -const CenterH2 = (props: HeadingProps) =>

+const CenterH2 = (props: Omit, "className">) => ( +

+) -const H3 = (props: HeadingProps) => ( - , "className">) => ( +

) -const CardContainer = (props: FlexProps) => ( - +const CardContainer = ({ className, ...props }: FlexProps) => ( + ) const ProblemCardContainer = (props: ChildOnlyProp) => { - const containerMaxWidth = useToken("breakpoints", ["lg"]) - - return + return ( + + ) } const CentreCard = (props: ComponentPropsWithRef) => ( @@ -95,14 +98,26 @@ const CentreCard = (props: ComponentPropsWithRef) => ( ) const CentralContent = (props: ChildOnlyProp) => ( - +
) const TrilemmaContent = (props: ChildOnlyProp) => ( - +
) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/roadmap/vision") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -113,18 +128,20 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const VisionPage = () => { const { t } = useTranslation(["page-roadmap-vision", "page-upgrades-index"]) - const { pathname } = useRouter() + const pathname = usePathname() const paths = [ { @@ -162,7 +179,7 @@ const VisionPage = () => { {t("page-roadmap-vision-upgrade-needs-desc")} {t("page-roadmap-vision-upgrade-needs-desc-2")} {t("page-roadmap-vision-upgrade-needs-desc-3")} - + {t("page-roadmap-vision-2022")} diff --git a/src/pages/run-a-node.tsx b/src/pages/[locale]/run-a-node.tsx similarity index 97% rename from src/pages/run-a-node.tsx rename to src/pages/[locale]/run-a-node.tsx index efa18aebd8c..d375ef613bc 100644 --- a/src/pages/run-a-node.tsx +++ b/src/pages/[locale]/run-a-node.tsx @@ -1,11 +1,9 @@ import { HTMLAttributes } from "react" import type { GetStaticProps } from "next/types" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import type { ReactNode } from "react" import { FaDiscord } from "react-icons/fa" -import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types" +import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types" import Emoji from "@/components/Emoji" import ExpandableCard from "@/components/ExpandableCard" @@ -21,7 +19,7 @@ import { SovereigntyGlyphIcon, VoteGlyphIcon, } from "@/components/icons/run-a-node" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageHero from "@/components/PageHero" import PageMetadata from "@/components/PageMetadata" @@ -38,6 +36,10 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import { InfoGrid } from "@/layouts/md/Staking" import community from "@/public/images/enterprise-eth.png" import hackathon from "@/public/images/hackathon_transparent.png" @@ -209,7 +211,16 @@ type RunANodeCard = { alt: string } -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage("/run-a-node") const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) @@ -220,14 +231,16 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const RunANodePage = () => { const { t } = useTranslation("page-run-a-node") @@ -343,7 +356,7 @@ const RunANodePage = () => { {t("page-run-a-node-what-3-text")} - { )} > - { - { - ( REVALIDATE_TIME * 1000 ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -174,16 +183,18 @@ export const getStaticProps = (async ({ locale }) => { marketsHasError = true } + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, markets, marketsHasError, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const Content = (props: BaseHTMLAttributes) => (
@@ -498,7 +509,7 @@ const StablecoinsPage = ({ markets, marketsHasError }) => {
- {
- ( ) const CardTitle = (props: ChildOnlyProp) => ( - +

) const Caption = (props: ChildOnlyProp) => ( @@ -142,7 +137,7 @@ const Caption = (props: ChildOnlyProp) => ( ) const Blockie = (props: { src: string }) => ( - { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const requiredNamespaces = getRequiredNamespacesForPage( "/staking/deposit-contract" ) @@ -176,17 +180,19 @@ export const getStaticProps = (async ({ locale }) => { lastDeployDate ) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const DepositContractPage = () => { - const { asPath } = useRouter() + const pathname = usePathname() const { t } = useTranslation("page-staking-deposit-contract") @@ -303,7 +309,7 @@ const DepositContractPage = () => { description={t("page-staking-deposit-contract-meta-desc")} /> - + {t("page-staking-deposit-contract-title")} {t("page-staking-deposit-contract-subtitle")}

{t("page-staking-deposit-contract-h2")}

diff --git a/src/pages/staking/index.tsx b/src/pages/[locale]/staking/index.tsx similarity index 97% rename from src/pages/staking/index.tsx rename to src/pages/[locale]/staking/index.tsx index 56febfc38c1..d54b0d2439a 100644 --- a/src/pages/staking/index.tsx +++ b/src/pages/[locale]/staking/index.tsx @@ -1,7 +1,5 @@ import { type HTMLAttributes, ReactNode } from "react" import { GetStaticProps, InferGetStaticPropsType } from "next" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" import type { BasePageProps, @@ -9,6 +7,7 @@ import type { EpochResponse, EthStoreResponse, Lang, + Params, StakingStatsData, } from "@/lib/types" @@ -41,8 +40,10 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate" import { getLocaleTimestamp } from "@/lib/utils/time" import { getRequiredNamespacesForPage } from "@/lib/utils/translations" -import { BASE_TIME_UNIT } from "@/lib/constants" +import { BASE_TIME_UNIT, DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" +import useTranslation from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" import rhino from "@/public/images/upgrades/upgrade_rhino.png" type BenefitsType = { @@ -156,7 +157,16 @@ const loadData = dataLoader( REVALIDATE_TIME * 1000 ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -169,15 +179,17 @@ export const getStaticProps = (async ({ locale }) => { const [data] = await loadData() + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, data, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const StakingPage = ({ data, diff --git a/src/pages/wallets/find-wallet.tsx b/src/pages/[locale]/wallets/find-wallet.tsx similarity index 82% rename from src/pages/wallets/find-wallet.tsx rename to src/pages/[locale]/wallets/find-wallet.tsx index 771d730db3d..622b8ccc09d 100644 --- a/src/pages/wallets/find-wallet.tsx +++ b/src/pages/[locale]/wallets/find-wallet.tsx @@ -1,14 +1,17 @@ import { GetStaticProps, InferGetStaticPropsType } from "next" -import { useRouter } from "next/router" -import { useTranslation } from "next-i18next" -import { serverSideTranslations } from "next-i18next/serverSideTranslations" -import type { BasePageProps, ChildOnlyProp, Lang, Wallet } from "@/lib/types" +import type { + BasePageProps, + ChildOnlyProp, + Lang, + Params, + Wallet, +} from "@/lib/types" import BannerNotification from "@/components/Banners/BannerNotification" import Breadcrumbs from "@/components/Breadcrumbs" import FindWalletProductTable from "@/components/FindWalletProductTable" -import { TwImage } from "@/components/Image" +import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import PageMetadata from "@/components/PageMetadata" import InlineLink from "@/components/ui/Link" @@ -24,6 +27,11 @@ import { getSupportedLocaleWallets, } from "@/lib/utils/wallets" +import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants" + +import { useTranslation } from "@/hooks/useTranslation" +import loadNamespaces from "@/i18n/loadNamespaces" +import { usePathname } from "@/i18n/routing" import HeroImage from "@/public/images/wallets/wallet-hero.png" const Subtitle = ({ children }: ChildOnlyProp) => ( @@ -36,7 +44,16 @@ type Props = BasePageProps & { wallets: Wallet[] } -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -61,20 +78,22 @@ export const getStaticProps = (async ({ locale }) => { ), })) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, wallets, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const FindWalletPage = ({ wallets, }: InferGetStaticPropsType) => { - const { pathname } = useRouter() + const pathname = usePathname() const { t } = useTranslation("page-wallets-find-wallet") return ( @@ -109,7 +128,7 @@ const FindWalletPage = ({

- ) => ( /> ) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const lastDeployDate = getLastDeployDate() const lastDeployLocaleTimestamp = getLocaleTimestamp( locale as Lang, @@ -52,17 +63,19 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const messages = await loadNamespaces(locale!, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const WalletsPage = () => { - const { locale } = useRouter() + const locale = useLocale() const { t } = useTranslation("page-wallets") const heroContent = { @@ -331,7 +344,7 @@ const WalletsPage = () => { > {t("page-wallets-find-wallet-btn")} - ( ) const Image400 = ({ src }: Pick) => ( - + ) type Props = BasePageProps & { @@ -178,7 +181,16 @@ type Props = BasePageProps & { const loadData = dataLoader([["growThePieData", fetchGrowThePie]]) -export const getStaticProps = (async ({ locale }) => { +export async function getStaticPaths() { + return { + paths: LOCALES_CODES.map((locale) => ({ params: { locale } })), + fallback: false, + } +} + +export const getStaticProps = (async ({ params }) => { + const { locale = DEFAULT_LOCALE } = params || {} + const [data] = await loadData() const lastDeployDate = getLastDeployDate() @@ -191,22 +203,24 @@ export const getStaticProps = (async ({ locale }) => { const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2]) + const messages = await loadNamespaces(locale, requiredNamespaces) + return { props: { - ...(await serverSideTranslations(locale!, requiredNamespaces)), + messages, contentNotTranslated, lastDeployLocaleTimestamp, data: data.txCount, }, } -}) satisfies GetStaticProps +}) satisfies GetStaticProps const WhatIsEthereumPage = ({ data, }: InferGetStaticPropsType) => { const { t } = useTranslation(["page-what-is-ethereum", "learn-quizzes"]) - const { locale } = useRouter() + const locale = useLocale() const localeForNumberFormat = getLocaleForNumberFormat(locale! as Lang) const formatNumber = ( @@ -331,7 +345,7 @@ const WhatIsEthereumPage = ({ - { + const router = useRouter() + useEffect(() => { if (!process.env.IS_PREVIEW_DEPLOY) { init({ @@ -26,18 +31,31 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => { const getLayout = Component.getLayout ?? ((page) => page) return ( - - - - {getLayout()} - - - + { + // Suppress errors by default, enable if needed to debug + // console.error(error) + }} + getMessageFallback={({ key }) => { + const keyOnly = key.split(".").pop() + return keyOnly || key + }} + > + + + + {getLayout()} + + + + ) } -export default appWithTranslation(App) +export default App diff --git a/src/pages/api/revalidate.ts b/src/pages/api/revalidate.ts index 1d1451dfd6a..d7d39309a00 100644 --- a/src/pages/api/revalidate.ts +++ b/src/pages/api/revalidate.ts @@ -10,7 +10,7 @@ export default async function handler( return res.status(401).json({ message: "Invalid secret" }) } - const BUILD_LOCALES = process.env.BUILD_LOCALES + const BUILD_LOCALES = process.env.NEXT_PUBLIC_BUILD_LOCALES // Supported locales defined in `i18n.config.json` const locales = BUILD_LOCALES ? BUILD_LOCALES.split(",") diff --git a/src/scripts/crowdin-import.ts b/src/scripts/crowdin-import.ts index fa8f7dbc70b..4e4914a5005 100644 --- a/src/scripts/crowdin-import.ts +++ b/src/scripts/crowdin-import.ts @@ -407,7 +407,7 @@ const langsSummary: string = summary.reduce( log("Empty buckets:", trackers.emptyBuckets) if (summary.length) { console.table(summary) - console.log("Langs to test:", `\nBUILD_LOCALES=en${langsSummary}`) + console.log("Langs to test:", `\nNEXT_PUBLIC_BUILD_LOCALES=en${langsSummary}`) console.log("🎉 Crowdin import complete.") } else { console.warn("Nothing imported, see instruction at top of crowdin-imports.ts") diff --git a/src/styled.d.ts b/src/styled.d.ts deleted file mode 100644 index 53b790d4761..00000000000 --- a/src/styled.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -// import original module declarations -import "@emotion/react" - -// and extend them! -declare module "@emotion/react" { - export interface Theme { - // TODO: to be defined better when we implement a UI lib - isDark: boolean - colors: unknown - fonts: { - monospace: string - } - fontSizes: { - xs: string - s: string - m: string - r: string - l: string - xl: string - } - breakpoints: { - xs: string - s: string - m: string - l: string - xl: string - } - variables: { - maxPageWidth: string - navHeight: string - navBannerHeightDesktop: string - navBannerHeightTablet: string - navBannerHeightMobile: string - navSubNavHeightDesktop: string - navSideNavHeightMobile: string - } - } -} diff --git a/src/styles/colors.stories.tsx b/src/styles/colors.stories.tsx new file mode 100644 index 00000000000..4af728227c7 --- /dev/null +++ b/src/styles/colors.stories.tsx @@ -0,0 +1,149 @@ +import { type ReactNode } from "react" +import capitalize from "lodash/capitalize" +import type { Meta, StoryObj } from "@storybook/react" + +import { HStack, Stack, VStack } from "@/components/ui/flex" + +import { cn } from "@/lib/utils/cn" + +const meta = { + title: "Design System / Colors", + parameters: { + // Do not create snapshots for any stories in the file. + chromatic: { disableSnapshot: true }, + }, +} satisfies Meta + +export default meta + +/** + * Get all CSS Variables in the document. + * + * Used to search CSS Variables and retrieve their values. + * + * NOTE: Function created with AI assistance + */ +const getCSSCustomPropIndex = () => { + const rootStyles = document.styleSheets + const variables = {} + + for (const sheet of rootStyles) { + for (const rule of sheet.cssRules) { + // Check for CSSStyleRule type as `selectorText` might not always be available + if (rule instanceof CSSStyleRule && rule.selectorText === ":root") { + for (const style of rule.style) { + if (style.startsWith("--")) { + variables[style] = rule.style.getPropertyValue(style).trim() + } + } + } + } + } + return variables as Record +} + +const cssVarsEntries = Object.entries(getCSSCustomPropIndex()) + +const primitiveColorKeys = ["gray", "purple"] as const +export const Primitives: StoryObj = { + render: () => { + return ( + + {primitiveColorKeys.map((color) => ( + + + {cssVarsEntries + .filter(([key]) => key.startsWith(`--${color}`)) + .map(([tokenKey, value]) => ( + +
+
+
+ + {value} + {tokenKey} + + + ))} + + + ))} + + ) + }, +} + +const ColorGroupWrapper = ({ + color, + children, +}: { + color: (typeof primitiveColorKeys)[number] + children: ReactNode +}) => ( +
+ {children} +
+) + +export const SemanticScheme: StoryObj = { + render: () => { + const tokenNames = [ + "primary", + "body", + "background", + "disabled", + "success", + "warning", + "error", + ] as const + + return ( + + {tokenNames.map((tokenName) => { + const variableObj = cssVarsEntries.filter(([key]) => + key.startsWith(`--${tokenName}`) + ) + + return ( + +

{capitalize(tokenName)}

+ + {variableObj.map((variable) => ( + + ))} + +
+ ) + })} +
+ ) + }, +} + +const SemanticColorBlock = ({ + variable: [varName, varValue], +}: { + variable: [string, string] +}) => ( + +
+ {varName} + +) diff --git a/src/styles/docsearch.css b/src/styles/docsearch.css index 05611fbea1c..e96791ab3cf 100644 --- a/src/styles/docsearch.css +++ b/src/styles/docsearch.css @@ -39,7 +39,7 @@ --docsearch-hit-height: fit-content; } -[data-theme="dark"] { +.dark { --docsearch-modal-background: theme(backgroundColor.background.DEFAULT); --docsearch-highlight-color: theme(colors.primary.hover); } diff --git a/src/styles/global.css b/src/styles/global.css index 8980eece024..2898047b069 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -50,7 +50,7 @@ ); } - [data-theme="dark"] { + .dark { /* Misc semantics: dark mode */ --tooltip-shadow: rgba(255, 255, 255, 0.24); --switch-background: rgba(255, 255, 255, 0.24); @@ -80,8 +80,12 @@ } @layer base { + * { + @apply border-border; + } + body { - @apply !bg-background font-body !text-body; + @apply bg-background font-body leading-base text-body; } a { diff --git a/src/styles/semantic-tokens.css b/src/styles/semantic-tokens.css index d9fc6459cc0..08716c5735b 100644 --- a/src/styles/semantic-tokens.css +++ b/src/styles/semantic-tokens.css @@ -129,7 +129,7 @@ } /* Dark mode token declarations */ - [data-theme="dark"] { + .dark { --body: var(--gray-100); --body-medium: var(--gray-400); --body-light: var(--gray-600); diff --git a/src/theme.ts b/src/theme.ts deleted file mode 100644 index eea69f281a6..00000000000 --- a/src/theme.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { mix } from "polished" - -const white = "#ffffff" -const black = "#000000" -const primaryLight = "#1c1cff" -const primaryDark = "#ff7324" -const success = "#109e62" -const fail = "#b80000" -const turquoise = "#ccfcff" -const turquoiseDark = "#293233" -const yellow = "#fff8df" -const mint = "#e1fefa" -const mintDark = "#2d3332" -const codeBoxDark = "#2a2734" -const codeBoxLight = "#fafafa" - -// purple and orangeDark introduced for dark mode alts for homepage boxes -const purpleDark = "#212131" -const orangeDark = "#332821" -const pink = "#ffe5f9" -const pinkDark = "#332027" -const gridYellow = "#ffe78e" -const gridRed = "#ef7d7d" -const gridBlue = "#a7d0f4" -const gridPink = "#ffa1c3" - -const white500 = white -const white600 = mix(0.03, black, white) -const white700 = mix(0.1, black, white) -const white800 = mix(0.2, black, white) -const white900 = mix(0.3, black, white) - -const black50 = mix(0.5, white, black) -const black100 = mix(0.4, white, black) -const black200 = mix(0.3, white, black) -const black300 = mix(0.2, white, black) -const black400 = mix(0.1, white, black) -const black500 = black - -const primaryLight950 = mix(0.85, black, primaryLight) -const primaryLight900 = mix(0.8, black, primaryLight) -const primaryLight800 = mix(0.6, black, primaryLight) -const primaryLight700 = mix(0.4, black, primaryLight) -const primaryLight600 = mix(0.2, black, primaryLight) -const primaryLight500 = primaryLight -const primaryLight400 = mix(0.2, white, primaryLight) -const primaryLight300 = mix(0.4, white, primaryLight) -const primaryLight200 = mix(0.6, white, primaryLight) -const primaryLight100 = mix(0.8, white, primaryLight) -const primaryLight50 = mix(0.9, white, primaryLight) - -const primaryDark950 = mix(0.9, black, primaryDark) -const primaryDark900 = mix(0.8, black, primaryDark) -const primaryDark800 = mix(0.6, black, primaryDark) -const primaryDark700 = mix(0.4, black, primaryDark) -const primaryDark600 = mix(0.2, black, primaryDark) -const primaryDark500 = primaryDark -const primaryDark400 = mix(0.2, white, primaryDark) -const primaryDark300 = mix(0.4, white, primaryDark) -const primaryDark200 = mix(0.6, white, primaryDark) -const primaryDark100 = mix(0.8, white, primaryDark) - -const success900 = mix(0.8, black, success) -const success800 = mix(0.6, black, success) -const success700 = mix(0.4, black, success) -const success600 = mix(0.2, black, success) -const success500 = success -const success400 = mix(0.2, white, success) -const success300 = mix(0.4, white, success) -const success200 = mix(0.6, white, success) -const success100 = mix(0.8, white, success) - -const fail900 = mix(0.8, black, fail) -const fail800 = mix(0.6, black, fail) -const fail700 = mix(0.4, black, fail) -const fail600 = mix(0.2, black, fail) -const fail500 = fail -const fail400 = mix(0.2, white, fail) -const fail300 = mix(0.4, white, fail) -const fail200 = mix(0.6, white, fail) -const fail100 = mix(0.8, white, fail) - -const baseColors = { - white, - white500, - white600, - white700, - white800, - white900, - black, - black500, - black400, - black300, - black200, - black100, - black50, - boxShadow: "rgba(0,0,0,0.12)", - boxShadowHover: "rgba(0,0,0,0.24)", - secondary: "#b2b2b2", // TODO replace - success900, - success800, - success700, - success600, - success, - success500, - success400, - success300, - success200, - success100, - fail900, - fail800, - fail700, - fail600, - fail, - fail500, - fail400, - fail300, - fail200, - fail100, - tagBlue: primaryLight100, - tagOrange: primaryDark100, - tagGreen: success100, - tagRed: fail100, - tagTurquoise: turquoise, - tagGray: white700, - tagYellow: yellow, - tagMint: mint, - tagPink: pink, - warning: primaryDark100, - warningLink: primaryDark700, - warningLinkHover: primaryDark900, - lowBug: primaryDark100, - mediumBug: primaryDark300, - primaryLight300, - primaryDark300, - yellow, - gridYellow, - gridRed, - gridBlue, - gridGreen: success300, - gridOrange: primaryDark300, - gridPink, - gridPurple: primaryLight200, - infoBanner: primaryLight50, -} - -// TODO replace random variables w/ baseColor variables -const lightColors = { - buttonColor: white, - ghostCardBackground: white, - ghostCardGhost: white600, - secondaryButtonBackgroundActive: white700, - primary: primaryLight, - primary950: primaryLight950, - primary900: primaryLight900, - primary800: primaryLight800, - primary700: primaryLight700, - primary600: primaryLight600, - primary500: primaryLight500, - primary400: primaryLight400, - primary300: primaryLight300, - primary200: primaryLight200, - primary100: primaryLight100, - primaryHover: "rgba(28, 28, 225, 0.8)", - primaryActive: primaryLight600, - lightBorder: "#ececec", - searchBorder: "#7f7f7f", - searchBackground: white, - searchBackgroundEmpty: "#f2f2f2", - searchResultText: "#33363d", - searchResultBackground: "#f1f3f5", - selectHover: primaryLight100, - selectActive: primaryLight200, - dropdownBackground: white, - dropdownBackgroundHover: "#f2f2f2", - dropdownBorder: "#e5e5e5", - markBackground: "rgba(143,187,237,.1)", - markUnderline: "rgba(143,187,237,.5)", - modalBackground: "hsla(0, 0%, 69.8%, 0.9)", - text: "#333333", - text200: "#666666", - text300: "#4c4c4c", - textTableOfContents: "#7f7f7f", - background: white, - ednBackground: white600, - layer2ContentSecondary: white700, - border: white700, - tableBoxShadow: - "0 14px 66px rgba(0,0,0,.07), 0 10px 17px rgba(0,0,0,.03), 0 4px 7px rgba(0,0,0,.05)", - tableItemBoxShadow: "rgba(0, 0, 0, 0.1)", - tableBackgroundHover: "#f2f2f2", - preBackground: "#f2f2f2", - preBorder: "rgba(0,0,0,.05)", - homeDivider: "#a4a4f3", - displayDark: "none", - displayLight: "block", - grayBackground: "#fcfcfc", - cardGradient: - // Migrate to: "bg-gradient-to-r from-accent-a/10 to-accent-c/10" - "radial-gradient(46.28% 66.31% at 66.95% 58.35%, #e6e6f7 0%, #e7edfa 50%, #e9fbfa 100%)", - warning: primaryDark100, - warningLink: primaryDark700, - warningLinkHover: primaryDark900, - tagMint: mint, - mainnet: success200, - mainnetBorder: black50, - beaconchain: turquoise, - beaconchainBorder: black50, - shard: primaryDark100, - shardBorder: black50, - infoLink: primaryLight800, - infoLinkHover: primaryLight900, - cardBoxShadow: "4px 4px 0px 0px #d2d2f9", - homeBoxMint: mint, - homeBoxTurquoise: turquoise, - homeBoxOrange: primaryDark100, - homeBoxPurple: primaryLight50, - homeBoxPink: pink, - codeBackground: codeBoxLight, - rollupDevDocList: primaryLight50, - beta: "radial-gradient(25.56% 133.51% at 28.36% 45.54%, rgba(28, 28, 225, 0) 0%, rgba(28, 28, 225, 0.06) 100%)", - offBackground: "#f7f7f7", - stakingPillPlatform: "#cd9df3", - stakingPillUI: "#ebd27a", - stakingGold: "#be8d10", - stakingGoldFill: "#fef9ef", - stakingGreen: "#129e5b", - stakingGreenFill: "#f7faf1", - stakingBlue: "#0b83dc", - stakingBlueFill: "#f1fcf5", - stakingRed: "#a0524c", - stakingRedFill: "#f8fbf9", - feedbackGradient: - "linear-gradient(102.7deg, rgba(185, 185, 241, 0.2) 0%, rgba(84, 132, 234, 0.2) 51.56%, rgba(58, 142, 137, 0.2) 100%)", - bannerGridGradient: - "linear-gradient(90deg, rgba(127,127,213,0.2) 0%, rgba(132,145,221,0.2) 50%, rgba(145,234,228,0.2) 100%)", - sliderBg: "#F7F7F7", - sliderBorder: "#ECECEC", - sliderDot: "#A4A4A4", - sliderDotActive: "#1C1DFF", - sliderBtnBg: "#A4A4A4", - sliderBtnColor: white, - sliderBtnBgDisabled: "#E7E7E7", - sliderBtnColorDisabled: "#737373", -} - -// TODO replace random variables w/ baseColor variables -const darkColors = { - buttonColor: black300, - primaryHover: primaryDark400, - primaryActive: primaryDark200, - ghostCardBackground: black300, - ghostCardGhost: black50, - secondaryButtonBackgroundActive: black300, - primary: primaryDark, - primary950: primaryDark950, - primary900: primaryDark900, - primary800: primaryDark800, - primary700: primaryDark700, - primary600: primaryDark600, - primary500: primaryDark500, - primary400: primaryDark400, - primary300: primaryDark300, - primary200: primaryDark200, - primary100: primaryDark100, - lightBorder: "#404040", - searchBorder: "#b2b2b2", - searchBackground: "#4c4c4c", - searchBackgroundEmpty: "#333333", - searchResultText: "#f1f3f5", - searchResultBackground: "#33363d", - selectHover: primaryDark700, - selectActive: primaryDark600, - dropdownBackground: "#191919", - dropdownBackgroundHover: "#000000", - dropdownBorder: "#333333", - markBackground: "rgb(255, 115, 36, .1)", - markUnderline: "rgb(255, 115, 36, .5)", - modalBackground: "rgba(25,25,25,0.8)", - text: "#f2f2f2", - text200: "#b2b2b2", - text300: "#cccccc", - textTableOfContents: "hsla(0,0%,69.8%,.8)", - background: "#222222", - ednBackground: black400, - layer2ContentSecondary: black300, - border: black300, - tableBoxShadow: - "0 14px 66px hsla(0,0%,96.1%,.07), 0 10px 17px hsla(0,0%,96.1%,.03), 0 4px 7px hsla(0,0%,96.1%,.05)", - tableItemBoxShadow: "hsla(0,0%,100%,.1)", - tableBackgroundHover: "rgba(255,115,36,.013)", - preBackground: "#191919", - preBorder: "hsla(0,0%,100%,.05)", - homeDivider: "#ffc7a7", - displayDark: "block", - displayLight: "none", - grayBackground: "#272627", - warning: primaryDark100, - warningLink: primaryDark700, - warningLinkHover: primaryDark900, - tagMint: mint, - mainnet: "#222222", - mainnetBorder: success300, - beaconchain: "#222222", - beaconchainBorder: pink, - shard: "#222222", - shardBorder: primaryDark500, - infoLink: primaryLight800, - infoLinkHover: primaryLight900, - cardBoxShadow: "4px 4px 0px 0px #ffab7c", - homeBoxMint: mintDark, - homeBoxTurquoise: turquoiseDark, - homeBoxOrange: orangeDark, - homeBoxPurple: purpleDark, - homeBoxPink: pinkDark, - codeBackground: codeBoxDark, - rollupDevDocList: "#4c4c4c", - beta: "background: radial-gradient(25.56% 133.51% at 28.36% 45.54%, rgba(255, 143, 80, 0.72) 0%, rgba(255, 143, 80, 0.22) 100%)", - cardGradient: - // Migrate to: "dark:bg-gradient-to-tr dark:from-primary/20 dark:from-20% dark:via-accent-a/20 dark:via-60% dark:to-accent-c/20 dark:to-95%" - "linear-gradient(49.21deg, rgba(127, 127, 213, 0.2) 19.87%, rgba(134, 168, 231, 0.2) 58.46%, rgba(145, 234, 228, 0.2) 97.05% )", - offBackground: "#181818", - stakingPillPlatform: "#cd9df3", - stakingPillUI: "#ebd27a", - stakingGold: "#F2BB2F", - stakingGoldFill: "#373228", - stakingGreen: "#49DE96", - stakingGreenFill: "#30342b", - stakingBlue: "#A9D3F2", - stakingBlueFill: "#2b352f", - stakingRed: "#D6BBB9", - stakingRedFill: "#313432", - feedbackGradient: - "linear-gradient(83.46deg, #2C2C32 7.03%, #44404D 52.42%, #303038 98.77%)", - bannerGridGradient: - "linear-gradient(90deg, rgba(172, 182, 229, 0.08) 0%, rgba(134, 253, 232, 0.08) 100%)", - sliderBg: "#191919", - sliderBorder: "#404040", - sliderDot: "#A4A4A4", - sliderDotActive: "#FF7324", - sliderBtnBg: "#404040", - sliderBtnColor: white, - sliderBtnBgDisabled: "#404040", - sliderBtnColorDisabled: "#737373", -} - -const lightThemeColors = Object.assign({}, baseColors, lightColors) -const darkThemeColors = Object.assign({}, baseColors, darkColors) - -const theme = { - isDark: false, // Overwritten in Object.assign - colors: {}, // Overwritten in Object.assign - fonts: { - monospace: - '"SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", "Liberation Mono", Menlo, Courier, monospace', - }, - fontSizes: { - // based on typical browser default font size of 16px - xs: "0.75rem", // 12px - s: "0.875rem", // 14px - m: "1rem", // 16px - r: "1.125rem", // 18px - l: "1.5rem", // 24px - xl: "2rem", // 32px - }, - breakpoints: { - xs: "320px", - s: "414px", - m: "768px", - l: "1024px", - xl: "1440px", // Used as the max-width - }, - variables: { - maxPageWidth: "1504px", // xl breakpoint (1440px) + 72px (2rem padding on each side) - navHeight: "4.75rem", - navBannerHeightDesktop: "134px", // 76px + 58px - navBannerHeightTablet: "159px", // 76px + 83px - navBannerHeightMobile: "184px", // 76px + 108px - navSubNavHeightDesktop: "134px", // 76px + 58px - navSideNavHeightMobile: "140px", // 76px + 64px - }, -} - -export const lightTheme = Object.assign( - {}, - theme, - { isDark: false }, - { colors: lightThemeColors } -) -export const darkTheme = Object.assign( - {}, - theme, - { isDark: true }, - { colors: darkThemeColors } -) diff --git a/tailwind.config.ts b/tailwind.config.ts index 2e1d469783d..c37ae34ff39 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -4,13 +4,8 @@ import plugin from "tailwindcss/plugin" import { screens } from "./src/lib/utils/screen" const config = { - // TODO: Move to "class" strategy after removing Chakra - darkMode: ["selector", '[data-theme="dark"]'], - content: [ - "./src/**/*.{ts,tsx}", - // TODO: remove after migration - "./tailwind/**/*.tsx", - ], + darkMode: ["selector"], + content: ["./src/**/*.{ts,tsx}"], prefix: "", theme: { extend: { diff --git a/tsconfig.json b/tsconfig.json index 0e0e5ce843e..1b936f73573 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,6 +21,6 @@ "@/storybook-utils": ["./.storybook/utils.ts"] } }, - "include": ["./src/**/*", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".storybook/**/*", "tailwind/ui"], + "include": ["./src/**/*", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".storybook/**/*"], "exclude": ["node_modules", "./public", "./src/intl"] } diff --git a/yarn.lock b/yarn.lock index 332198cde67..e05129da599 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2093,7 +2093,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== @@ -2187,825 +2187,6 @@ resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" integrity sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA== -"@chakra-ui/accordion@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-2.3.1.tgz#a326509e286a5c4e8478de9bc2b4b05017039e6b" - integrity sha512-FSXRm8iClFyU+gVaXisOSEw0/4Q+qZbFRiuhIAkVU6Boj0FxAMrlo9a8AV5TuF77rgaHytCdHk0Ng+cyUijrag== - dependencies: - "@chakra-ui/descendant" "3.1.0" - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.1.0" - -"@chakra-ui/alert@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-2.2.2.tgz#aeba951d120c7c6e69d5f515a695ad6e4db43ffe" - integrity sha512-jHg4LYMRNOJH830ViLuicjb3F+v6iriE/2G5T+Sd0Hna04nukNJ1MxUmBPE+vI22me2dIflfelu2v9wdB6Pojw== - dependencies: - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/spinner" "2.1.0" - -"@chakra-ui/anatomy@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.2.2.tgz#2d0e14cba2534d92077ca28abf8c183b6e27897b" - integrity sha512-MV6D4VLRIHr4PkW4zMyqfrNS1mPlCTiCXwvYGtDFQYr+xHFfonhAuf9WjsSc0nyp2m0OdkSLnzmVKkZFLo25Tg== - -"@chakra-ui/avatar@2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-2.3.0.tgz#f018a2714d1e3ba5970bcf66558887925fdfccf4" - integrity sha512-8gKSyLfygnaotbJbDMHDiJoF38OHXUYVme4gGxZ1fLnQEdPVEaIWfH+NndIjOM0z8S+YEFnT9KyGMUtvPrBk3g== - dependencies: - "@chakra-ui/image" "2.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/breadcrumb@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-2.2.0.tgz#751bc48498f3c403f97b5d9aae528ebfd405ef48" - integrity sha512-4cWCG24flYBxjruRi4RJREWTGF74L/KzI2CognAW/d/zWR0CjiScuJhf37Am3LFbCySP6WSoyBOtTIoTA4yLEA== - dependencies: - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/breakpoint-utils@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.8.tgz#750d3712668b69f6e8917b45915cee0e08688eed" - integrity sha512-Pq32MlEX9fwb5j5xx8s18zJMARNHlQZH2VH1RZgfgRDpp7DcEgtRW5AInfN5CfqdHLO1dGxA7I3MqEuL5JnIsA== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/button@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-2.1.0.tgz#623ed32cc92fc8e52492923e9924791fc6f25447" - integrity sha512-95CplwlRKmmUXkdEp/21VkEWgnwcx2TOBG6NfYlsuLBDHSLlo5FKIiE2oSi4zXc4TLcopGcWPNcm/NDaSC5pvA== - dependencies: - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/spinner" "2.1.0" - -"@chakra-ui/card@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/card/-/card-2.2.0.tgz#b5e59dc51c171fced76ea76bf26088803b8bc184" - integrity sha512-xUB/k5MURj4CtPAhdSoXZidUbm8j3hci9vnc+eZJVDqhDOShNlD6QeniQNRPRys4lWAQLCbFcrwL29C8naDi6g== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/checkbox@2.3.2": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-2.3.2.tgz#4ecb14a2f57b7470d1a58542ca4691c3b105bfa1" - integrity sha512-85g38JIXMEv6M+AcyIGLh7igNtfpAN6KGQFYxY9tBj0eWvWk4NKQxvqqyVta0bSAyIl1rixNIIezNpNWk2iO4g== - dependencies: - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/visually-hidden" "2.2.0" - "@zag-js/focus-visible" "0.16.0" - -"@chakra-ui/cli@^2.4.1": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/cli/-/cli-2.4.1.tgz#254a0f229a38c2ba235e2a7cc24c6c20deee8117" - integrity sha512-GZZuHUA1cXJWpmYNiVTLPihvY4VhIssRl+AXgw/0IbeodTMop3jWlIioPKLAQeXu5CwvRA6iESyGjnu1V8Zykg== - dependencies: - chokidar "^3.5.3" - cli-check-node "^1.3.4" - cli-handle-unhandled "^1.1.1" - cli-welcome "^2.2.2" - commander "^9.3.0" - esbuild "^0.17.18" - prettier "^2.8.8" - -"@chakra-ui/clickable@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-2.1.0.tgz#800fa8d10cf45a41fc50a3df32c679a3ce1921c3" - integrity sha512-flRA/ClPUGPYabu+/GLREZVZr9j2uyyazCAUHAdrTUEdDYCr31SVGhgh7dgKdtq23bOvAQJpIJjw/0Bs0WvbXw== - dependencies: - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/close-button@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-2.1.1.tgz#995b245c56eb41465a71d8667840c238618a7b66" - integrity sha512-gnpENKOanKexswSVpVz7ojZEALl2x5qjLYNqSQGbxz+aP9sOXPfUS56ebyBrre7T7exuWGiFeRwnM0oVeGPaiw== - dependencies: - "@chakra-ui/icon" "3.2.0" - -"@chakra-ui/color-mode@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.2.0.tgz#828d47234c74ba2fb4c5dd63a63331aead20b9f6" - integrity sha512-niTEA8PALtMWRI9wJ4LL0CSBDo8NBfLNp4GD6/0hstcm3IlbBHTVKxN6HwSaoNYfphDQLxCjT4yG+0BJA5tFpg== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - -"@chakra-ui/control-box@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-2.1.0.tgz#0f4586797b3154c02463bc5c106782e70c88f04f" - integrity sha512-gVrRDyXFdMd8E7rulL0SKeoljkLQiPITFnsyMO8EFHNZ+AHt5wK4LIguYVEq88APqAGZGfHFWXr79RYrNiE3Mg== - -"@chakra-ui/counter@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-2.1.0.tgz#e413a2f1093a18f847bb7aa240117fde788a59e6" - integrity sha512-s6hZAEcWT5zzjNz2JIWUBzRubo9la/oof1W7EKZVVfPYHERnl5e16FmBC79Yfq8p09LQ+aqFKm/etYoJMMgghw== - dependencies: - "@chakra-ui/number-utils" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/css-reset@2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-2.3.0.tgz#83e3160a9c2a12431cad0ee27ebfbf3aedc5c9c7" - integrity sha512-cQwwBy5O0jzvl0K7PLTLgp8ijqLPKyuEMiDXwYzl95seD3AoeuoCLyzZcJtVqaUZ573PiBdAbY/IlZcwDOItWg== - -"@chakra-ui/descendant@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-3.1.0.tgz#f3b80ed13ffc4bf1d615b3ed5541bd0905375cca" - integrity sha512-VxCIAir08g5w27klLyi7PVo8BxhW4tgU/lxQyujkmi4zx7hT9ZdrcQLAted/dAa+aSIZ14S1oV0Q9lGjsAdxUQ== - dependencies: - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - -"@chakra-ui/dom-utils@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/dom-utils/-/dom-utils-2.1.0.tgz#d15df89e458ef19756db04c7cfd084eb552454f0" - integrity sha512-ZmF2qRa1QZ0CMLU8M1zCfmw29DmPNtfjR9iTo74U5FPr3i1aoAh7fbJ4qAlZ197Xw9eAW28tvzQuoVWeL5C7fQ== - -"@chakra-ui/editable@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-3.1.0.tgz#065783c2e3389c3bb9ab0582cb50d38e1dc00fa1" - integrity sha512-j2JLrUL9wgg4YA6jLlbU88370eCRyor7DZQD9lzpY95tSOXpTljeg3uF9eOmDnCs6fxp3zDWIfkgMm/ExhcGTg== - dependencies: - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-focus-on-pointer-down" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/event-utils@2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/event-utils/-/event-utils-2.0.8.tgz#e6439ba200825a2f15d8f1973d267d1c00a6d1b4" - integrity sha512-IGM/yGUHS+8TOQrZGpAKOJl/xGBrmRYJrmbHfUE7zrG3PpQyXvbLDP1M+RggkCFVgHlJi2wpYIf0QtQlU0XZfw== - -"@chakra-ui/focus-lock@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-2.1.0.tgz#580e5450fe85356987b9a246abaff8333369c667" - integrity sha512-EmGx4PhWGjm4dpjRqM4Aa+rCWBxP+Rq8Uc/nAVnD4YVqkEhBkrPTpui2lnjsuxqNaZ24fIAZ10cF1hlpemte/w== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - react-focus-lock "^2.9.4" - -"@chakra-ui/form-control@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-2.2.0.tgz#69c771d6406ddac8ab357ae88446cc11827656a4" - integrity sha512-wehLC1t4fafCVJ2RvJQT2jyqsAwX7KymmiGqBu7nQoQz8ApTkGABWpo/QwDh3F/dBLrouHDoOvGmYTqft3Mirw== - dependencies: - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/hooks@2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.2.1.tgz#b86ce5eeaaab877ddcb11a50842d1227306ace28" - integrity sha512-RQbTnzl6b1tBjbDPf9zGRo9rf/pQMholsOudTxjy4i9GfTfz6kgp5ValGjQm2z7ng6Z31N1cnjZ1AlSzQ//ZfQ== - dependencies: - "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/utils" "2.0.15" - compute-scroll-into-view "3.0.3" - copy-to-clipboard "3.3.3" - -"@chakra-ui/icon@3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-3.2.0.tgz#92b9454aa0d561b4994bcd6a1b3bb1fdd5c67bef" - integrity sha512-xxjGLvlX2Ys4H0iHrI16t74rG9EBcpFvJ3Y3B7KMQTrnW34Kf7Da/UC8J67Gtx85mTHW020ml85SVPKORWNNKQ== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/image@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-2.1.0.tgz#6c205f1ca148e3bf58345b0b5d4eb3d959eb9f87" - integrity sha512-bskumBYKLiLMySIWDGcz0+D9Th0jPvmX6xnRMs4o92tT3Od/bW26lahmV2a2Op2ItXeCmRMY+XxJH5Gy1i46VA== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/input@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-2.1.2.tgz#0cad49ec372f8f21f2f4f1db365f34b9a708ff9d" - integrity sha512-GiBbb3EqAA8Ph43yGa6Mc+kUPjh4Spmxp1Pkelr8qtudpc3p2PJOOebLpd90mcqw8UePPa+l6YhhPtp6o0irhw== - dependencies: - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/layout@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-2.3.1.tgz#0601c5eb91555d24a7015a7c9d4e01fed2698557" - integrity sha512-nXuZ6WRbq0WdgnRgLw+QuxWAHuhDtVX8ElWqcTK+cSMFg/52eVP47czYBE5F35YhnoW2XBwfNoNgZ7+e8Z01Rg== - dependencies: - "@chakra-ui/breakpoint-utils" "2.0.8" - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/lazy-utils@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/lazy-utils/-/lazy-utils-2.0.5.tgz#363c3fa1d421362790b416ffa595acb835e1ae5b" - integrity sha512-UULqw7FBvcckQk2n3iPO56TMJvDsNv0FKZI6PlUNJVaGsPbsYxK/8IQ60vZgaTVPtVcjY6BE+y6zg8u9HOqpyg== - -"@chakra-ui/live-region@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-2.1.0.tgz#02b4b1d997075f19a7a9a87187e08c72e82ef0dd" - integrity sha512-ZOxFXwtaLIsXjqnszYYrVuswBhnIHHP+XIgK1vC6DePKtyK590Wg+0J0slDwThUAd4MSSIUa/nNX84x1GMphWw== - -"@chakra-ui/media-query@3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-3.3.0.tgz#40f9151dedb6a7af9df3be0474b59a799c92c619" - integrity sha512-IsTGgFLoICVoPRp9ykOgqmdMotJG0CnPsKvGQeSFOB/dZfIujdVb14TYxDU4+MURXry1MhJ7LzZhv+Ml7cr8/g== - dependencies: - "@chakra-ui/breakpoint-utils" "2.0.8" - "@chakra-ui/react-env" "3.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/menu@2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-2.2.1.tgz#7d9810d435f6b40fa72ed867a33b88a1ef75073f" - integrity sha512-lJS7XEObzJxsOwWQh7yfG4H8FzFPRP5hVPN/CL+JzytEINCSBvsCDHrYPQGp7jzpCi8vnTqQQGQe0f8dwnXd2g== - dependencies: - "@chakra-ui/clickable" "2.1.0" - "@chakra-ui/descendant" "3.1.0" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/popper" "3.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-animation-state" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-disclosure" "2.1.0" - "@chakra-ui/react-use-focus-effect" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-outside-click" "2.2.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.1.0" - -"@chakra-ui/modal@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-2.3.1.tgz#524dc32b6b4f545b54ae531dbf6c74e1052ee794" - integrity sha512-TQv1ZaiJMZN+rR9DK0snx/OPwmtaGH1HbZtlYt4W4s6CzyK541fxLRTjIXfEzIGpvNW+b6VFuFjbcR78p4DEoQ== - dependencies: - "@chakra-ui/close-button" "2.1.1" - "@chakra-ui/focus-lock" "2.1.0" - "@chakra-ui/portal" "2.1.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/transition" "2.1.0" - aria-hidden "^1.2.3" - react-remove-scroll "^2.5.6" - -"@chakra-ui/number-input@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-2.1.2.tgz#dda9095fba6a4b89212332db02831b94120da163" - integrity sha512-pfOdX02sqUN0qC2ysuvgVDiws7xZ20XDIlcNhva55Jgm095xjm8eVdIBfNm3SFbSUNxyXvLTW/YQanX74tKmuA== - dependencies: - "@chakra-ui/counter" "2.1.0" - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.1.0" - "@chakra-ui/react-use-interval" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/number-utils@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-utils/-/number-utils-2.0.7.tgz#aaee979ca2fb1923a0373a91619473811315db11" - integrity sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg== - -"@chakra-ui/object-utils@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/object-utils/-/object-utils-2.1.0.tgz#a4ecf9cea92f1de09f5531f53ffdc41e0b19b6c3" - integrity sha512-tgIZOgLHaoti5PYGPTwK3t/cqtcycW0owaiOXoZOcpwwX/vlVb+H1jFsQyWiiwQVPt9RkoSLtxzXamx+aHH+bQ== - -"@chakra-ui/pin-input@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-2.1.0.tgz#61e6bbf909ec510634307b2861c4f1891a9f8d81" - integrity sha512-x4vBqLStDxJFMt+jdAHHS8jbh294O53CPQJoL4g228P513rHylV/uPscYUHrVJXRxsHfRztQO9k45jjTYaPRMw== - dependencies: - "@chakra-ui/descendant" "3.1.0" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/popover@2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-2.2.1.tgz#89cfd29817abcd204da570073c0f2b4d8072c3a3" - integrity sha512-K+2ai2dD0ljvJnlrzesCDT9mNzLifE3noGKZ3QwLqd/K34Ym1W/0aL1ERSynrcG78NKoXS54SdEzkhCZ4Gn/Zg== - dependencies: - "@chakra-ui/close-button" "2.1.1" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/popper" "3.1.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-animation-state" "2.1.0" - "@chakra-ui/react-use-disclosure" "2.1.0" - "@chakra-ui/react-use-focus-effect" "2.1.0" - "@chakra-ui/react-use-focus-on-pointer-down" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/popper@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-3.1.0.tgz#92a9180c6894763af3b22a6003f9a9d958fe2659" - integrity sha512-ciDdpdYbeFG7og6/6J8lkTFxsSvwTdMLFkpVylAF6VNC22jssiWfquj2eyD4rJnzkRFPvIWJq8hvbfhsm+AjSg== - dependencies: - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@popperjs/core" "^2.9.3" - -"@chakra-ui/portal@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-2.1.0.tgz#9e7f57424d7041738b6563cac80134561080bd27" - integrity sha512-9q9KWf6SArEcIq1gGofNcFPSWEyl+MfJjEUg/un1SMlQjaROOh3zYr+6JAwvcORiX7tyHosnmWC3d3wI2aPSQg== - dependencies: - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - -"@chakra-ui/progress@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-2.2.0.tgz#67444ea9779631d7c8395b2c9c78e5634f994999" - integrity sha512-qUXuKbuhN60EzDD9mHR7B67D7p/ZqNS2Aze4Pbl1qGGZfulPW0PY8Rof32qDtttDQBkzQIzFGE8d9QpAemToIQ== - dependencies: - "@chakra-ui/react-context" "2.1.0" - -"@chakra-ui/provider@2.4.2": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/provider/-/provider-2.4.2.tgz#92cb10b6a7df0720e3fa62716dc7cd872ae3ea3d" - integrity sha512-w0Tef5ZCJK1mlJorcSjItCSbyvVuqpvyWdxZiVQmE6fvSJR83wZof42ux0+sfWD+I7rHSfj+f9nzhNaEWClysw== - dependencies: - "@chakra-ui/css-reset" "2.3.0" - "@chakra-ui/portal" "2.1.0" - "@chakra-ui/react-env" "3.1.0" - "@chakra-ui/system" "2.6.2" - "@chakra-ui/utils" "2.0.15" - -"@chakra-ui/radio@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-2.1.2.tgz#66db19c61a2e628aaf5e727027f7c3b4006ea898" - integrity sha512-n10M46wJrMGbonaghvSRnZ9ToTv/q76Szz284gv4QUWvyljQACcGrXIONUnQ3BIwbOfkRqSk7Xl/JgZtVfll+w== - dependencies: - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@zag-js/focus-visible" "0.16.0" - -"@chakra-ui/react-children-utils@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-children-utils/-/react-children-utils-2.0.6.tgz#6c480c6a60678fcb75cb7d57107c7a79e5179b92" - integrity sha512-QVR2RC7QsOsbWwEnq9YduhpqSFnZGvjjGREV8ygKi8ADhXh93C8azLECCUVgRJF2Wc+So1fgxmjLcbZfY2VmBA== - -"@chakra-ui/react-context@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-context/-/react-context-2.1.0.tgz#4858be1d5ff1c8ac0a0ec088d93a3b7f1cbbff99" - integrity sha512-iahyStvzQ4AOwKwdPReLGfDesGG+vWJfEsn0X/NoGph/SkN+HXtv2sCfYFFR9k7bb+Kvc6YfpLlSuLvKMHi2+w== - -"@chakra-ui/react-env@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-3.1.0.tgz#7d3c1c05a501bb369524d9f3d38c9325eb16ab50" - integrity sha512-Vr96GV2LNBth3+IKzr/rq1IcnkXv+MLmwjQH6C8BRtn3sNskgDFD5vLkVXcEhagzZMCh8FR3V/bzZPojBOyNhw== - dependencies: - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - -"@chakra-ui/react-types@2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-types/-/react-types-2.0.7.tgz#799c166a44882b23059c8f510eac9bd5d0869ac4" - integrity sha512-12zv2qIZ8EHwiytggtGvo4iLT0APris7T0qaAWqzpUGS0cdUtR8W+V1BJ5Ocq+7tA6dzQ/7+w5hmXih61TuhWQ== - -"@chakra-ui/react-use-animation-state@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.1.0.tgz#eab661fbafd96804fe867b0df0c27e78feefe6e2" - integrity sha512-CFZkQU3gmDBwhqy0vC1ryf90BVHxVN8cTLpSyCpdmExUEtSEInSCGMydj2fvn7QXsz/za8JNdO2xxgJwxpLMtg== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.1.0" - -"@chakra-ui/react-use-callback-ref@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.1.0.tgz#a508085f4d9e7d84d4ceffdf5f41745c9ac451d7" - integrity sha512-efnJrBtGDa4YaxDzDE90EnKD3Vkh5a1t3w7PhnRQmsphLy3g2UieasoKTlT2Hn118TwDjIv5ZjHJW6HbzXA9wQ== - -"@chakra-ui/react-use-controllable-state@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.1.0.tgz#8fb6fa2f45d0c04173582ae8297e604ffdb9c7d9" - integrity sha512-QR/8fKNokxZUs4PfxjXuwl0fj/d71WPrmLJvEpCTkHjnzu7LnYvzoe2wB867IdooQJL0G1zBxl0Dq+6W1P3jpg== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-disclosure@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.1.0.tgz#90093eaf45db1bea7a6851dd0ce5cdb3eb66f90a" - integrity sha512-Ax4pmxA9LBGMyEZJhhUZobg9C0t3qFE4jVF1tGBsrLDcdBeLR9fwOogIPY9Hf0/wqSlAryAimICbr5hkpa5GSw== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-event-listener@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.1.0.tgz#afea2645bd9b38f754fc2b8eb858f9bb22385ded" - integrity sha512-U5greryDLS8ISP69DKDsYcsXRtAdnTQT+jjIlRYZ49K/XhUR/AqVZCK5BkR1spTDmO9H8SPhgeNKI70ODuDU/Q== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-focus-effect@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.1.0.tgz#963fb790370dfadd51d12666ff2da60706f53a2a" - integrity sha512-xzVboNy7J64xveLcxTIJ3jv+lUJKDwRM7Szwn9tNzUIPD94O3qwjV7DDCUzN2490nSYDF4OBMt/wuDBtaR3kUQ== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - -"@chakra-ui/react-use-focus-on-pointer-down@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.1.0.tgz#2fbcf6bc7d06d97606747e231a908d5c387ca0cc" - integrity sha512-2jzrUZ+aiCG/cfanrolsnSMDykCAbv9EK/4iUyZno6BYb3vziucmvgKuoXbMPAzWNtwUwtuMhkby8rc61Ue+Lg== - dependencies: - "@chakra-ui/react-use-event-listener" "2.1.0" - -"@chakra-ui/react-use-interval@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-interval/-/react-use-interval-2.1.0.tgz#2602c097b3ab74b6644812e4f5efaad621218d98" - integrity sha512-8iWj+I/+A0J08pgEXP1J1flcvhLBHkk0ln7ZvGIyXiEyM6XagOTJpwNhiu+Bmk59t3HoV/VyvyJTa+44sEApuw== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-latest-ref@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.1.0.tgz#d1e926130102566ece1d39f8a48ed125e0c8441a" - integrity sha512-m0kxuIYqoYB0va9Z2aW4xP/5b7BzlDeWwyXCH6QpT2PpW3/281L3hLCm1G0eOUcdVlayqrQqOeD6Mglq+5/xoQ== - -"@chakra-ui/react-use-merge-refs@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.1.0.tgz#c0c233527abdbea9a1348269c192012205762314" - integrity sha512-lERa6AWF1cjEtWSGjxWTaSMvneccnAVH4V4ozh8SYiN9fSPZLlSG3kNxfNzdFvMEhM7dnP60vynF7WjGdTgQbQ== - -"@chakra-ui/react-use-outside-click@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.2.0.tgz#5570b772a255f6f02b69e967127397c1b5fa3d3c" - integrity sha512-PNX+s/JEaMneijbgAM4iFL+f3m1ga9+6QK0E5Yh4s8KZJQ/bLwZzdhMz8J/+mL+XEXQ5J0N8ivZN28B82N1kNw== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-pan-event@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.1.0.tgz#51c21bc3c0e9e73d1faef5ea4f7e3c3d071a2758" - integrity sha512-xmL2qOHiXqfcj0q7ZK5s9UjTh4Gz0/gL9jcWPA6GVf+A0Od5imEDa/Vz+533yQKWiNSm1QGrIj0eJAokc7O4fg== - dependencies: - "@chakra-ui/event-utils" "2.0.8" - "@chakra-ui/react-use-latest-ref" "2.1.0" - framesync "6.1.2" - -"@chakra-ui/react-use-previous@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-previous/-/react-use-previous-2.1.0.tgz#f6046e6f7398b1e8d7e66ff7ebb8d61c92a2d3d0" - integrity sha512-pjxGwue1hX8AFcmjZ2XfrQtIJgqbTF3Qs1Dy3d1krC77dEsiCUbQ9GzOBfDc8pfd60DrB5N2tg5JyHbypqh0Sg== - -"@chakra-ui/react-use-safe-layout-effect@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.1.0.tgz#3a95f0ba6fd5d2d0aa14919160f2c825f13e686f" - integrity sha512-Knbrrx/bcPwVS1TorFdzrK/zWA8yuU/eaXDkNj24IrKoRlQrSBFarcgAEzlCHtzuhufP3OULPkELTzz91b0tCw== - -"@chakra-ui/react-use-size@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-size/-/react-use-size-2.1.0.tgz#fcf3070eaade8b4a84af8ce5341c4d5ca0a42bec" - integrity sha512-tbLqrQhbnqOjzTaMlYytp7wY8BW1JpL78iG7Ru1DlV4EWGiAmXFGvtnEt9HftU0NJ0aJyjgymkxfVGI55/1Z4A== - dependencies: - "@zag-js/element-size" "0.10.5" - -"@chakra-ui/react-use-timeout@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-timeout/-/react-use-timeout-2.1.0.tgz#24415f54267d7241a3c1d36a5cae4d472834cef7" - integrity sha512-cFN0sobKMM9hXUhyCofx3/Mjlzah6ADaEl/AXl5Y+GawB5rgedgAcu2ErAgarEkwvsKdP6c68CKjQ9dmTQlJxQ== - dependencies: - "@chakra-ui/react-use-callback-ref" "2.1.0" - -"@chakra-ui/react-use-update-effect@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.1.0.tgz#5c57cd1f50c2a6a8119e0f57f69510723d69884b" - integrity sha512-ND4Q23tETaR2Qd3zwCKYOOS1dfssojPLJMLvUtUbW5M9uW1ejYWgGUobeAiOVfSplownG8QYMmHTP86p/v0lbA== - -"@chakra-ui/react-utils@2.0.12": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.12.tgz#d6b773b9a5b2e51dce61f51ac8a0e9a0f534f479" - integrity sha512-GbSfVb283+YA3kA8w8xWmzbjNWk14uhNpntnipHCftBibl0lxtQ9YqMFQLwuFOO0U2gYVocszqqDWX+XNKq9hw== - dependencies: - "@chakra-ui/utils" "2.0.15" - -"@chakra-ui/react@^2.8.0": - version "2.8.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.8.2.tgz#94d692fb35e4447748c5bfd73d8d38a746193c7d" - integrity sha512-Hn0moyxxyCDKuR9ywYpqgX8dvjqwu9ArwpIb9wHNYjnODETjLwazgNIliCVBRcJvysGRiV51U2/JtJVrpeCjUQ== - dependencies: - "@chakra-ui/accordion" "2.3.1" - "@chakra-ui/alert" "2.2.2" - "@chakra-ui/avatar" "2.3.0" - "@chakra-ui/breadcrumb" "2.2.0" - "@chakra-ui/button" "2.1.0" - "@chakra-ui/card" "2.2.0" - "@chakra-ui/checkbox" "2.3.2" - "@chakra-ui/close-button" "2.1.1" - "@chakra-ui/control-box" "2.1.0" - "@chakra-ui/counter" "2.1.0" - "@chakra-ui/css-reset" "2.3.0" - "@chakra-ui/editable" "3.1.0" - "@chakra-ui/focus-lock" "2.1.0" - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/hooks" "2.2.1" - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/image" "2.1.0" - "@chakra-ui/input" "2.1.2" - "@chakra-ui/layout" "2.3.1" - "@chakra-ui/live-region" "2.1.0" - "@chakra-ui/media-query" "3.3.0" - "@chakra-ui/menu" "2.2.1" - "@chakra-ui/modal" "2.3.1" - "@chakra-ui/number-input" "2.1.2" - "@chakra-ui/pin-input" "2.1.0" - "@chakra-ui/popover" "2.2.1" - "@chakra-ui/popper" "3.1.0" - "@chakra-ui/portal" "2.1.0" - "@chakra-ui/progress" "2.2.0" - "@chakra-ui/provider" "2.4.2" - "@chakra-ui/radio" "2.1.2" - "@chakra-ui/react-env" "3.1.0" - "@chakra-ui/select" "2.1.2" - "@chakra-ui/skeleton" "2.1.0" - "@chakra-ui/skip-nav" "2.1.0" - "@chakra-ui/slider" "2.1.0" - "@chakra-ui/spinner" "2.1.0" - "@chakra-ui/stat" "2.1.1" - "@chakra-ui/stepper" "2.3.1" - "@chakra-ui/styled-system" "2.9.2" - "@chakra-ui/switch" "2.1.2" - "@chakra-ui/system" "2.6.2" - "@chakra-ui/table" "2.1.0" - "@chakra-ui/tabs" "3.0.0" - "@chakra-ui/tag" "3.1.1" - "@chakra-ui/textarea" "2.1.2" - "@chakra-ui/theme" "3.3.1" - "@chakra-ui/theme-utils" "2.0.21" - "@chakra-ui/toast" "7.0.2" - "@chakra-ui/tooltip" "2.3.1" - "@chakra-ui/transition" "2.1.0" - "@chakra-ui/utils" "2.0.15" - "@chakra-ui/visually-hidden" "2.2.0" - -"@chakra-ui/select@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-2.1.2.tgz#f57d6cec0559373c32094fd4a5abd32855829264" - integrity sha512-ZwCb7LqKCVLJhru3DXvKXpZ7Pbu1TDZ7N0PdQ0Zj1oyVLJyrpef1u9HR5u0amOpqcH++Ugt0f5JSmirjNlctjA== - dependencies: - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/shared-utils@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz#cb2b49705e113853647f1822142619570feba081" - integrity sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q== - -"@chakra-ui/skeleton@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-2.1.0.tgz#e3b25dd3afa330029d6d63be0f7cb8d44ad25531" - integrity sha512-JNRuMPpdZGd6zFVKjVQ0iusu3tXAdI29n4ZENYwAJEMf/fN0l12sVeirOxkJ7oEL0yOx2AgEYFSKdbcAgfUsAQ== - dependencies: - "@chakra-ui/media-query" "3.3.0" - "@chakra-ui/react-use-previous" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/skip-nav@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/skip-nav/-/skip-nav-2.1.0.tgz#cac27eecc6eded1e83c8f0cf7445d727739cb325" - integrity sha512-Hk+FG+vadBSH0/7hwp9LJnLjkO0RPGnx7gBJWI4/SpoJf3e4tZlWYtwGj0toYY4aGKl93jVghuwGbDBEMoHDug== - -"@chakra-ui/slider@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-2.1.0.tgz#1caeed18761ba2a390777418cc9389ba25e39bce" - integrity sha512-lUOBcLMCnFZiA/s2NONXhELJh6sY5WtbRykPtclGfynqqOo47lwWJx+VP7xaeuhDOPcWSSecWc9Y1BfPOCz9cQ== - dependencies: - "@chakra-ui/number-utils" "2.0.7" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-callback-ref" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-latest-ref" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-pan-event" "2.1.0" - "@chakra-ui/react-use-size" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - -"@chakra-ui/spinner@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-2.1.0.tgz#aa24a3d692c6ac90714e0f0f82c76c12c78c8e60" - integrity sha512-hczbnoXt+MMv/d3gE+hjQhmkzLiKuoTo42YhUG7Bs9OSv2lg1fZHW1fGNRFP3wTi6OIbD044U1P9HK+AOgFH3g== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/stat@2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-2.1.1.tgz#a204ba915795345996a16c79794d84826d7dcc2d" - integrity sha512-LDn0d/LXQNbAn2KaR3F1zivsZCewY4Jsy1qShmfBMKwn6rI8yVlbvu6SiA3OpHS0FhxbsZxQI6HefEoIgtqY6Q== - dependencies: - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/stepper@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/stepper/-/stepper-2.3.1.tgz#a0a0b73e147f202ab4e51cae55dad45489cc89fd" - integrity sha512-ky77lZbW60zYkSXhYz7kbItUpAQfEdycT0Q4bkHLxfqbuiGMf8OmgZOQkOB9uM4v0zPwy2HXhe0vq4Dd0xa55Q== - dependencies: - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/styled-system@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.9.2.tgz#898ab63da560a4a014f7b05fa7767e8c76da6d2f" - integrity sha512-To/Z92oHpIE+4nk11uVMWqo2GGRS86coeMmjxtpnErmWRdLcp1WVCVRAvn+ZwpLiNR+reWFr2FFqJRsREuZdAg== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - csstype "^3.1.2" - lodash.mergewith "4.6.2" - -"@chakra-ui/switch@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-2.1.2.tgz#f7c6878d8126bfac8fa3b939079f1017c21b7479" - integrity sha512-pgmi/CC+E1v31FcnQhsSGjJnOE2OcND4cKPyTE+0F+bmGm48Q/b5UmKD9Y+CmZsrt/7V3h8KNczowupfuBfIHA== - dependencies: - "@chakra-ui/checkbox" "2.3.2" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/system@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.6.2.tgz#528ec955bd6a7f74da46470ee8225b1e2c80a78b" - integrity sha512-EGtpoEjLrUu4W1fHD+a62XR+hzC5YfsWm+6lO0Kybcga3yYEij9beegO0jZgug27V+Rf7vns95VPVP6mFd/DEQ== - dependencies: - "@chakra-ui/color-mode" "2.2.0" - "@chakra-ui/object-utils" "2.1.0" - "@chakra-ui/react-utils" "2.0.12" - "@chakra-ui/styled-system" "2.9.2" - "@chakra-ui/theme-utils" "2.0.21" - "@chakra-ui/utils" "2.0.15" - react-fast-compare "3.2.2" - -"@chakra-ui/table@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-2.1.0.tgz#20dce14c5e4d70dc7c6c0e87cce9b05907ff8c50" - integrity sha512-o5OrjoHCh5uCLdiUb0Oc0vq9rIAeHSIRScc2ExTC9Qg/uVZl2ygLrjToCaKfaaKl1oQexIeAcZDKvPG8tVkHyQ== - dependencies: - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/tabs@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-3.0.0.tgz#854c06880af26158d7c72881c4b5e0453f6c485d" - integrity sha512-6Mlclp8L9lqXmsGWF5q5gmemZXOiOYuh0SGT/7PgJVNPz3LXREXlXg2an4MBUD8W5oTkduCX+3KTMCwRrVrDYw== - dependencies: - "@chakra-ui/clickable" "2.1.0" - "@chakra-ui/descendant" "3.1.0" - "@chakra-ui/lazy-utils" "2.0.5" - "@chakra-ui/react-children-utils" "2.0.6" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-controllable-state" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/react-use-safe-layout-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/tag@3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-3.1.1.tgz#d05284b6549a84d3a08e57eec57df3ad0eebd882" - integrity sha512-Bdel79Dv86Hnge2PKOU+t8H28nm/7Y3cKd4Kfk9k3lOpUh4+nkSGe58dhRzht59lEqa4N9waCgQiBdkydjvBXQ== - dependencies: - "@chakra-ui/icon" "3.2.0" - "@chakra-ui/react-context" "2.1.0" - -"@chakra-ui/textarea@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-2.1.2.tgz#30f8af0e233cec2dee79d527450c6586e7122eff" - integrity sha512-ip7tvklVCZUb2fOHDb23qPy/Fr2mzDOGdkrpbNi50hDCiV4hFX02jdQJdi3ydHZUyVgZVBKPOJ+lT9i7sKA2wA== - dependencies: - "@chakra-ui/form-control" "2.2.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/theme-tools@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.1.2.tgz#913be05879cd816c546993ccb9ff7615f85ff69f" - integrity sha512-Qdj8ajF9kxY4gLrq7gA+Azp8CtFHGO9tWMN2wfF9aQNgG9AuMhPrUzMq9AMQ0MXiYcgNq/FD3eegB43nHVmXVA== - dependencies: - "@chakra-ui/anatomy" "2.2.2" - "@chakra-ui/shared-utils" "2.0.5" - color2k "^2.0.2" - -"@chakra-ui/theme-utils@2.0.21": - version "2.0.21" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-utils/-/theme-utils-2.0.21.tgz#da7ed541a5241a8ed0384eb14f37fa9b998382cf" - integrity sha512-FjH5LJbT794r0+VSCXB3lT4aubI24bLLRWB+CuRKHijRvsOg717bRdUN/N1fEmEpFnRVrbewttWh/OQs0EWpWw== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.2" - "@chakra-ui/theme" "3.3.1" - lodash.mergewith "4.6.2" - -"@chakra-ui/theme@3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.3.1.tgz#75c6cd0b5c70c0aa955068274ee4780f299bd8a4" - integrity sha512-Hft/VaT8GYnItGCBbgWd75ICrIrIFrR7lVOhV/dQnqtfGqsVDlrztbSErvMkoPKt0UgAkd9/o44jmZ6X4U2nZQ== - dependencies: - "@chakra-ui/anatomy" "2.2.2" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/theme-tools" "2.1.2" - -"@chakra-ui/toast@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-7.0.2.tgz#d1c396bbfced12e22b010899731fd8cc294d53ec" - integrity sha512-yvRP8jFKRs/YnkuE41BVTq9nB2v/KDRmje9u6dgDmE5+1bFt3bwjdf9gVbif4u5Ve7F7BGk5E093ARRVtvLvXA== - dependencies: - "@chakra-ui/alert" "2.2.2" - "@chakra-ui/close-button" "2.1.1" - "@chakra-ui/portal" "2.1.0" - "@chakra-ui/react-context" "2.1.0" - "@chakra-ui/react-use-timeout" "2.1.0" - "@chakra-ui/react-use-update-effect" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - "@chakra-ui/styled-system" "2.9.2" - "@chakra-ui/theme" "3.3.1" - -"@chakra-ui/tooltip@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-2.3.1.tgz#29fb8508a37bb6b20ab8dbb32bca6cd59b098796" - integrity sha512-Rh39GBn/bL4kZpuEMPPRwYNnccRCL+w9OqamWHIB3Qboxs6h8cOyXfIdGxjo72lvhu1QI/a4KFqkM3St+WfC0A== - dependencies: - "@chakra-ui/dom-utils" "2.1.0" - "@chakra-ui/popper" "3.1.0" - "@chakra-ui/portal" "2.1.0" - "@chakra-ui/react-types" "2.0.7" - "@chakra-ui/react-use-disclosure" "2.1.0" - "@chakra-ui/react-use-event-listener" "2.1.0" - "@chakra-ui/react-use-merge-refs" "2.1.0" - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/transition@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-2.1.0.tgz#c8e95564f7ab356e78119780037bae5ad150c7b3" - integrity sha512-orkT6T/Dt+/+kVwJNy7zwJ+U2xAZ3EU7M3XCs45RBvUnZDr/u9vdmaM/3D/rOpmQJWgQBwKPJleUXrYWUagEDQ== - dependencies: - "@chakra-ui/shared-utils" "2.0.5" - -"@chakra-ui/utils@2.0.15": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.15.tgz#bd800b1cff30eb5a5e8c36fa039f49984b4c5e4a" - integrity sha512-El4+jL0WSaYYs+rJbuYFDbjmfCcfGDmRY95GO4xwzit6YAPZBLcR65rOEwLps+XWluZTy1xdMrusg/hW0c1aAA== - dependencies: - "@types/lodash.mergewith" "4.6.7" - css-box-model "1.2.1" - framesync "6.1.2" - lodash.mergewith "4.6.2" - -"@chakra-ui/visually-hidden@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-2.2.0.tgz#9b0ecef8f01263ab808ba3bda7b36a0d91b4d5c1" - integrity sha512-KmKDg01SrQ7VbTD3+cPWf/UfpF5MSwm3v7MWi0n5t8HnnadT13MF0MJCDSXbBWnzLv1ZKJ6zlyAOeARWX+DpjQ== - "@chromatic-com/storybook@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@chromatic-com/storybook/-/storybook-1.5.0.tgz#a1312b7fc8ac0df2d43c51e48014e024fd4b9561" @@ -3101,13 +2282,6 @@ dependencies: "@emotion/memoize" "0.7.4" -"@emotion/is-prop-valid@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" - integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== - dependencies: - "@emotion/memoize" "^0.8.1" - "@emotion/memoize@0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" @@ -3118,7 +2292,7 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/react@^11.11.1", "@emotion/react@^11.8.1": +"@emotion/react@^11.8.1": version "11.11.3" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.3.tgz#96b855dc40a2a55f52a72f518a41db4f69c31a25" integrity sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA== @@ -3148,18 +2322,6 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/styled@^11.11.0": - version "11.11.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346" - integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng== - dependencies: - "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.11.0" - "@emotion/is-prop-valid" "^1.2.1" - "@emotion/serialize" "^1.1.2" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" - "@emotion/utils" "^1.2.1" - "@emotion/unitless@^0.8.1": version "0.8.1" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" @@ -3185,221 +2347,111 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== -"@esbuild/android-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" - integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== - "@esbuild/android-arm64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== -"@esbuild/android-arm@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" - integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== - "@esbuild/android-arm@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== -"@esbuild/android-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" - integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== - "@esbuild/android-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== -"@esbuild/darwin-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" - integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== - "@esbuild/darwin-arm64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== -"@esbuild/darwin-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" - integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== - "@esbuild/darwin-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== -"@esbuild/freebsd-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" - integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== - "@esbuild/freebsd-arm64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== -"@esbuild/freebsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" - integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== - "@esbuild/freebsd-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== -"@esbuild/linux-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" - integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== - "@esbuild/linux-arm64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== -"@esbuild/linux-arm@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" - integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== - "@esbuild/linux-arm@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== -"@esbuild/linux-ia32@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" - integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== - "@esbuild/linux-ia32@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== -"@esbuild/linux-loong64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" - integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== - "@esbuild/linux-loong64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== -"@esbuild/linux-mips64el@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" - integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== - "@esbuild/linux-mips64el@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== -"@esbuild/linux-ppc64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" - integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== - "@esbuild/linux-ppc64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== -"@esbuild/linux-riscv64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" - integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== - "@esbuild/linux-riscv64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== -"@esbuild/linux-s390x@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" - integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== - "@esbuild/linux-s390x@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== -"@esbuild/linux-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" - integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== - "@esbuild/linux-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== -"@esbuild/netbsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" - integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== - "@esbuild/netbsd-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== -"@esbuild/openbsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" - integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== - "@esbuild/openbsd-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== -"@esbuild/sunos-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" - integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== - "@esbuild/sunos-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== -"@esbuild/win32-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" - integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== - "@esbuild/win32-arm64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== -"@esbuild/win32-ia32@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" - integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== - "@esbuild/win32-ia32@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== -"@esbuild/win32-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" - integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== - "@esbuild/win32-x64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" @@ -3487,6 +2539,54 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.5.tgz#105c37d9d9620ce69b7f692a20c821bf1ad2cbf9" integrity sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ== +"@formatjs/ecma402-abstract@2.3.3": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.3.tgz#fbc7555c9e4fdd104cd5e23129fa3735be3ad0ba" + integrity sha512-pJT1OkhplSmvvr6i3CWTPvC/FGC06MbN5TNBfRO6Ox62AEz90eMq+dVvtX9Bl3jxCEkS0tATzDarRZuOLw7oFg== + dependencies: + "@formatjs/fast-memoize" "2.2.6" + "@formatjs/intl-localematcher" "0.6.0" + decimal.js "10" + tslib "2" + +"@formatjs/fast-memoize@2.2.6", "@formatjs/fast-memoize@^2.2.0": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz#fac0a84207a1396be1f1aa4ee2805b179e9343d1" + integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw== + dependencies: + tslib "2" + +"@formatjs/icu-messageformat-parser@2.11.1": + version "2.11.1" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.1.tgz#59d69124b9cf3186800a576c0228947d10594347" + integrity sha512-o0AhSNaOfKoic0Sn1GkFCK4MxdRsw7mPJ5/rBpIqdvcC7MIuyUSW8WChUEvrK78HhNpYOgqCQbINxCTumJLzZA== + dependencies: + "@formatjs/ecma402-abstract" "2.3.3" + "@formatjs/icu-skeleton-parser" "1.8.13" + tslib "2" + +"@formatjs/icu-skeleton-parser@1.8.13": + version "1.8.13" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.13.tgz#5e8b1e1bb467c937735fecb4cb4b345932151a44" + integrity sha512-N/LIdTvVc1TpJmMt2jVg0Fr1F7Q1qJPdZSCs19unMskCmVQ/sa0H9L8PWt13vq+gLdLg1+pPsvBLydL1Apahjg== + dependencies: + "@formatjs/ecma402-abstract" "2.3.3" + tslib "2" + +"@formatjs/intl-localematcher@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.0.tgz#33cf0d33279572c990e02ab75a93122569878082" + integrity sha512-4rB4g+3hESy1bHSBG3tDFaMY2CH67iT7yne1e+0CLTsGLDcmoEWWpJjjpWVaYgYfYuohIRuo0E+N536gd2ZHZA== + dependencies: + tslib "2" + +"@formatjs/intl-localematcher@^0.5.4": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz#1e0bd3fc1332c1fe4540cfa28f07e9227b659a58" + integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q== + dependencies: + tslib "2" + "@hookform/resolvers@^3.8.0": version "3.9.0" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.9.0.tgz#cf540ac21c6c0cd24a40cf53d8e6d64391fb753d" @@ -3762,11 +2862,6 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== -"@popperjs/core@^2.9.3": - version "2.11.8" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" - integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== - "@radix-ui/number@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" @@ -5126,7 +4221,7 @@ fs-extra "^11.1.0" read-pkg-up "^7.0.1" -"@storybook/test@8.1.10", "@storybook/test@^8.0.10": +"@storybook/test@8.1.10": version "8.1.10" resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.1.10.tgz#ed05aaeaf96d00cc82947ac596b0456e21583a30" integrity sha512-uskw/xb/GkGLRTEKPao/5xUKxjP1X3DnDpE52xDF46ZmTvM+gPQbkex97qdG6Mfv37/0lhVhufAsV3g5+CrYKQ== @@ -5554,14 +4649,6 @@ dependencies: "@types/unist" "*" -"@types/hoist-non-react-statics@^3.3.1": - version "3.3.5" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494" - integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -5582,14 +4669,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash.mergewith@4.6.7": - version "4.6.7" - resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz#eaa65aa5872abdd282f271eae447b115b2757212" - integrity sha512-3m+lkO5CLRRYU0fhGRp7zbsGi6+BZj0uTVSwvcKU+nSlhjA9/QRNfuSGnD2mX6hQA7ZbmcCkzk5h4ZYGOtk14A== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*", "@types/lodash@^4.14.167": +"@types/lodash@^4.14.167": version "4.14.202" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== @@ -6170,23 +5250,6 @@ "@types/emscripten" "^1.39.6" tslib "^1.13.0" -"@zag-js/dom-query@0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@zag-js/dom-query/-/dom-query-0.16.0.tgz#bca46bcd78f78c900064478646d95f9781ed098e" - integrity sha512-Oqhd6+biWyKnhKwFFuZrrf6lxBz2tX2pRQe6grUnYwO6HJ8BcbqZomy2lpOdr+3itlaUqx+Ywj5E5ZZDr/LBfQ== - -"@zag-js/element-size@0.10.5": - version "0.10.5" - resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.10.5.tgz#a24bad2eeb7e2c8709e32be5336e158e1a1a174f" - integrity sha512-uQre5IidULANvVkNOBQ1tfgwTQcGl4hliPSe69Fct1VfYb2Fd0jdAcGzqQgPhfrXFpR62MxLPB7erxJ/ngtL8w== - -"@zag-js/focus-visible@0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.16.0.tgz#c9e53e3dbab0f2649d04a489bb379f5800f4f069" - integrity sha512-a7U/HSopvQbrDU4GLerpqiMcHKEkQkNPeDZJWz38cw/6Upunh41GjHetq5TB84hxyCaDzJ6q2nEdNoBQfC0FKA== - dependencies: - "@zag-js/dom-query" "0.16.0" - abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -6410,7 +5473,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1, aria-hidden@^1.2.3: +aria-hidden@^1.1.1: version "1.2.3" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== @@ -7245,19 +6308,6 @@ clean-css@^5.2.2: dependencies: source-map "~0.6.0" -clear-any-console@^1.16.0: - version "1.16.2" - resolved "https://registry.yarnpkg.com/clear-any-console/-/clear-any-console-1.16.2.tgz#0543bb068da00151bf77b7a01ebf05d611086bb9" - integrity sha512-OL/7wZpNy9x0GBSzz3poWja84Nr7iaH8aYNsJ5Uet2BVLj6Lm1zvWpZN/yH46Vv3ae7YfHmLLMmfHj911fshJg== - -cli-check-node@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/cli-check-node/-/cli-check-node-1.3.4.tgz#f48f5b088ce4ab2ff5630ae007461b4f12ee2bb7" - integrity sha512-iLGgQXm82iP8eH3R67qbOWs5qqUOLmNnMy5Lzl/RybcMh3y+H2zWU5POzuQ6oDUOdz4XWuxcFhP75szqd6frLg== - dependencies: - chalk "^3.0.0" - log-symbols "^3.0.0" - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -7272,21 +6322,6 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" -cli-handle-error@^4.1.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cli-handle-error/-/cli-handle-error-4.4.0.tgz#f65d7d66c3d648a063696b5c83f3b8cc850da25d" - integrity sha512-RyBCnKlc7xVr79cKb9RfBq+4fjwQeX8HKeNzIPnI/W+DWWIUUKh2ur576DpwJ3kZt2UGHlIAOF7N9txy+mgZsA== - dependencies: - chalk "^3.0.0" - log-symbols "^3.0.0" - -cli-handle-unhandled@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/cli-handle-unhandled/-/cli-handle-unhandled-1.1.1.tgz#8a62e244e29cc74ec3f89954a8e8871a4d81e7d8" - integrity sha512-Em91mJvU7VdgT2MxQpyY633vW1tDzRjPDbii6ZjEBHHLLh0xDoVkFt/wjvi9nSvJcz9rJmvtJSK8KL/hvF0Stg== - dependencies: - cli-handle-error "^4.1.0" - cli-spinners@^2.5.0: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" @@ -7309,15 +6344,6 @@ cli-truncate@^4.0.0: slice-ansi "^5.0.0" string-width "^7.0.0" -cli-welcome@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/cli-welcome/-/cli-welcome-2.2.2.tgz#a67c55e7826acbd8117266db73590e35b3611261" - integrity sha512-LgDGS0TW4nIf8v81wpuZzfOEDPcy68u0jKR0Fy5IaWftqdminI6FoDiMFt1mjPylqKGNv/wFsZ7fCs93IeDMIw== - dependencies: - chalk "^2.4.2" - clear-any-console "^1.16.0" - prettier "^2.0.5" - client-only@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -7401,11 +6427,6 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" -color2k@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.3.tgz#a771244f6b6285541c82aa65ff0a0c624046e533" - integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== - color@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" @@ -7456,11 +6477,6 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -commander@^9.3.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" @@ -7496,11 +6512,6 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" -compute-scroll-into-view@3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz#c418900a5c56e2b04b885b54995df164535962b1" - integrity sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -7553,13 +6564,6 @@ cookie@0.6.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -copy-to-clipboard@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" - integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== - dependencies: - toggle-selection "^1.0.6" - core-js-compat@^3.31.0, core-js-compat@^3.34.0: version "3.35.1" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.35.1.tgz#215247d7edb9e830efa4218ff719beb2803555e2" @@ -7579,11 +6583,6 @@ core-js-pure@^3.23.3: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd" integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA== -core-js@^3: - version "3.35.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.1.tgz#9c28f8b7ccee482796f8590cc8d15739eaaf980c" - integrity sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -7689,13 +6688,6 @@ crypto-random-string@^4.0.0: dependencies: type-fest "^1.0.1" -css-box-model@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" - integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== - dependencies: - tiny-invariant "^1.0.6" - css-loader@^6.7.1, css-loader@^6.7.3: version "6.11.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" @@ -7770,7 +6762,7 @@ csso@^5.0.5: dependencies: css-tree "~2.2.0" -csstype@^3.0.2, csstype@^3.1.2: +csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== @@ -7889,6 +6881,11 @@ decimal.js-light@^2.4.1: resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== +decimal.js@10: + version "10.5.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" + integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== + decode-named-character-reference@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" @@ -8572,34 +7569,6 @@ esbuild@^0.12.9: resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.29.tgz#be602db7c4dc78944a9dbde0d1ea19d36c1f882d" integrity sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g== -esbuild@^0.17.18: - version "0.17.19" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" - integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== - optionalDependencies: - "@esbuild/android-arm" "0.17.19" - "@esbuild/android-arm64" "0.17.19" - "@esbuild/android-x64" "0.17.19" - "@esbuild/darwin-arm64" "0.17.19" - "@esbuild/darwin-x64" "0.17.19" - "@esbuild/freebsd-arm64" "0.17.19" - "@esbuild/freebsd-x64" "0.17.19" - "@esbuild/linux-arm" "0.17.19" - "@esbuild/linux-arm64" "0.17.19" - "@esbuild/linux-ia32" "0.17.19" - "@esbuild/linux-loong64" "0.17.19" - "@esbuild/linux-mips64el" "0.17.19" - "@esbuild/linux-ppc64" "0.17.19" - "@esbuild/linux-riscv64" "0.17.19" - "@esbuild/linux-s390x" "0.17.19" - "@esbuild/linux-x64" "0.17.19" - "@esbuild/netbsd-x64" "0.17.19" - "@esbuild/openbsd-x64" "0.17.19" - "@esbuild/sunos-x64" "0.17.19" - "@esbuild/win32-arm64" "0.17.19" - "@esbuild/win32-ia32" "0.17.19" - "@esbuild/win32-x64" "0.17.19" - "esbuild@^0.18.0 || ^0.19.0 || ^0.20.0": version "0.20.2" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" @@ -9265,13 +8234,6 @@ flow-parser@0.*: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.227.0.tgz#e50b65be9dc6810438c975e816a68005fbcd5107" integrity sha512-nOygtGKcX/siZK/lFzpfdHEfOkfGcTW7rNroR1Zsz6T/JxSahPALXVt5qVHq/fgvMJuv096BTKbgxN3PzVBaDA== -focus-lock@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-1.0.0.tgz#2c50d8ce59d3d6608cda2672be9e65812459206c" - integrity sha512-a8Ge6cdKh9za/GZR/qtigTAk7SrGore56EFcoMshClsh7FLk1zwszc/ltuMfKhx56qeuyL/jWQ4J4axou0iJ9w== - dependencies: - tslib "^2.0.3" - follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" @@ -9338,13 +8300,6 @@ framer-motion@^10.13.0: optionalDependencies: "@emotion/is-prop-valid" "^0.8.2" -framesync@6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.1.2.tgz#755eff2fb5b8f3b4d2b266dd18121b300aefea27" - integrity sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g== - dependencies: - tslib "2.4.0" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -9863,7 +8818,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -9898,13 +8853,6 @@ html-minifier-terser@^6.0.2: relateurl "^0.2.7" terser "^5.10.0" -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" - html-tags@^3.1.0: version "3.3.1" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" @@ -9975,18 +8923,6 @@ husky@^9.0.11: resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== -i18next-fs-backend@^2.1.5: - version "2.3.1" - resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-2.3.1.tgz#0c7d2459ff4a039e2b3228131809fbc0e74ff1a8" - integrity sha512-tvfXskmG/9o+TJ5Fxu54sSO5OkY6d+uMn+K6JiUGLJrwxAVfer+8V3nU8jq3ts9Pe5lXJv4b1N7foIjJ8Iy2Gg== - -i18next@^23.6.0: - version "23.8.1" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.8.1.tgz#c9c6c0a2718177457192d3a867af5b35cd2f46fe" - integrity sha512-Yhe6oiJhigSh64ev7nVVywu7vHjuUG41MRmFKNwphbkadqTL1ozZFBQISflY7/ju+gL6I/SPfI1GgWQh1yYArA== - dependencies: - "@babel/runtime" "^7.23.2" - iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -10076,6 +9012,16 @@ internal-slot@^1.0.4, internal-slot@^1.0.5: resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== +intl-messageformat@^10.5.14: + version "10.7.15" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.15.tgz#5cdc62139ef39ece1b083db32dae4d1c9fa5b627" + integrity sha512-LRyExsEsefQSBjU2p47oAheoKz+EOJxSLDdjOaEjdriajfHsMXOmV/EhMvYSg9bAgCUHasuAC+mcUBe/95PfIg== + dependencies: + "@formatjs/ecma402-abstract" "2.3.3" + "@formatjs/fast-memoize" "2.2.6" + "@formatjs/icu-messageformat-parser" "2.11.1" + tslib "2" + invariant@^2.2.1, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -10777,11 +9723,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.mergewith@4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== - lodash.shuffle@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.shuffle/-/lodash.shuffle-4.2.0.tgz#145b5053cf875f6f5c2a33f48b6e9948c6ec7b4b" @@ -10802,13 +9743,6 @@ lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -11631,21 +10565,24 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + neo-async@^2.5.0, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -next-i18next@^14.0.3: - version "14.0.3" - resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-14.0.3.tgz#9c17e69483b3af4172b15454af2ef92c5f79be48" - integrity sha512-FtnjRMfhlamk8YyeyWqd+pndNL+3er83iMZnH4M4mhiGA93l0+vtBUvuObgOAMHDJGLLB2SS2xOOZq69oiJh7A== +next-intl@^3.26.3: + version "3.26.4" + resolved "https://registry.yarnpkg.com/next-intl/-/next-intl-3.26.4.tgz#7dcb4c15412c69f60df56636a9ed56ade82fb63c" + integrity sha512-/kFFR7WYJGisOR0xKoC930e6oTOOWf8rbHviQgte5zIn6OgJ6mKFvXI94RWAW3ksCZJCvE4zblIuYwHCSbbw7g== dependencies: - "@babel/runtime" "^7.20.13" - "@types/hoist-non-react-statics" "^3.3.1" - core-js "^3" - hoist-non-react-statics "^3.3.2" - i18next-fs-backend "^2.1.5" + "@formatjs/intl-localematcher" "^0.5.4" + negotiator "^1.0.0" + use-intl "^3.26.4" next-mdx-remote@^3.0.8: version "3.0.8" @@ -12484,11 +11421,6 @@ prettier-plugin-tailwindcss@^0.6.5: resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz#e05202784a3f41889711ae38c75c5b8cad72f368" integrity sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ== -prettier@^2.0.5, prettier@^2.8.8: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - prettier@^3.1.1: version "3.3.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" @@ -12742,13 +11674,6 @@ react-chartjs-2@^5.2.0: resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz#43c1e3549071c00a1a083ecbd26c1ad34d385f5d" integrity sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA== -react-clientside-effect@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz#29f9b14e944a376b03fb650eed2a754dd128ea3a" - integrity sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg== - dependencies: - "@babel/runtime" "^7.12.13" - react-colorful@^5.1.2: version "5.6.1" resolved "https://registry.yarnpkg.com/react-colorful/-/react-colorful-5.6.1.tgz#7dc2aed2d7c72fac89694e834d179e32f3da563b" @@ -12818,36 +11743,11 @@ react-emoji-render@^2.0.1: prop-types "^15.5.8" string-replace-to-array "^1.0.1" -react-fast-compare@3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" - integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== - -react-focus-lock@^2.9.4: - version "2.9.7" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.9.7.tgz#778358691b55db38a9954a989341048bd4065935" - integrity sha512-EfhX040SELLqnQ9JftqsmQCG49iByg8F5X5m19Er+n371OaETZ35dlNPZrLOOTlnnwD4c2Zv0KDgabDTc7dPHw== - dependencies: - "@babel/runtime" "^7.0.0" - focus-lock "^1.0.0" - prop-types "^15.6.2" - react-clientside-effect "^1.2.6" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - react-hook-form@^7.52.1: version "7.52.1" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.52.1.tgz#ec2c96437b977f8b89ae2d541a70736c66284852" integrity sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg== -react-i18next@^13.3.1: - version "13.5.0" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-13.5.0.tgz#44198f747628267a115c565f0c736a50a76b1ab0" - integrity sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA== - dependencies: - "@babel/runtime" "^7.22.5" - html-parse-stringify "^3.0.1" - react-icons@^4.10.1: version "4.12.0" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.12.0.tgz#54806159a966961bfd5cdb26e492f4dafd6a8d78" @@ -12907,7 +11807,7 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-remove-scroll@2.5.7, react-remove-scroll@^2.5.6: +react-remove-scroll@2.5.7: version "2.5.7" resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== @@ -13838,18 +12738,17 @@ store2@^2.14.2: resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.4.tgz#81b313abaddade4dcd7570c5cc0e3264a8f7a242" integrity sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw== -storybook-i18n@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/storybook-i18n/-/storybook-i18n-3.0.1.tgz#9320f6e091deb006c6db2e4ce632cccff8429047" - integrity sha512-euCfw6ABqq8jSZ4fCaAIsNwk1FBIrSIr4kMP900bjUgO/mGgzZzXmrYmZaXs51mx9A2p87xo0OktPPZUuKYCTQ== - -storybook-react-i18next@3.1.1: +storybook-i18n@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/storybook-react-i18next/-/storybook-react-i18next-3.1.1.tgz#f602b9aacca4a9b73e8d68c45fe6d73454b762e8" - integrity sha512-myMs1r2Ng4JFna3QiaY590VFTg6/gzRURwJGL95mPcS8bNA5g98Jn74Bs9lJKdltN7D+J01Z0boHM3lMQZB7nA== + resolved "https://registry.yarnpkg.com/storybook-i18n/-/storybook-i18n-3.1.1.tgz#d75f84d62682a76d58586534719a7f5042b82cb9" + integrity sha512-k1/lS+Rx6l5mJEYAHQWEgXuwU5IyWk7kjcJtm2FDIn1UqZwbEraGlrp/fEZKK2e/7+SXEQdKeCaTz7+63WTQxw== + +storybook-next-intl@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/storybook-next-intl/-/storybook-next-intl-1.2.5.tgz#0c710eb8ba592ff1a3df4f3983d864c21540c429" + integrity sha512-YiI6tBHFNF/dU/uVfaXX+tzpbe/MhLD9YMvbn4vdn/t0UQ7yOJl9AFNHhsqhP5FMmIIDrXSr/WCRbLeJCnKq0A== dependencies: - "@storybook/test" "^8.0.10" - storybook-i18n "^3.0.1" + storybook-i18n "3.1.1" storybook@8.1.10: version "8.1.10" @@ -14358,7 +13257,7 @@ timers-browserify@^2.0.12: dependencies: setimmediate "^1.0.4" -tiny-invariant@^1.0.6, tiny-invariant@^1.3.1: +tiny-invariant@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== @@ -14395,11 +13294,6 @@ tocbot@^4.20.1: resolved "https://registry.yarnpkg.com/tocbot/-/tocbot-4.25.0.tgz#bc38aea5ec8f076779bb39636f431b044129a237" integrity sha512-kE5wyCQJ40hqUaRVkyQ4z5+4juzYsv/eK+aqD97N62YH0TxFhzJvo22RUQQZdO3YnXAk42ZOfOpjVdy+Z0YokA== -toggle-selection@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" - integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -14502,10 +13396,10 @@ tsconfig-paths@^4.0.0, tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tslib@^1.13.0, tslib@^1.8.1: version "1.14.1" @@ -14907,6 +13801,14 @@ use-callback-ref@^1.3.0: dependencies: tslib "^2.0.0" +use-intl@^3.26.4: + version "3.26.4" + resolved "https://registry.yarnpkg.com/use-intl/-/use-intl-3.26.4.tgz#ec05127ea7f32fb0d3ac46614423d4c8d8576326" + integrity sha512-5DhN+YfsocNO7LiLpns7/pxRcMHA4DgBZQo5Z6uw3LvX9XIZyPAdRBdFPE2eBKTAwhY77k5eBhxqDtx8wzUaBg== + dependencies: + "@formatjs/fast-memoize" "^2.2.0" + intl-messageformat "^10.5.14" + use-isomorphic-layout-effect@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" @@ -15059,11 +13961,6 @@ vm-browserify@^1.1.2: 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== - watchpack@^2.2.0, watchpack@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff"