- {!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/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 b018a6a854d..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"
@@ -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 bdf96ae6afb..c0079c8248e 100644
--- a/src/layouts/stories/BaseLayout.stories.tsx
+++ b/src/layouts/stories/BaseLayout.stories.tsx
@@ -15,6 +15,9 @@ const meta = {
...langViewportModes,
},
},
+ nextjs: {
+ appDirectory: true,
+ },
},
argTypes: {
children: {
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 978607d0189..4149b2465c9 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -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/md.ts b/src/lib/utils/md.ts
index 7b80932d3a3..08dd074f9f8 100644
--- a/src/lib/utils/md.ts
+++ b/src/lib/utils/md.ts
@@ -16,7 +16,7 @@ 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 getContentRoot() {
return join(process.cwd(), CONTENT_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 faa9bdca95b..8a90b43cf29 100644
--- a/src/pages/404.tsx
+++ b/src/pages/404.tsx
@@ -1,5 +1,4 @@
import type { GetStaticProps } from "next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
import { BasePageProps, Lang } from "@/lib/types"
@@ -12,7 +11,14 @@ 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 46e768b8392..77c87985265 100644
--- a/src/pages/assets.tsx
+++ b/src/pages/[locale]/assets.tsx
@@ -1,9 +1,7 @@
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"
@@ -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(
diff --git a/src/pages/bug-bounty.tsx b/src/pages/[locale]/bug-bounty.tsx
similarity index 97%
rename from src/pages/bug-bounty.tsx
rename to src/pages/[locale]/bug-bounty.tsx
index af60ce785a7..b3e747b1c51 100644
--- a/src/pages/bug-bounty.tsx
+++ b/src/pages/[locale]/bug-bounty.tsx
@@ -1,10 +1,7 @@
import { HTMLAttributes } from "react"
-import { useRouter } from "next/router"
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"
/* Uncomment for Bug Bounty Banner: */
import BugBountyBanner from "@/components/Banners/BugBountyBanner"
@@ -35,7 +32,12 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import consensusData from "@/data/consensus-bounty-hunters.json"
import executionData from "@/data/execution-bounty-hunters.json"
+import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
+
import useColorModeValue from "@/hooks/useColorModeValue"
+import { useTranslation } from "@/hooks/useTranslation"
+import loadNamespaces from "@/i18n/loadNamespaces"
+import { usePathname } from "@/i18n/routing"
import besu from "@/public/images/upgrades/besu.png"
import erigon from "@/public/images/upgrades/erigon.png"
import geth from "@/public/images/upgrades/geth.png"
@@ -229,7 +231,16 @@ const sortBountyHuntersFn = (a: BountyHuntersArg, b: BountyHuntersArg) => {
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)
diff --git a/src/pages/community.tsx b/src/pages/[locale]/community.tsx
similarity index 95%
rename from src/pages/community.tsx
rename to src/pages/[locale]/community.tsx
index cc14421714b..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"
@@ -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}
diff --git a/src/pages/contributing/translation-program/acknowledgements.tsx b/src/pages/[locale]/contributing/translation-program/acknowledgements.tsx
similarity index 89%
rename from src/pages/contributing/translation-program/acknowledgements.tsx
rename to src/pages/[locale]/contributing/translation-program/acknowledgements.tsx
index 28cbc8722b0..8d983e14aef 100644
--- a/src/pages/contributing/translation-program/acknowledgements.tsx
+++ b/src/pages/[locale]/contributing/translation-program/acknowledgements.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, Lang } from "@/lib/types"
+import { BasePageProps, Lang, Params } from "@/lib/types"
import ActionCard from "@/components/ActionCard"
import Breadcrumbs from "@/components/Breadcrumbs"
@@ -23,11 +20,16 @@ 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 monthData from "../../../data/translation-reports/month/month-data.json"
-import quarterData from "../../../data/translation-reports/quarter/quarter-data.json"
+import allTimeData from "@/data/translation-reports/alltime/alltime-data.json"
+import monthData from "@/data/translation-reports/month/month-data.json"
+import quarterData from "@/data/translation-reports/quarter/quarter-data.json"
+
+import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
import useColorModeValue from "@/hooks/useColorModeValue"
+import { useTranslation } from "@/hooks/useTranslation"
+import loadNamespaces from "@/i18n/loadNamespaces"
+import { usePathname } from "@/i18n/routing"
import darkThemeCertificateImg from "@/public/images/certificates/dark-certificate.png"
import lightThemeCertificateImg from "@/public/images/certificates/light-certificate.png"
import dogeComputerImg from "@/public/images/doge-computer.png"
@@ -54,7 +56,16 @@ const Text = ({
)
-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"
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 98%
rename from src/pages/dapps.tsx
rename to src/pages/[locale]/dapps.tsx
index 18940a7635f..ebb2dfc9eed 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"
@@ -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"
@@ -320,7 +323,16 @@ interface Categories {
[key: string]: Category
}
-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("/dapps")
const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2])
@@ -331,18 +343,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 DappsPage = () => {
const { t } = useTranslation(["page-dapps", "common"])
- const { locale, query } = useRouter()
+ const { query } = useRouter()
+ const locale = useLocale()
const [selectedCategory, setCategory] = useState(
CategoryType.FINANCE
diff --git a/src/pages/developers/index.tsx b/src/pages/[locale]/developers/index.tsx
similarity index 96%
rename from src/pages/developers/index.tsx
rename to src/pages/[locale]/developers/index.tsx
index 30c822da4d3..bf30b227584 100644
--- a/src/pages/developers/index.tsx
+++ b/src/pages/[locale]/developers/index.tsx
@@ -1,9 +1,7 @@
import { HTMLAttributes, ReactNode } 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 Callout from "@/components/Callout"
import Card, { CardProps } from "@/components/Card"
@@ -23,6 +21,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 SpeedRunEthereumImage from "@/public/images/dev-tools/speed-run-ethereum-banner.png"
import DevelopersImage from "@/public/images/developers-eth-blocks.png"
import DogeImage from "@/public/images/doge-computer.png"
@@ -125,7 +127,16 @@ const SpeedRunEthereumBanner = ({
)
-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])
@@ -136,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
diff --git a/src/pages/developers/learning-tools.tsx b/src/pages/[locale]/developers/learning-tools.tsx
similarity index 95%
rename from src/pages/developers/learning-tools.tsx
rename to src/pages/[locale]/developers/learning-tools.tsx
index 4df693ea8bc..3317452e400 100644
--- a/src/pages/developers/learning-tools.tsx
+++ b/src/pages/[locale]/developers/learning-tools.tsx
@@ -1,10 +1,8 @@
import { BaseHTMLAttributes } from "react"
import shuffle from "lodash/shuffle"
import { GetStaticProps } from "next"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
-import { BasePageProps, Lang, LearningTool } from "@/lib/types"
+import { BasePageProps, Lang, LearningTool, Params } from "@/lib/types"
import CalloutBanner from "@/components/CalloutBanner"
import FeedbackCard from "@/components/FeedbackCard"
@@ -21,6 +19,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 AlchemyUniversityImage from "@/public/images/dev-tools/alchemyuniversity.png"
import AtlasImage from "@/public/images/dev-tools/atlas.png"
import BloomTechImage from "@/public/images/dev-tools/bloomtech.png"
@@ -117,7 +119,16 @@ const StackContainer = ({
/>
)
-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"
)
@@ -64,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,
diff --git a/src/pages/developers/tutorials.tsx b/src/pages/[locale]/developers/tutorials.tsx
similarity index 94%
rename from src/pages/developers/tutorials.tsx
rename to src/pages/[locale]/developers/tutorials.tsx
index da869c6ec94..aff62369a2e 100644
--- a/src/pages/developers/tutorials.tsx
+++ b/src/pages/[locale]/developers/tutorials.tsx
@@ -7,12 +7,10 @@ import React, {
useState,
} from "react"
import { GetStaticProps, InferGetServerSidePropsType } from "next"
-import { useRouter } from "next/router"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
+import { useLocale } from "next-intl"
import { FaGithub } from "react-icons/fa"
-import { BasePageProps, Lang } from "@/lib/types"
+import { BasePageProps, Lang, Params } from "@/lib/types"
import Emoji from "@/components/Emoji"
import FeedbackCard from "@/components/FeedbackCard"
@@ -40,7 +38,11 @@ import {
import externalTutorials from "@/data/externalTutorials.json"
+import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
+
import { useBreakpointValue } from "@/hooks/useBreakpointValue"
+import { useTranslation } from "@/hooks/useTranslation"
+import loadNamespaces from "@/i18n/loadNamespaces"
type Props = BasePageProps & {
internalTutorials: ITutorial[]
@@ -82,7 +84,16 @@ const LinkFlex = ({ href, children, ...props }: LinkFlexProps) => {
)
}
-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"
)
@@ -95,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
@@ -146,7 +159,7 @@ const TutorialPage = ({
internalTutorials,
contentNotTranslated,
}: InferGetServerSidePropsType) => {
- const { locale } = useRouter()
+ const locale = useLocale()
const filteredTutorialsByLang = useMemo(
() =>
filterTutorialsByLang(
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 9d2c8177fff..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"
@@ -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")
diff --git a/src/pages/gas.tsx b/src/pages/[locale]/gas.tsx
similarity index 95%
rename from src/pages/gas.tsx
rename to src/pages/[locale]/gas.tsx
index 1906c686781..1fb9d92cd18 100644
--- a/src/pages/gas.tsx
+++ b/src/pages/[locale]/gas.tsx
@@ -1,9 +1,7 @@
import { BaseHTMLAttributes, ComponentPropsWithRef } from "react"
import { GetStaticProps } from "next/types"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
-import { BasePageProps, Lang } from "@/lib/types"
+import { BasePageProps, Lang, Params } from "@/lib/types"
import Callout from "@/components/Callout"
import Card from "@/components/Card"
@@ -40,6 +38,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 dogeComputerImg from "@/public/images/doge-computer.png"
import ethImg from "@/public/images/eth.png"
@@ -84,7 +86,16 @@ const H3 = ({
)
-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")
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 2b43b4c31f9..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, {
@@ -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 98%
rename from src/pages/index.tsx
rename to src/pages/[locale]/index.tsx
index 8eb0ad6f0ce..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,6 +9,7 @@ import type {
BasePageProps,
CommunityBlog,
Lang,
+ Params,
RSSItem,
} from "@/lib/types"
@@ -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,
diff --git a/src/pages/layer-2/index.tsx b/src/pages/[locale]/layer-2/index.tsx
similarity index 97%
rename from src/pages/layer-2/index.tsx
rename to src/pages/[locale]/layer-2/index.tsx
index fc357101796..987c9727742 100644
--- a/src/pages/layer-2/index.tsx
+++ b/src/pages/[locale]/layer-2/index.tsx
@@ -1,7 +1,6 @@
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"
@@ -22,8 +21,9 @@ 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"
@@ -43,7 +43,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,
@@ -77,9 +86,11 @@ export const getStaticProps = (async ({ locale }) => {
const userRandomL2s = getRandomL2s()
+ const messages = await loadNamespaces(locale, requiredNamespaces)
+
return {
props: {
- ...(await serverSideTranslations(locale!, requiredNamespaces)),
+ messages,
randomL2s,
userRandomL2s,
contentNotTranslated,
@@ -88,7 +99,7 @@ export const getStaticProps = (async ({ locale }) => {
growThePieData,
},
}
-}) satisfies GetStaticProps
+}) satisfies GetStaticProps
const Layer2Hub = ({
randomL2s,
diff --git a/src/pages/layer-2/learn.tsx b/src/pages/[locale]/layer-2/learn.tsx
similarity index 94%
rename from src/pages/layer-2/learn.tsx
rename to src/pages/[locale]/layer-2/learn.tsx
index 7f4a9507a6f..68bc29e94b2 100644
--- a/src/pages/layer-2/learn.tsx
+++ b/src/pages/[locale]/layer-2/learn.tsx
@@ -1,9 +1,6 @@
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"
@@ -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 },
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 c8e148c4d02..6049f4ca231 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 97%
rename from src/pages/learn.tsx
rename to src/pages/[locale]/learn.tsx
index c0383f3f1de..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,
@@ -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"
@@ -117,10 +125,19 @@ const ImageHeight200 = ({ src, alt }: ImageProps) => (
)
-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")
diff --git a/src/pages/quizzes.tsx b/src/pages/[locale]/quizzes.tsx
similarity index 88%
rename from src/pages/quizzes.tsx
rename to src/pages/[locale]/quizzes.tsx
index 3ab601ba7a5..fbf90bfcdaa 100644
--- a/src/pages/quizzes.tsx
+++ b/src/pages/[locale]/quizzes.tsx
@@ -1,10 +1,8 @@
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 { BasePageProps, Lang, QuizKey, QuizStatus } from "@/lib/types"
+import { BasePageProps, Lang, Params, QuizKey, QuizStatus } from "@/lib/types"
import FeedbackCard from "@/components/FeedbackCard"
import { HubHero } from "@/components/Hero"
@@ -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
diff --git a/src/pages/roadmap/vision.tsx b/src/pages/[locale]/roadmap/vision.tsx
similarity index 92%
rename from src/pages/roadmap/vision.tsx
rename to src/pages/[locale]/roadmap/vision.tsx
index 9350d2b4b2a..b01cae17597 100644
--- a/src/pages/roadmap/vision.tsx
+++ b/src/pages/[locale]/roadmap/vision.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 {
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 Card from "@/components/Card"
@@ -34,6 +31,11 @@ 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"
/**
@@ -106,7 +108,16 @@ 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])
@@ -117,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 = [
{
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 a28c68015d0..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"
@@ -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")
diff --git a/src/pages/stablecoins.tsx b/src/pages/[locale]/stablecoins.tsx
similarity index 97%
rename from src/pages/stablecoins.tsx
rename to src/pages/[locale]/stablecoins.tsx
index 36cbcce68be..3767f55fb67 100644
--- a/src/pages/stablecoins.tsx
+++ b/src/pages/[locale]/stablecoins.tsx
@@ -1,10 +1,8 @@
import { BaseHTMLAttributes } from "react"
import { GetStaticProps } from "next/types"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
import { MdHelpOutline } from "react-icons/md"
-import { BasePageProps, Lang } from "@/lib/types"
+import { BasePageProps, Lang, Params } from "@/lib/types"
import CalloutBanner from "@/components/CalloutBanner"
import DataProductCard from "@/components/DataProductCard"
@@ -36,8 +34,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 {
fetchEthereumEcosystemData,
fetchEthereumStablecoinsData,
@@ -93,7 +93,16 @@ const loadData = dataLoader<[EthereumDataResponse, StablecoinDataResponse]>(
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) => (
diff --git a/src/pages/staking/deposit-contract.tsx b/src/pages/[locale]/staking/deposit-contract.tsx
similarity index 95%
rename from src/pages/staking/deposit-contract.tsx
rename to src/pages/[locale]/staking/deposit-contract.tsx
index 3f5bbedcba3..a5c4424a60a 100644
--- a/src/pages/staking/deposit-contract.tsx
+++ b/src/pages/[locale]/staking/deposit-contract.tsx
@@ -1,14 +1,12 @@
import { useEffect, useState } from "react"
import makeBlockie from "ethereum-blockies-base64"
import { type GetStaticProps } from "next"
-import { useRouter } from "next/router"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
import type {
BasePageProps,
ChildOnlyProp,
Lang,
+ Params,
TranslationKey,
} from "@/lib/types"
@@ -40,6 +38,11 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { DEPOSIT_CONTRACT_ADDRESS } from "@/data/addresses"
+import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
+
+import useTranslation from "@/hooks/useTranslation"
+import loadNamespaces from "@/i18n/loadNamespaces"
+import { usePathname } from "@/i18n/routing"
import consensys from "@/public/images/projects/consensys.png"
import etherscan from "@/public/images/projects/etherscan-logo-circle.png"
import ef from "@/public/images/staking/ef-blog-logo.png"
@@ -155,7 +158,16 @@ const CHUNKED_ADDRESS = DEPOSIT_CONTRACT_ADDRESS.match(/.{1,3}/g)?.join(" ")
const blockieSrc = makeBlockie(DEPOSIT_CONTRACT_ADDRESS)
-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(
"/staking/deposit-contract"
)
@@ -168,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")
@@ -295,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 83%
rename from src/pages/wallets/find-wallet.tsx
rename to src/pages/[locale]/wallets/find-wallet.tsx
index 5272ea01647..622b8ccc09d 100644
--- a/src/pages/wallets/find-wallet.tsx
+++ b/src/pages/[locale]/wallets/find-wallet.tsx
@@ -1,9 +1,12 @@
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"
@@ -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 (
diff --git a/src/pages/wallets/index.tsx b/src/pages/[locale]/wallets/index.tsx
similarity index 95%
rename from src/pages/wallets/index.tsx
rename to src/pages/[locale]/wallets/index.tsx
index 2c4d39ce8bb..2cf49efca44 100644
--- a/src/pages/wallets/index.tsx
+++ b/src/pages/[locale]/wallets/index.tsx
@@ -1,10 +1,8 @@
import { ComponentPropsWithRef } from "react"
import { 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 { BasePageProps, Lang } from "@/lib/types"
+import { BasePageProps, Lang, Params } from "@/lib/types"
import Callout from "@/components/Callout"
import Card from "@/components/Card"
@@ -29,6 +27,10 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { walletOnboardingSimData } from "@/data/WalletSimulatorData"
+import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
+
+import { useTranslation } from "@/hooks/useTranslation"
+import loadNamespaces from "@/i18n/loadNamespaces"
import DappsImage from "@/public/images/doge-computer.png"
import ETHImage from "@/public/images/eth-logo.png"
import FindWalletImage from "@/public/images/wallets/find-wallet.png"
@@ -41,7 +43,16 @@ export const StyledCard = (props: ComponentPropsWithRef) => (
/>
)
-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 = {
diff --git a/src/pages/what-is-ethereum.tsx b/src/pages/[locale]/what-is-ethereum.tsx
similarity index 98%
rename from src/pages/what-is-ethereum.tsx
rename to src/pages/[locale]/what-is-ethereum.tsx
index c3642bd9c13..62ee0ffe105 100644
--- a/src/pages/what-is-ethereum.tsx
+++ b/src/pages/[locale]/what-is-ethereum.tsx
@@ -1,8 +1,6 @@
import { GetStaticProps, InferGetStaticPropsType } from "next"
import type { ImageProps } from "next/image"
-import { useRouter } from "next/router"
-import { useTranslation } from "next-i18next"
-import { serverSideTranslations } from "next-i18next/serverSideTranslations"
+import { useLocale } from "next-intl"
import type { HTMLAttributes } from "react"
import { MdInfoOutline } from "react-icons/md"
@@ -11,6 +9,7 @@ import type {
ChildOnlyProp,
Lang,
MetricReturnData,
+ Params,
} from "@/lib/types"
import AdoptionChart from "@/components/AdoptionChart"
@@ -54,6 +53,10 @@ 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 { fetchGrowThePie } from "@/lib/api/fetchGrowThePie"
import dogeComputerImg from "@/public/images/doge-computer.png"
import ethImg from "@/public/images/eth.png"
@@ -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 = (
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 1d60a767ad4..170195ba294 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,5 +1,6 @@
import { useEffect } from "react"
-import { appWithTranslation } from "next-i18next"
+import { useRouter } from "next/router"
+import { NextIntlClientProvider } from "next-intl"
import { TooltipProvider } from "@radix-ui/react-tooltip"
import { init } from "@socialgouv/matomo-next"
@@ -7,11 +8,15 @@ import { AppPropsWithLayout } from "@/lib/types"
import ThemeProvider from "@/components/ThemeProvider"
+import { DEFAULT_LOCALE } from "@/lib/constants"
+
import "@/styles/global.css"
import { BaseLayout } from "@/layouts/BaseLayout"
const App = ({ Component, pageProps }: AppPropsWithLayout) => {
+ 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/yarn.lock b/yarn.lock
index 65305d5d792..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.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.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==
@@ -2539,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"
@@ -4173,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==
@@ -4601,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"
@@ -6543,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"
@@ -6846,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"
@@ -8778,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==
@@ -8813,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"
@@ -8890,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"
@@ -8991,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"
@@ -10534,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"
@@ -11714,14 +11748,6 @@ react-hook-form@^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"
@@ -12712,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"
@@ -13371,6 +13396,11 @@ 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:
+ 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"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
@@ -13771,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"
@@ -13923,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"