From 672f07983e1c2cd61c7c85685c14896bf564699f Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Tue, 19 Aug 2025 10:41:19 -0600 Subject: [PATCH 1/3] setup /apps page and components for translation --- .../apps/_components/SuggestAnApp.tsx | 14 ++-- app/[locale]/apps/_components/TopApps.tsx | 7 +- app/[locale]/apps/page.tsx | 37 +++++---- src/data/apps/categories.ts | 79 ++++++++----------- src/intl/en/page-apps.json | 50 +++++++++++- 5 files changed, 113 insertions(+), 74 deletions(-) diff --git a/app/[locale]/apps/_components/SuggestAnApp.tsx b/app/[locale]/apps/_components/SuggestAnApp.tsx index d249f1ff4d8..9367bbaa540 100644 --- a/app/[locale]/apps/_components/SuggestAnApp.tsx +++ b/app/[locale]/apps/_components/SuggestAnApp.tsx @@ -1,20 +1,20 @@ +import { getTranslations } from "next-intl/server" + import { ButtonLink } from "@/components/ui/buttons/Button" -const SuggestAnApp = () => { +const SuggestAnApp = async () => { + const t = await getTranslations("page-apps") return (
-

Suggest an app

-

- We're always looking for new apps to add to our list. If you know - of an app that you think should be on the list, please let us know. -

+

{t("page-apps-suggest-an-app-title")}

+

{t("page-apps-suggest-an-app-description")}

- Suggest an app + {t("page-apps-suggest-an-app-button")}
) diff --git a/app/[locale]/apps/_components/TopApps.tsx b/app/[locale]/apps/_components/TopApps.tsx index fb2210a69a8..1bc145fe736 100644 --- a/app/[locale]/apps/_components/TopApps.tsx +++ b/app/[locale]/apps/_components/TopApps.tsx @@ -23,11 +23,14 @@ import AppCard from "./AppCard" import { useBreakpointValue } from "@/hooks/useBreakpointValue" import { useIsClient } from "@/hooks/useIsClient" +import useTranslation from "@/hooks/useTranslation" + interface TopAppsProps { appsData: Record } const TopApps = ({ appsData }: TopAppsProps) => { + const { t } = useTranslation("page-apps") const isClient = useIsClient() const cardStyling = useBreakpointValue({ base: { @@ -119,7 +122,7 @@ const TopApps = ({ appsData }: TopAppsProps) => { })()}

- {category} + {t(appsCategories[category].name)}

@@ -129,7 +132,7 @@ const TopApps = ({ appsData }: TopAppsProps) => { size="sm" className="w-fit" > -

See all

+

{t("page-apps-see-all")}

diff --git a/app/[locale]/apps/page.tsx b/app/[locale]/apps/page.tsx index 5d8f24f7652..a3f6658debd 100644 --- a/app/[locale]/apps/page.tsx +++ b/app/[locale]/apps/page.tsx @@ -1,5 +1,9 @@ import { pick } from "lodash" -import { getMessages, setRequestLocale } from "next-intl/server" +import { + getMessages, + getTranslations, + setRequestLocale, +} from "next-intl/server" import Breadcrumbs from "@/components/Breadcrumbs" import { SimpleHero } from "@/components/Hero" @@ -49,6 +53,9 @@ const Page = async ({ params }: { params: { locale: string } }) => { // Get 6 random staff pick apps const discoverApps = getDiscoverApps(appsData, 6) + // Get translations + const t = await getTranslations({ locale, namespace: "page-apps" }) + // Get i18n messages const allMessages = await getMessages({ locale }) const requiredNamespaces = getRequiredNamespacesForPage("/apps") @@ -57,12 +64,12 @@ const Page = async ({ params }: { params: { locale: string } }) => { } - title="Apps" - subtitle="Discover a list of curated applications that run on ethereum and layer 2 networks" + title={t("page-apps-title")} + subtitle={t("page-apps-subtitle")} buttons={[ { href: "/what-are-apps/", - label: "Learn about apps", + label: t("page-apps-learn-button"), variant: "outline", isSecondary: true, }, @@ -71,12 +78,12 @@ const Page = async ({ params }: { params: { locale: string } }) => {
-

Highlights

+

{t("page-apps-highlights-title")}

-

Discover

+

{t("page-apps-discover-title")}

{discoverApps.map((app) => ( {
-

Applications

+

{t("page-apps-applications-title")}

{/* Note: Implemented this instead of swiper from design to allow for SSR */}
-

Application categories

+

{t("page-apps-categories-title")}

{Object.values(appsCategories).map((category) => ( } href={`/apps/categories/${category.slug}`} matomoEvent={{ eventCategory: "apps", eventAction: "categories", - eventName: `category name ${category.name}`, + eventName: `category name ${t(category.name)}`, }} /> ))} @@ -118,7 +125,7 @@ const Page = async ({ params }: { params: { locale: string } }) => {
-

Community picks

+

{t("page-apps-community-picks-title")}

@@ -136,13 +143,13 @@ export async function generateMetadata({ params: Promise<{ locale: string }> }) { const { locale } = await params + const t = await getTranslations({ locale, namespace: "page-apps" }) return await getMetadata({ locale, slug: ["apps"], - title: "Top crypto apps on Ethereum", - description: - "Discover crypto apps on ethereum: explore DeFi, NFTs, Social, Gaming, Bridges, Privacy, Productivity & DAO dApps. Find trusted on-chain apps to trade, earn, and interact.", + title: t("page-apps-meta-title"), + description: t("page-apps-meta-description"), }) } diff --git a/src/data/apps/categories.ts b/src/data/apps/categories.ts index 83e908d3b80..ea3a917ac1f 100644 --- a/src/data/apps/categories.ts +++ b/src/data/apps/categories.ts @@ -13,82 +13,67 @@ import { slugify } from "@/lib/utils/url" export const appsCategories: AppCategories = { [AppCategoryEnum.DEFI]: { - name: "DeFi", + name: "page-apps-category-defi-name", icon: DeFiIcon, slug: slugify(AppCategoryEnum.DEFI), - description: - "DeFi is a category of decentralized applications that allow users to lend, borrow, trade, and earn interest on their crypto assets.", - metaTitle: "List of ethereum DeFi apps — Lending, Borrowing & Yield", - metaDescription: - "Explore top DeFi apps on Ethereum for lending, borrowing, stablecoin issuance, credit and on-chain DEX trading.", + description: "page-apps-category-defi-description", + metaTitle: "page-apps-category-defi-meta-title", + metaDescription: "page-apps-category-defi-meta-description", }, [AppCategoryEnum.COLLECTIBLE]: { - name: "Collectibles", + name: "page-apps-category-collectibles-name", icon: CollectiblesIcon, slug: slugify(AppCategoryEnum.COLLECTIBLE), - description: - "Collectibles are digital assets that are unique and cannot be replicated.", - metaTitle: "List of best NFT apps on ethereum", - metaDescription: - "Explore top NFT apps for buying collectibles, trading gaming skins, and discovering new digital assets across leading Ethereum marketplaces.", + description: "page-apps-category-collectibles-description", + metaTitle: "page-apps-category-collectibles-meta-title", + metaDescription: "page-apps-category-collectibles-meta-description", }, [AppCategoryEnum.SOCIAL]: { - name: "Social", + name: "page-apps-category-social-name", icon: SocialIcon, slug: slugify(AppCategoryEnum.SOCIAL), - description: - "Social is a category of decentralized applications that allow users to connect with others and share content.", - metaTitle: "Social apps on ethereum: farcaster, zora and more", - metaDescription: "Explore best messaging and social apps on ethereum.", + description: "page-apps-category-social-description", + metaTitle: "page-apps-category-social-meta-title", + metaDescription: "page-apps-category-social-meta-description", }, [AppCategoryEnum.GAMING]: { - name: "Gaming", + name: "page-apps-category-gaming-name", icon: GamingIcon, slug: slugify(AppCategoryEnum.GAMING), - description: - "Gaming is a category of decentralized applications that allow users to play games and earn rewards.", - metaTitle: "List of crypto and NFT games on ethereum", - metaDescription: - "Discover the best blockchain games that are fun to play. MMORPG, card games, AI gaming, RPG, casual games", + description: "page-apps-category-gaming-description", + metaTitle: "page-apps-category-gaming-meta-title", + metaDescription: "page-apps-category-gaming-meta-description", }, [AppCategoryEnum.BRIDGE]: { - name: "Bridge", + name: "page-apps-category-bridge-name", icon: BridgeIcon, slug: slugify(AppCategoryEnum.BRIDGE), - description: - "Bridge is a category of decentralized applications that allow users to bridge their assets between different networks.", - metaTitle: "List of ethereum bridges to different networks", - metaDescription: - "Discover the best crypto bridge app to move your assets between different networks and layer 2s.", + description: "page-apps-category-bridge-description", + metaTitle: "page-apps-category-bridge-meta-title", + metaDescription: "page-apps-category-bridge-meta-description", }, [AppCategoryEnum.PRODUCTIVITY]: { - name: "Productivity", + name: "page-apps-category-productivity-name", icon: ProductivityIcon, slug: slugify(AppCategoryEnum.PRODUCTIVITY), - description: - "Productivity is a category of decentralized applications that allow users to be productive.", - metaTitle: "Productivity and decentralized identity apps", - metaDescription: - "Explore top Ethereum apps for decentralized identity, storage, DNS, and video computing. Boost your on-chain productivity with trusted infrastructure tools.", + description: "page-apps-category-productivity-description", + metaTitle: "page-apps-category-productivity-meta-title", + metaDescription: "page-apps-category-productivity-meta-description", }, [AppCategoryEnum.PRIVACY]: { - name: "Privacy", + name: "page-apps-category-privacy-name", icon: PrivacyIcon, slug: slugify(AppCategoryEnum.PRIVACY), - description: - "Privacy is a category of decentralized applications that allow users to be private.", - metaTitle: "Ethereum privacy apps: tornado cash and others", - metaDescription: - "Explore Ethereum privacy apps like Tornado Cash and others that protect user anonymity, enable private transactions, and enhance on-chain confidentiality.", + description: "page-apps-category-privacy-description", + metaTitle: "page-apps-category-privacy-meta-title", + metaDescription: "page-apps-category-privacy-meta-description", }, [AppCategoryEnum.GOVERNANCE_DAO]: { - name: "DAO", + name: "page-apps-category-dao-name", icon: GovernanceIcon, slug: slugify(AppCategoryEnum.GOVERNANCE_DAO), - description: - "DAO is a category of decentralized applications that allow users to govern and create decentralized autonomous organizations.", - metaTitle: "List of DAO tools on ethereum", - metaDescription: - "Discover top DAO tools on Ethereum for governance, treasury management, voting, and contributor coordination. Launch, manage, and grow your decentralized organization.", + description: "page-apps-category-dao-description", + metaTitle: "page-apps-category-dao-meta-title", + metaDescription: "page-apps-category-dao-meta-description", }, } diff --git a/src/intl/en/page-apps.json b/src/intl/en/page-apps.json index ef36be7e20b..fe158f56d2e 100644 --- a/src/intl/en/page-apps.json +++ b/src/intl/en/page-apps.json @@ -6,8 +6,52 @@ "page-apps-dapp-description-gods-unchained": "Strategic trading card game. Earn cards by playing that you can sell in real life.", "page-apps-dapp-description-augur": "Bet on outcomes. Trade on information markets.", "page-apps-ready-button": "Go", - "page-apps-meta-title": "Ethereum Apps - Discover Decentralized Applications", - "page-apps-meta-description": "Explore a curated list of decentralized applications (dapps) that run on Ethereum and Layer 2 networks. Find DeFi, NFT, gaming, and other Web3 applications.", "foundation": "Foundation", - "page-wallets-get-some": "Get some ETH" + "page-wallets-get-some": "Get some ETH", + "page-apps-title": "Apps", + "page-apps-subtitle": "Discover a list of curated applications that run on ethereum and layer 2 networks", + "page-apps-learn-button": "Learn about apps", + "page-apps-highlights-title": "Highlights", + "page-apps-discover-title": "Discover", + "page-apps-applications-title": "Applications", + "page-apps-categories-title": "Application categories", + "page-apps-community-picks-title": "Community picks", + "page-apps-meta-title": "Top crypto apps on Ethereum", + "page-apps-meta-description": "Discover crypto apps on ethereum: explore DeFi, NFTs, Social, Gaming, Bridges, Privacy, Productivity & DAO dApps. Find trusted onchain apps to trade, earn, and interact.", + "page-apps-category-defi-name": "DeFi", + "page-apps-category-defi-description": "DeFi is a category of decentralized applications that allow users to lend, borrow, trade, and earn interest on their crypto assets.", + "page-apps-category-defi-meta-title": "List of ethereum DeFi apps — Lending, Borrowing & Yield", + "page-apps-category-defi-meta-description": "Explore top DeFi apps on Ethereum for lending, borrowing, stablecoin issuance, credit and on-chain DEX trading.", + "page-apps-category-collectibles-name": "Collectibles", + "page-apps-category-collectibles-description": "Collectibles are digital assets that are unique and cannot be replicated.", + "page-apps-category-collectibles-meta-title": "List of best NFT apps on ethereum", + "page-apps-category-collectibles-meta-description": "Explore top NFT apps for buying collectibles, trading gaming skins, and discovering new digital assets across leading Ethereum marketplaces.", + "page-apps-category-social-name": "Social", + "page-apps-category-social-description": "Social is a category of decentralized applications that allow users to connect with others and share content.", + "page-apps-category-social-meta-title": "Social apps on ethereum: farcaster, zora and more", + "page-apps-category-social-meta-description": "Explore best messaging and social apps on ethereum.", + "page-apps-category-gaming-name": "Gaming", + "page-apps-category-gaming-description": "Gaming is a category of decentralized applications that allow users to play games and earn rewards.", + "page-apps-category-gaming-meta-title": "List of crypto and NFT games on ethereum", + "page-apps-category-gaming-meta-description": "Discover the best blockchain games that are fun to play. MMORPG, card games, AI gaming, RPG, casual games", + "page-apps-category-bridge-name": "Bridge", + "page-apps-category-bridge-description": "Bridge is a category of decentralized applications that allow users to bridge their assets between different networks.", + "page-apps-category-bridge-meta-title": "List of ethereum bridges to different networks", + "page-apps-category-bridge-meta-description": "Discover the best crypto bridge app to move your assets between different networks and layer 2s.", + "page-apps-category-productivity-name": "Productivity", + "page-apps-category-productivity-description": "Productivity is a category of decentralized applications that allow users to be productive.", + "page-apps-category-productivity-meta-title": "Productivity and decentralized identity apps", + "page-apps-category-productivity-meta-description": "Explore top Ethereum apps for decentralized identity, storage, DNS, and video computing. Boost your on-chain productivity with trusted infrastructure tools.", + "page-apps-category-privacy-name": "Privacy", + "page-apps-category-privacy-description": "Privacy is a category of decentralized applications that allow users to be private.", + "page-apps-category-privacy-meta-title": "Ethereum privacy apps: tornado cash and others", + "page-apps-category-privacy-meta-description": "Explore Ethereum privacy apps like Tornado Cash and others that protect user anonymity, enable private transactions, and enhance on-chain confidentiality.", + "page-apps-category-dao-name": "DAO", + "page-apps-category-dao-description": "DAO is a category of decentralized applications that allow users to govern and create decentralized autonomous organizations.", + "page-apps-category-dao-meta-title": "List of DAO tools on ethereum", + "page-apps-category-dao-meta-description": "Discover top DAO tools on Ethereum for governance, treasury management, voting, and contributor coordination. Launch, manage, and grow your decentralized organization.", + "page-apps-see-all": "See all", + "page-apps-suggest-an-app-title": "Suggest an app", + "page-apps-suggest-an-app-description": "We're always looking for new apps to add to our list. If you know of an app that you think should be on the list, please let us know.", + "page-apps-suggest-an-app-button": "Suggest an app" } \ No newline at end of file From 9120b097eb145c2aad41d6df21cc3ede46e838e2 Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Tue, 19 Aug 2025 10:56:59 -0600 Subject: [PATCH 2/3] setup /app/categories/{category} for translation --- app/[locale]/apps/[application]/page.tsx | 2 +- app/[locale]/apps/_components/AppsTable.tsx | 9 ++++--- .../apps/_components/CategoriesNav.tsx | 18 ++++++++++--- .../apps/categories/[catetgoryName]/page.tsx | 25 +++++++++++++------ src/intl/en/page-apps.json | 5 +++- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/app/[locale]/apps/[application]/page.tsx b/app/[locale]/apps/[application]/page.tsx index 7b02b409d0a..fafacdf0c81 100644 --- a/app/[locale]/apps/[application]/page.tsx +++ b/app/[locale]/apps/[application]/page.tsx @@ -275,7 +275,7 @@ const Page = async ({ {nextApp && (
-

See next

+

See next

{nextApp.name}

diff --git a/app/[locale]/apps/_components/AppsTable.tsx b/app/[locale]/apps/_components/AppsTable.tsx index 4a56810ec83..0746c3b2938 100644 --- a/app/[locale]/apps/_components/AppsTable.tsx +++ b/app/[locale]/apps/_components/AppsTable.tsx @@ -16,7 +16,10 @@ import { trackCustomEvent } from "@/lib/utils/matomo" import AppCard from "./AppCard" +import useTranslation from "@/hooks/useTranslation" + const AppsTable = ({ apps }: { apps: AppData[] }) => { + const { t } = useTranslation("page-apps") const [filterBy, setFilterBy] = useState("All") const subCategories = useMemo( @@ -41,7 +44,7 @@ const AppsTable = ({ apps }: { apps: AppData[] }) => {
-

Filter by

+

{t("page-apps-filter-by")}