Skip to content

Commit 6d0030b

Browse files
committed
adapt pages for next-intl
1 parent b176281 commit 6d0030b

37 files changed

+603
-215
lines changed

src/hooks/useTranslation.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,31 @@ import { useTranslations } from "next-intl"
1616

1717
const DEFAULT_NAMESPACE = "common"
1818

19-
export default function useTranslation(namespaces?: string[] | string) {
19+
export function useTranslation(namespaces?: string[] | string) {
2020
const t = useTranslations()
2121

2222
const customT: typeof t = (fullKey, values) => {
23-
if (fullKey.includes(":")) {
24-
const [namespace, key] = fullKey.split(":")
23+
try {
24+
if (fullKey.includes(":")) {
25+
const [namespace, key] = fullKey.split(":")
2526

26-
if (values) {
27-
return t(`${namespace}.${key}`, values)
28-
}
27+
if (values) {
28+
return t(`${namespace}.${key}`, values)
29+
}
2930

30-
return t.raw(`${namespace}.${key}`)
31-
}
31+
return t.raw(`${namespace}.${key}`)
32+
}
3233

33-
const namespace = Array.isArray(namespaces)
34-
? namespaces[0]
35-
: namespaces || DEFAULT_NAMESPACE
34+
const namespace = Array.isArray(namespaces)
35+
? namespaces[0]
36+
: namespaces || DEFAULT_NAMESPACE
3637

37-
return t.raw(`${namespace}.${fullKey}`)
38+
return t.raw(`${namespace}.${fullKey}`)
39+
} catch (error) {
40+
// Suppress errors by default, enable if needed to debug
41+
// console.error(error)
42+
return fullKey
43+
}
3844
}
3945

4046
// keep the original methods
@@ -45,3 +51,5 @@ export default function useTranslation(namespaces?: string[] | string) {
4551

4652
return { t: customT }
4753
}
54+
55+
export default useTranslation

src/i18n/loadNamespaces.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
1+
import { DEFAULT_LOCALE } from "@/lib/constants"
2+
13
export default async function loadNamespaces(
24
locale: string,
35
namespaces: string[]
46
) {
57
const byNamespace = await Promise.all(
68
namespaces.map(async (namespace) => {
7-
return (await import(`../intl/${locale}/${namespace}.json`)).default
9+
try {
10+
const defaultNamespace = (
11+
await import(`../intl/${DEFAULT_LOCALE}/${namespace}.json`)
12+
).default
13+
const localeNamespace = (
14+
await import(`../intl/${locale}/${namespace}.json`)
15+
).default
16+
17+
// Merge the namespaces to have default translations for keys that are not present in the locale
18+
return { ...defaultNamespace, ...localeNamespace }
19+
} catch (error) {
20+
// If the namespace is not found, return the default namespace
21+
return (await import(`../intl/${DEFAULT_LOCALE}/${namespace}.json`))
22+
.default
23+
}
824
})
925
)
1026

src/layouts/md/Roadmap.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { useTranslation } from "next-i18next"
2-
31
import type { ChildOnlyProp } from "@/lib/types"
42
import type { MdPageContent, RoadmapFrontmatter } from "@/lib/interfaces"
53

@@ -10,6 +8,7 @@ import RoadmapImageContent from "@/components/Roadmap/RoadmapImageContent"
108

119
import { ContentLayout } from "../ContentLayout"
1210

11+
import { useTranslation } from "@/hooks/useTranslation"
1312
import RoadmapHubHeroImage from "@/public/images/heroes/roadmap-hub-hero.jpg"
1413

1514
const CardGrid = (props: ChildOnlyProp) => (

src/layouts/md/Staking.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { HTMLAttributes } from "react"
2-
import { useTranslation } from "next-i18next"
32

43
import type { ChildOnlyProp } from "@/lib/types"
54
import type { MdPageContent, StakingFrontmatter } from "@/lib/interfaces"
@@ -26,6 +25,8 @@ import UpgradeStatus from "@/components/UpgradeStatus"
2625

2726
import { ContentLayout } from "../ContentLayout"
2827

28+
import { useTranslation } from "@/hooks/useTranslation"
29+
2930
const Heading1 = (props: HTMLAttributes<HTMLHeadingElement>) => (
3031
<MdHeading1 className="md:text-5xl" {...props} />
3132
)

src/layouts/md/Upgrade.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { useTranslation } from "next-i18next"
2-
31
import type { ChildOnlyProp } from "@/lib/types"
42
import type { MdPageContent, UpgradeFrontmatter } from "@/lib/interfaces"
53

@@ -14,6 +12,8 @@ import { getSummaryPoints } from "@/lib/utils/getSummaryPoints"
1412

1513
import { ContentLayout } from "../ContentLayout"
1614

15+
import { useTranslation } from "@/hooks/useTranslation"
16+
1717
// Upgrade layout components
1818
export const upgradeComponents = {
1919
MergeArticleList,
@@ -42,7 +42,7 @@ export const UpgradeLayout = ({
4242

4343
const dropdownLinks: ButtonDropdownList = {
4444
text: t("page-upgrades-upgrades-guide"),
45-
ariaLabel: t("page-upgrades-upgrades-aria-label"),
45+
ariaLabel: t("page-upgrades-index:page-upgrades-upgrades-aria-label"),
4646
items: [
4747
{
4848
text: t("page-upgrades-upgrades-beacon-chain"),

src/layouts/md/UseCases.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useRouter } from "next/router"
2-
import { useTranslation } from "next-i18next"
32

43
import type { ChildOnlyProp } from "@/lib/types"
54
import type { MdPageContent, UseCasesFrontmatter } from "@/lib/interfaces"
@@ -16,6 +15,8 @@ import { getSummaryPoints } from "@/lib/utils/getSummaryPoints"
1615

1716
import { ContentLayout } from "../ContentLayout"
1817

18+
import { useTranslation } from "@/hooks/useTranslation"
19+
1920
// UseCases layout components
2021
export const useCasesComponents = {
2122
// Export empty object if none needed

src/lib/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import allQuestionData from "@/data/quizzes/questionBank"
2828
import { screens } from "./utils/screen"
2929
import { WALLETS_FILTERS_DEFAULT } from "./constants"
3030

31-
import { layoutMapping } from "@/pages/[...slug]"
31+
import { layoutMapping } from "@/pages/[locale]/[...slug]"
3232

3333
// Credit: https://stackoverflow.com/a/52331580
3434
export type Unpacked<T> = T extends (infer U)[] ? U : T
@@ -58,6 +58,10 @@ export type Root = {
5858
export type BasePageProps = SSRConfig &
5959
Pick<Root, "contentNotTranslated" | "lastDeployLocaleTimestamp">
6060

61+
export type Params = {
62+
locale: string
63+
}
64+
6165
export type Frontmatter = RoadmapFrontmatter &
6266
UpgradeFrontmatter &
6367
StaticFrontmatter &

src/pages/404.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { GetStaticProps } from "next"
2-
import { serverSideTranslations } from "next-i18next/serverSideTranslations"
32

43
import { BasePageProps, Lang } from "@/lib/types"
54

@@ -12,7 +11,14 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
1211
import { getLocaleTimestamp } from "@/lib/utils/time"
1312
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
1413

15-
export const getStaticProps = (async ({ locale }) => {
14+
import { DEFAULT_LOCALE } from "@/lib/constants"
15+
16+
import loadNamespaces from "@/i18n/loadNamespaces"
17+
18+
export const getStaticProps = (async () => {
19+
// TODO: generate 404 pages for each locale when we finish the app router migration
20+
const locale = DEFAULT_LOCALE
21+
1622
const requiredNamespaces = getRequiredNamespacesForPage("/")
1723

1824
// Want to check common namespace, so looking at requiredNamespaces[0]
@@ -24,9 +30,11 @@ export const getStaticProps = (async ({ locale }) => {
2430
lastDeployDate
2531
)
2632

33+
const messages = await loadNamespaces(locale!, requiredNamespaces)
34+
2735
return {
2836
props: {
29-
...(await serverSideTranslations(locale!, requiredNamespaces)),
37+
messages,
3038
contentNotTranslated,
3139
lastDeployLocaleTimestamp,
3240
},

src/pages/[locale]/[...slug].tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import type {
88
InferGetStaticPropsType,
99
} from "next/types"
1010
import type { SSRConfig } from "next-i18next"
11-
import { serverSideTranslations } from "next-i18next/serverSideTranslations"
1211
import { MDXRemote, type MDXRemoteSerializeResult } from "next-mdx-remote"
1312
import { serialize } from "next-mdx-remote/serialize"
1413
import { getPlaiceholder } from "plaiceholder"
@@ -34,11 +33,11 @@ import { getLastDeployDate } from "@/lib/utils/getLastDeployDate"
3433
import { getContent, getContentBySlug } from "@/lib/utils/md"
3534
import { getLocaleTimestamp } from "@/lib/utils/time"
3635
import { remapTableOfContents } from "@/lib/utils/toc"
37-
import {
38-
filterRealLocales,
39-
getRequiredNamespacesForPage,
40-
} from "@/lib/utils/translations"
36+
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
37+
38+
import { LOCALES_CODES } from "@/lib/constants"
4139

40+
import loadNamespaces from "@/i18n/loadNamespaces"
4241
import {
4342
docsComponents,
4443
DocsLayout,
@@ -64,6 +63,7 @@ import remarkInferToc from "@/lib/rehype/remarkInferToc"
6463

6564
interface Params extends ParsedUrlQuery {
6665
slug: string[]
66+
locale: string
6767
}
6868

6969
export const layoutMapping = {
@@ -88,17 +88,17 @@ const componentsMapping = {
8888
tutorial: tutorialsComponents,
8989
} as const
9090

91-
export const getStaticPaths = (({ locales }) => {
91+
export const getStaticPaths = (() => {
9292
const contentFiles = getContent("/")
9393

9494
// Generate page paths for each supported locale
95-
const paths = filterRealLocales(locales).flatMap((locale) =>
95+
const paths = LOCALES_CODES.flatMap((locale) =>
9696
contentFiles.map((file) => ({
9797
params: {
9898
// Splitting nested paths to generate proper slug
9999
slug: file.slug.split("/").slice(1),
100+
locale,
100101
},
101-
locale,
102102
}))
103103
)
104104

@@ -120,7 +120,7 @@ const loadData = dataLoader([["gfissues", fetchGFIs]])
120120

121121
export const getStaticProps = (async (context) => {
122122
const params = context.params!
123-
const { locale } = context
123+
const { locale } = params
124124

125125
const markdown = getContentBySlug(`${locale}/${params.slug.join("/")}`)
126126
const frontmatter = markdown.frontmatter
@@ -198,9 +198,11 @@ export const getStaticProps = (async (context) => {
198198

199199
const [gfissues] = await loadData()
200200

201+
const messages = await loadNamespaces(locale, requiredNamespaces)
202+
201203
return {
202204
props: {
203-
...(await serverSideTranslations(locale!, requiredNamespaces)),
205+
messages,
204206
mdxSource,
205207
slug,
206208
frontmatter,

src/pages/[locale]/assets.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { HTMLAttributes } from "react"
22
import type { GetStaticProps } from "next/types"
3-
import { useTranslation } from "next-i18next"
4-
import { serverSideTranslations } from "next-i18next/serverSideTranslations"
53

6-
import type { BasePageProps, ChildOnlyProp, Lang } from "@/lib/types"
4+
import type { BasePageProps, ChildOnlyProp, Lang, Params } from "@/lib/types"
75

86
import AssetDownload from "@/components/AssetDownload"
97
import FeedbackCard from "@/components/FeedbackCard"
@@ -28,7 +26,11 @@ import { getLocaleTimestamp } from "@/lib/utils/time"
2826
// import leslieTheRhino from "@/public/images/upgrades/upgrade_rhino.png"
2927
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
3028

29+
import { DEFAULT_LOCALE, LOCALES_CODES } from "@/lib/constants"
30+
3131
import useColorModeValue from "@/hooks/useColorModeValue"
32+
import { useTranslation } from "@/hooks/useTranslation"
33+
import loadNamespaces from "@/i18n/loadNamespaces"
3234
import ethDiamondBlack from "@/public/images/assets/eth-diamond-black.png"
3335
import ethDiamondBlackGray from "@/public/images/assets/eth-diamond-black-gray.png"
3436
import ethDiamondBlackWhite from "@/public/images/assets/eth-diamond-black-white.jpg"
@@ -96,7 +98,16 @@ const H3 = (props: ChildOnlyProp) => (
9698
<h3 className="mb-0 mt-10 leading-xs" {...props} />
9799
)
98100

99-
export const getStaticProps = (async ({ locale }) => {
101+
export async function getStaticPaths() {
102+
return {
103+
paths: LOCALES_CODES.map((locale) => ({ params: { locale } })),
104+
fallback: false,
105+
}
106+
}
107+
108+
export const getStaticProps = (async ({ params }) => {
109+
const { locale = DEFAULT_LOCALE } = params || {}
110+
100111
const requiredNamespaces = getRequiredNamespacesForPage("assets")
101112

102113
const contentNotTranslated = !existsNamespace(locale!, requiredNamespaces[2])
@@ -107,14 +118,16 @@ export const getStaticProps = (async ({ locale }) => {
107118
lastDeployDate
108119
)
109120

121+
const messages = await loadNamespaces(locale, requiredNamespaces)
122+
110123
return {
111124
props: {
112-
...(await serverSideTranslations(locale!, requiredNamespaces)),
125+
messages,
113126
contentNotTranslated,
114127
lastDeployLocaleTimestamp,
115128
},
116129
}
117-
}) satisfies GetStaticProps<BasePageProps>
130+
}) satisfies GetStaticProps<BasePageProps, Params>
118131

119132
const AssetsPage = () => {
120133
// Ignore locale in the URL for SVG path in public directory to fix broken link

0 commit comments

Comments
 (0)