Skip to content

Commit 352f15c

Browse files
authored
Merge pull request #15181 from ethereum/staging
Deploy v10.0.0
2 parents 3d4aa87 + 70a1ea4 commit 352f15c

File tree

781 files changed

+20821
-4738
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

781 files changed

+20821
-4738
lines changed

.github/CODEOWNERS

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
* @wackerow @corwintines @pettinarip @minimalsm
99

1010
# Owners of specific files
11-
/src/data/consensus-bounty-hunters.json @djrtwo @asanso @fredriksvantes
11+
/src/data/consensus-bounty-hunters.json @asanso @fredriksvantes
1212
/src/data/wallets/new-to-crypto.ts @konopkja @minimalsm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Suggest a resource
2+
description: Suggest a new resource to list on ethereum.org/resources
3+
title: Suggest a resource
4+
labels: ["resource 📚"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Before suggesting a resource, make sure you've read [our listing policy](https://www.ethereum.org/en/contributing/adding-resources/).
10+
- type: markdown
11+
attributes:
12+
value: Only continue with the issue if your resource meets the criteria listed there.
13+
- type: markdown
14+
attributes:
15+
value: If it does, complete the following information which we need to accurately list the resource.
16+
- type: markdown
17+
id: resource_info
18+
attributes:
19+
value: "## Resource info"
20+
- type: input
21+
id: resource_name
22+
attributes:
23+
label: Name
24+
description: Please provide the official name of the resource
25+
validations:
26+
required: true
27+
- type: input
28+
id: resource_url
29+
attributes:
30+
label: Resource URL
31+
description: Please provide a URL to the resource
32+
validations:
33+
required: true
34+
- type: textarea
35+
id: resource_description
36+
attributes:
37+
label: Description
38+
description: Please provide a short 1-2 sentence description of the resource
39+
validations:
40+
required: true
41+
- type: textarea
42+
id: resource_logo
43+
attributes:
44+
label: Logo
45+
description: |
46+
Please provide an SVG or transparent PNG
47+
Tip: You can attach images by clicking this area to highlight it and then dragging files in.
48+
- type: input
49+
id: resource_category
50+
attributes:
51+
label: Category
52+
description: Please specify a best fit to categorize the resource (e.g., DeFi, NFT, Scaling, etc.)
53+
- type: checkboxes
54+
id: resource_work_on
55+
attributes:
56+
label: Would you like to work on this issue?
57+
options:
58+
- label: "Yes"
59+
required: false
60+
- label: "No"
61+
required: false
62+
validations:
63+
required: true

app/[locale]/[...slug]/page.tsx

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import pick from "lodash.pick"
2+
import { notFound } from "next/navigation"
3+
import { getMessages, setRequestLocale } from "next-intl/server"
4+
5+
import I18nProvider from "@/components/I18nProvider"
6+
import mdComponents from "@/components/MdComponents"
7+
8+
import { dataLoader } from "@/lib/utils/data/dataLoader"
9+
import { dateToString } from "@/lib/utils/date"
10+
import { getPostSlugs } from "@/lib/utils/md"
11+
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
12+
13+
import { LOCALES_CODES } from "@/lib/constants"
14+
15+
import { componentsMapping, layoutMapping } from "@/layouts"
16+
import { fetchGFIs } from "@/lib/api/fetchGFIs"
17+
import { getPageData } from "@/lib/md/data"
18+
import { getMdMetadata } from "@/lib/md/metadata"
19+
20+
const loadData = dataLoader([["gfissues", fetchGFIs]])
21+
22+
function getLayoutFromSlug(slug: string) {
23+
if (slug.includes("developers/docs")) {
24+
return "docs"
25+
}
26+
27+
if (slug.includes("developers/tutorials")) {
28+
return "tutorial"
29+
}
30+
31+
return "static"
32+
}
33+
34+
export default async function Page({
35+
params,
36+
}: {
37+
params: Promise<{ locale: string; slug: string[] }>
38+
}) {
39+
const { locale, slug: slugArray } = await params
40+
41+
// Check if this specific path is in our valid paths
42+
const validPaths = await generateStaticParams()
43+
const isValidPath = validPaths.some(
44+
(path) =>
45+
path.locale === locale && path.slug.join("/") === slugArray.join("/")
46+
)
47+
48+
if (!isValidPath) {
49+
notFound()
50+
}
51+
52+
// Enable static rendering
53+
setRequestLocale(locale)
54+
55+
const [gfissues] = await loadData()
56+
57+
const slug = slugArray.join("/")
58+
59+
const {
60+
content,
61+
frontmatter,
62+
tocItems,
63+
lastEditLocaleTimestamp,
64+
isTranslated,
65+
contributors,
66+
} = await getPageData({
67+
locale,
68+
slug,
69+
// TODO: Address component typing error here (flip `FC` types to prop object types)
70+
// @ts-expect-error Incompatible component function signatures
71+
components: { ...mdComponents, ...componentsMapping },
72+
scope: {
73+
gfissues,
74+
},
75+
})
76+
77+
// Determine the actual layout after we have the frontmatter
78+
const layout = frontmatter.template || getLayoutFromSlug(slug)
79+
const Layout = layoutMapping[layout]
80+
81+
// If the page has a published date, format it
82+
if ("published" in frontmatter) {
83+
frontmatter.published = dateToString(frontmatter.published)
84+
}
85+
86+
// Get i18n messages
87+
const allMessages = await getMessages({ locale })
88+
const requiredNamespaces = getRequiredNamespacesForPage(slug, layout)
89+
const messages = pick(allMessages, requiredNamespaces)
90+
91+
return (
92+
<I18nProvider locale={locale} messages={messages}>
93+
<Layout
94+
slug={slug}
95+
frontmatter={frontmatter}
96+
tocItems={tocItems}
97+
lastEditLocaleTimestamp={lastEditLocaleTimestamp}
98+
contentNotTranslated={!isTranslated}
99+
contributors={contributors}
100+
// TODO: Remove this once we have a real timeToRead value
101+
timeToRead={2}
102+
>
103+
{content}
104+
</Layout>
105+
</I18nProvider>
106+
)
107+
}
108+
109+
export async function generateStaticParams() {
110+
const slugs = await getPostSlugs("/")
111+
112+
return LOCALES_CODES.flatMap((locale) =>
113+
slugs.map((slug) => ({
114+
slug: slug.split("/").slice(1),
115+
locale,
116+
}))
117+
)
118+
}
119+
120+
export const dynamicParams = false
121+
122+
export async function generateMetadata({
123+
params,
124+
}: {
125+
params: Promise<{ locale: string; slug: string[] }>
126+
}) {
127+
const { locale, slug } = await params
128+
129+
return await getMdMetadata({
130+
locale,
131+
slug,
132+
})
133+
}

app/[locale]/error.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use client"
2+
3+
import { useEffect } from "react"
4+
5+
import MainArticle from "@/components/MainArticle"
6+
import Translation from "@/components/Translation"
7+
import { Button } from "@/components/ui/buttons/Button"
8+
9+
export default function Error({
10+
error,
11+
reset,
12+
}: {
13+
error: Error
14+
reset: () => void
15+
}) {
16+
useEffect(() => {
17+
// TODO: log the error to an error reporting service
18+
console.error(error)
19+
}, [error])
20+
21+
return (
22+
<div className="mx-auto mb-0 mt-16 flex w-full flex-col items-center">
23+
<MainArticle className="my-8 w-full space-y-8 px-8 py-4">
24+
<h1>
25+
<Translation id="we-couldnt-find-that-page" />
26+
</h1>
27+
<p>Something went wrong.</p>
28+
<Button onClick={() => reset()}>Try again</Button>
29+
</MainArticle>
30+
</div>
31+
)
32+
}

app/[locale]/layout.tsx

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pick from "lodash.pick"
2+
import { notFound } from "next/navigation"
3+
import { getMessages, setRequestLocale } from "next-intl/server"
4+
5+
import { Lang } from "@/lib/types"
6+
7+
import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
8+
import { getLocaleTimestamp } from "@/lib/utils/time"
9+
10+
import Providers from "./providers"
11+
12+
import "@/styles/global.css"
13+
14+
import { routing } from "@/i18n/routing"
15+
import { BaseLayout } from "@/layouts/BaseLayout"
16+
17+
export default async function LocaleLayout({
18+
children,
19+
params: { locale },
20+
}: {
21+
children: React.ReactNode
22+
params: { locale: string }
23+
}) {
24+
if (!routing.locales.includes(locale)) {
25+
notFound()
26+
}
27+
28+
// Enable static rendering
29+
setRequestLocale(locale)
30+
31+
const allMessages = await getMessages({ locale })
32+
const messages = pick(allMessages, "common")
33+
34+
const lastDeployDate = getLastDeployDate()
35+
const lastDeployLocaleTimestamp = getLocaleTimestamp(
36+
locale as Lang,
37+
lastDeployDate
38+
)
39+
40+
return (
41+
<html lang={locale} suppressHydrationWarning>
42+
<body>
43+
<Providers locale={locale} messages={messages}>
44+
<BaseLayout lastDeployLocaleTimestamp={lastDeployLocaleTimestamp}>
45+
{children}
46+
</BaseLayout>
47+
</Providers>
48+
</body>
49+
</html>
50+
)
51+
}

app/[locale]/not-found.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import NotFoundPage from "@/components/NotFoundPage"
2+
3+
export default function NotFound() {
4+
return <NotFoundPage />
5+
}

app/[locale]/providers.tsx

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use client"
2+
3+
import { type AbstractIntlMessages } from "next-intl"
4+
5+
import I18nProvider from "@/components/I18nProvider"
6+
import ThemeProvider from "@/components/ThemeProvider"
7+
import { TooltipProvider } from "@/components/ui/tooltip"
8+
9+
import { FeedbackWidgetProvider } from "@/contexts/FeedbackWidgetContext"
10+
11+
export default function Providers({
12+
children,
13+
locale,
14+
messages,
15+
}: {
16+
children: React.ReactNode
17+
locale: string
18+
messages: AbstractIntlMessages
19+
}) {
20+
return (
21+
<I18nProvider locale={locale} messages={messages}>
22+
<ThemeProvider>
23+
<FeedbackWidgetProvider>
24+
<TooltipProvider>{children}</TooltipProvider>
25+
</FeedbackWidgetProvider>
26+
</ThemeProvider>
27+
</I18nProvider>
28+
)
29+
}

app/layout.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { ReactNode } from "react"
2+
3+
import "@/styles/global.css"
4+
5+
type Props = {
6+
children: ReactNode
7+
}
8+
9+
// Since we have a root `not-found.tsx` page, a layout file
10+
// is required, even if it's just passing children through.
11+
export default function RootLayout({ children }: Props) {
12+
return children
13+
}

app/not-found.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client"
2+
3+
import Error from "next/error"
4+
5+
import { DEFAULT_LOCALE } from "@/lib/constants"
6+
7+
export default function GlobalNotFound() {
8+
return (
9+
<html lang={DEFAULT_LOCALE}>
10+
<body>
11+
<Error statusCode={404} />
12+
</body>
13+
</html>
14+
)
15+
}

app/page.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { redirect } from "next/navigation"
2+
3+
import { routing } from "@/i18n/routing"
4+
5+
export default function Page() {
6+
redirect(routing.defaultLocale)
7+
}

docs/applying-storybook.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,4 @@ parameters: {
229229
}
230230
```
231231

232-
> 🚨 NOTE: This will be notated ahead of time by the team which stories should not receive snapshots.
232+
> 🚨 NOTE: This will be noted ahead of time by the team which stories should not receive snapshots.

docs/best-practices.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ How to prepare your content for translation depends on whether you're working on
88

99
**- MDX pages (`public/content/page/`)**
1010

11-
Markdown will be translated as whole pages of content, so no specific action is required. Simply create a new folder within `public/content/` with the name of the page, then place index markdown file (ie. `index.md`) within the new folder.
11+
Markdown will be translated as whole pages of content, so no specific action is required. Simply create a new folder within `public/content/` with the name of the page, then place an index markdown file (ie. `index.md`) within the new folder.
1212

1313
**- React component page**
1414

docs/header-ids.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ See a live example on ethereum.org: [https://ethereum.org/en/developers/docs/blo
3636

3737
### English content
3838

39-
These should be created for header on every new English markdown document.
39+
These should be created for header in every new English markdown document.
4040

4141
### Translated content
4242

docs/translation-program.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
_The Translation Program is an initiative to translate ethereum.org into different languages and make the website accessible to people from all over the world._
44

5-
If you are looking to get involved as a translator, you can [join our project in Crowdin](https://crowdin.com/project/ethereum-org/) and start translating the website to your language immediately.
5+
If you are looking to get involved as a translator, you can [join our project in Crowdin](https://crowdin.com/project/ethereum-org/) and start translating the website into your language immediately.
66

77
To get more information about the program, learn how to use Crowdin, check on the progress or find some useful tools for translators, please visit the [Translation Program page](https://ethereum.org/en/contributing/translation-program/).

0 commit comments

Comments
 (0)