Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1920fc8
fix(i18n): translate subcategory tags
myelinated-wackerow Mar 29, 2026
e6fa38f
i18n(ar): Gemini translation
wackerow Mar 29, 2026
1f8aed6
i18n(bn): Gemini translation
wackerow Mar 29, 2026
e73fd5f
i18n(cs): Gemini translation
wackerow Mar 29, 2026
a312eb2
i18n(de): Gemini translation
wackerow Mar 29, 2026
a88916a
i18n(es): Gemini translation
wackerow Mar 29, 2026
d85bc1d
i18n(fr): Gemini translation
wackerow Mar 29, 2026
2632a2c
i18n(hi): Gemini translation
wackerow Mar 29, 2026
c88b118
i18n(id): Gemini translation
wackerow Mar 29, 2026
586601e
i18n(it): Gemini translation
wackerow Mar 29, 2026
98d1299
i18n(ja): Gemini translation
wackerow Mar 29, 2026
e46bcbf
i18n(ko): Gemini translation
wackerow Mar 29, 2026
8201095
i18n(mr): Gemini translation
wackerow Mar 29, 2026
754706f
i18n(pl): Gemini translation
wackerow Mar 29, 2026
1f0d32f
i18n(pt-br): Gemini translation
wackerow Mar 29, 2026
3a75bd9
i18n(ru): Gemini translation
wackerow Mar 29, 2026
0cfa632
i18n(sw): Gemini translation
wackerow Mar 29, 2026
3d3b46e
i18n(ta): Gemini translation
wackerow Mar 29, 2026
5b9909f
i18n(te): Gemini translation
wackerow Mar 29, 2026
37218ae
i18n(tr): Gemini translation
wackerow Mar 29, 2026
45f1408
i18n(uk): Gemini translation
wackerow Mar 29, 2026
3f7f48b
i18n(ur): Gemini translation
wackerow Mar 29, 2026
9777787
i18n(vi): Gemini translation
wackerow Mar 29, 2026
39bc62f
i18n(zh): Gemini translation
wackerow Mar 29, 2026
be2a9fc
i18n(zh-tw): Gemini translation
wackerow Mar 29, 2026
bfa79f5
fix(i18n): fix subcategory translation errors
myelinated-wackerow Mar 31, 2026
bac60e3
Merge pull request #17892 from ethereum/i18n/translations-03-29T0230
wackerow Apr 1, 2026
1d071b6
fix(i18n): translate subcategory tags on /apps/
myelinated-wackerow Apr 1, 2026
f0da355
Merge remote-tracking branch 'origin/dev' into pr-17891-sub-tags
myelinated-wackerow Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions app/[locale]/apps/categories/[catetgoryName]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {

import {
AppCategoryEnum,
type AppData,
type Lang,
type PageParams,
type SectionNavDetails,
Expand All @@ -30,6 +31,7 @@ import { getHighlightedApps } from "@/lib/utils/apps"
import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { slugify } from "@/lib/utils/url"

import { appsCategories } from "@/data/apps/categories"

Expand Down Expand Up @@ -62,6 +64,7 @@ const Page = async (props: {
}

const t = await getTranslations("page-apps")
const tSubcategory = await getTranslations("app-subcategories")

// Get i18n messages
const allMessages = await getMessages({ locale })
Expand All @@ -86,6 +89,12 @@ const Page = async (props: {
notFound()
}

// Translate subcategory tags, falling back to the raw string
const translateSubcategories = (tag: string) => {
const key = `subcategory-${slugify(tag)}`
return tSubcategory.has(key) ? tSubcategory(key) : tag
}

// Get highlighted apps (apps with highlight=true)
const highlightedApps = getHighlightedApps(
appsData,
Expand Down Expand Up @@ -160,13 +169,25 @@ const Page = async (props: {
<div className="flex flex-col px-4 md:px-8">
<h2>{t("page-apps-highlights-title")}</h2>
<AppsHighlight
apps={highlightedApps}
apps={
highlightedApps.map((app) => ({
...app,
subCategory: app.subCategory.map(translateSubcategories),
})) as AppData[]
}
matomoCategory={`category_page`}
/>
</div>

<div className="flex flex-col px-4 md:px-8">
<AppsTable apps={appsData[categoryEnum]} />
<AppsTable
apps={
appsData[categoryEnum].map((app) => ({
...app,
subCategory: app.subCategory.map(translateSubcategories),
})) as AppData[]
}
/>
</div>

<div className="flex flex-col px-4 md:px-8">
Expand Down
30 changes: 25 additions & 5 deletions app/[locale]/apps/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
setRequestLocale,
} from "next-intl/server"

import { Lang, PageParams } from "@/lib/types"
import { AppCategory, AppData, Lang, PageParams } from "@/lib/types"

import AppCard from "@/components/AppCard"
import Breadcrumbs from "@/components/Breadcrumbs"
Expand Down Expand Up @@ -62,6 +62,26 @@ const Page = async (props: { params: Promise<PageParams> }) => {

// Get translations
const t = await getTranslations("page-apps")
const tSubcategory = await getTranslations("app-subcategories")

// Translate subcategory tags, falling back to the raw string
const translateSubcategories = (tag: string) => {
const key = `subcategory-${slugify(tag)}`
return tSubcategory.has(key) ? tSubcategory(key) : tag
}

const translateApp = (app: AppData) =>
({
...app,
subCategory: app.subCategory.map(translateSubcategories),
}) as AppData

const translatedAppsData = Object.fromEntries(
Object.entries(appsData).map(([category, apps]) => [
category,
(apps as AppData[]).map(translateApp),
])
) as Record<AppCategory, AppData[]>

// Get i18n messages
const allMessages = await getMessages({ locale })
Expand Down Expand Up @@ -94,7 +114,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
<MainArticle className="flex flex-col gap-32 py-10">
<div className="flex flex-col gap-8 px-4 md:px-8">
<h2>{t("page-apps-highlights-title")}</h2>
<AppsHighlight apps={highlightedApps} matomoCategory="apps" />
<AppsHighlight apps={highlightedApps.map(translateApp)} matomoCategory="apps" />
</div>

<div className="flex flex-col gap-4 px-4 md:px-8">
Expand All @@ -108,7 +128,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
thumbnail={app.image}
category={app.category}
categoryTagStatus={APP_TAG_VARIANTS[app.category]}
tags={app.subCategory}
tags={app.subCategory.map(translateSubcategories)}
href={`/apps/${slugify(app.name)}`}
imageSize="large"
customEventOptions={{
Expand All @@ -128,7 +148,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {

<div className="flex flex-col gap-4 px-4 md:px-8">
<h2>{t("page-apps-applications-title")}</h2>
<TopApps appsData={appsData} />
<TopApps appsData={translatedAppsData} />
</div>

{/* Note: Implemented this instead of swiper from design to allow for SSR */}
Expand Down Expand Up @@ -156,7 +176,7 @@ const Page = async (props: { params: Promise<PageParams> }) => {
<h2>{t("page-apps-community-picks-title")}</h2>
<CommunityPicks
communityPicks={communityPicks}
appsData={appsData}
appsData={translatedAppsData}
/>
</div>

Expand Down
50 changes: 50 additions & 0 deletions src/intl/ar/app-subcategories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"subcategory-mmorpg": "MMORPG",
"subcategory-rpg": "RPG",
"subcategory-strategy": "استراتيجية",
"subcategory-multiplayer": "متعددة اللاعبين",
"subcategory-onchain": "على السلسلة",
"subcategory-casual": "ألعاب خفيفة",
"subcategory-retro-gaming": "ألعاب كلاسيكية",
"subcategory-ai-gaming": "ألعاب الذكاء الاصطناعي",
"subcategory-action": "أكشن",
"subcategory-adventure": "مغامرة",
"subcategory-card-deck-building": "بطاقات وبناء مجموعات",
"subcategory-text-based": "نصية",
"subcategory-roguelike": "روجلايك",
"subcategory-shooter": "تصويب",
"subcategory-metaverse": "ميتافيرس",
"subcategory-simulation-and-management": "محاكاة وإدارة",
"subcategory-sports-and-fantasy": "رياضة وفانتازيا",
"subcategory-lending": "إقراض",
"subcategory-lending-and-borrowing": "إقراض واقتراض",
"subcategory-liquid-staking": "التحصيص السائل",
"subcategory-dex": "DEX",
"subcategory-insurance": "تأمين",
"subcategory-prediction": "توقع",
"subcategory-rwa": "RWA",
"subcategory-ip": "IP",
"subcategory-art": "فن",
"subcategory-gaming": "ألعاب",
"subcategory-media": "وسائط",
"subcategory-membership": "عضوية",
"subcategory-market": "سوق",
"subcategory-social-network": "شبكة اجتماعية",
"subcategory-video": "فيديو",
"subcategory-messaging": "مراسلة",
"subcategory-identity": "هوية",
"subcategory-native": "أصلي",
"subcategory-validator-or-oracle": "مُدقِّق أو خدمة أوراكل",
"subcategory-generalized-message-passing": "تمرير الرسائل المعمم",
"subcategory-liquidity-network": "شبكة السيولة",
"subcategory-chain-abstraction": "تجريد السلسلة",
"subcategory-dns": "DNS",
"subcategory-pools": "مجمعات",
"subcategory-payments": "مدفوعات",
"subcategory-rpc": "RPC",
"subcategory-stealth-address": "عنوان متخفي",
"subcategory-governance": "الحوكمة",
"subcategory-delegation": "تفويض",
"subcategory-offchain-voting": "تصويت خارج السلسلة",
"subcategory-organization": "منظمة"
}
35 changes: 34 additions & 1 deletion src/intl/bn/app-subcategories.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,38 @@
"subcategory-text-based": "টেক্সট-ভিত্তিক",
"subcategory-roguelike": "রোগলাইক",
"subcategory-shooter": "শুটার",
"subcategory-metaverse": "মেটাভার্স"
"subcategory-metaverse": "মেটাভার্স",
"subcategory-simulation-and-management": "সিমুলেশন এবং ম্যানেজমেন্ট",
"subcategory-sports-and-fantasy": "স্পোর্টস এবং ফ্যান্টাসি",
"subcategory-lending": "লেন্ডিং",
"subcategory-lending-and-borrowing": "লেন্ডিং এবং বরোয়িং",
"subcategory-liquid-staking": "লিকুইড স্টেকিং",
"subcategory-dex": "DEX",
"subcategory-insurance": "ইন্স্যুরেন্স",
"subcategory-prediction": "প্রেডিকশন",
"subcategory-rwa": "RWA",
"subcategory-ip": "IP",
"subcategory-art": "আর্ট",
"subcategory-gaming": "গেমিং",
"subcategory-media": "মিডিয়া",
"subcategory-membership": "মেম্বারশিপ",
"subcategory-market": "মার্কেট",
"subcategory-social-network": "সোশ্যাল নেটওয়ার্ক",
"subcategory-video": "ভিডিও",
"subcategory-messaging": "মেসেজিং",
"subcategory-identity": "আইডেন্টিটি",
"subcategory-native": "নেটিভ",
"subcategory-validator-or-oracle": "ভ্যালিডেটর বা ওরাকল",
"subcategory-generalized-message-passing": "জেনারেলাইজড মেসেজ পাসিং",
"subcategory-liquidity-network": "লিকুইডিটি নেটওয়ার্ক",
"subcategory-chain-abstraction": "চেইন অ্যাবস্ট্রাকশন",
"subcategory-dns": "DNS",
"subcategory-pools": "পুলস",
"subcategory-payments": "পেমেন্টস",
"subcategory-rpc": "RPC",
"subcategory-stealth-address": "স্টিলথ এডড্রেস",
"subcategory-governance": "গভর্নেন্স",
"subcategory-delegation": "ডেলিগেশন",
"subcategory-offchain-voting": "অফচেইন ভোটিং",
"subcategory-organization": "অর্গানাইজেশন"
}
50 changes: 50 additions & 0 deletions src/intl/cs/app-subcategories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"subcategory-mmorpg": "MMORPG",
"subcategory-rpg": "RPG",
"subcategory-strategy": "Strategie",
"subcategory-multiplayer": "Multiplayer",
"subcategory-onchain": "Na blockchainu",
"subcategory-casual": "Oddechové",
"subcategory-retro-gaming": "Retro hry",
"subcategory-ai-gaming": "AI hry",
"subcategory-action": "Akční",
"subcategory-adventure": "Dobrodružné",
"subcategory-card-deck-building": "Karetní a deck-building",
"subcategory-text-based": "Textové",
"subcategory-roguelike": "Roguelike",
"subcategory-shooter": "Střílečky",
"subcategory-metaverse": "Metaverse",
"subcategory-simulation-and-management": "Simulace a management",
"subcategory-sports-and-fantasy": "Sportovní a fantasy",
"subcategory-lending": "Půjčování",
"subcategory-lending-and-borrowing": "Půjčování a výpůjčky",
"subcategory-liquid-staking": "Likvidní staking",
"subcategory-dex": "DEX",
"subcategory-insurance": "Pojištění",
"subcategory-prediction": "Predikce",
"subcategory-rwa": "RWA",
"subcategory-ip": "IP",
"subcategory-art": "Umění",
"subcategory-gaming": "Hry",
"subcategory-media": "Média",
"subcategory-membership": "Členství",
"subcategory-market": "Trh",
"subcategory-social-network": "Sociální síť",
"subcategory-video": "Video",
"subcategory-messaging": "Zasílání zpráv",
"subcategory-identity": "Identita",
"subcategory-native": "Nativní",
"subcategory-validator-or-oracle": "Validátor nebo oracle",
"subcategory-generalized-message-passing": "Obecné předávání zpráv",
"subcategory-liquidity-network": "Síť likvidity",
"subcategory-chain-abstraction": "Abstrakce řetězce",
"subcategory-dns": "DNS",
"subcategory-pools": "Fondy",
"subcategory-payments": "Platby",
"subcategory-rpc": "RPC",
"subcategory-stealth-address": "Skrytá adresa",
"subcategory-governance": "Správa",
"subcategory-delegation": "Delegování",
"subcategory-offchain-voting": "Hlasování mimo blockchain",
"subcategory-organization": "Organizace"
}
37 changes: 35 additions & 2 deletions src/intl/de/app-subcategories.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"subcategory-mmorpg": "MMORPG",
"subcategory-rpg": "RPG",
"subcategory-strategy": "Strategie",
"subcategory-multiplayer": "Multiplayer",
"subcategory-multiplayer": "Mehrspieler",
"subcategory-onchain": "Auf der Blockchain",
"subcategory-casual": "Casual",
"subcategory-retro-gaming": "Retro-Gaming",
Expand All @@ -13,5 +13,38 @@
"subcategory-text-based": "Textbasiert",
"subcategory-roguelike": "Roguelike",
"subcategory-shooter": "Shooter",
"subcategory-metaverse": "Metaverse"
"subcategory-metaverse": "Metaverse",
"subcategory-simulation-and-management": "Simulation und Management",
"subcategory-sports-and-fantasy": "Sport und Fantasy",
"subcategory-lending": "Kreditvergabe",
"subcategory-lending-and-borrowing": "Kreditvergabe und -aufnahme",
"subcategory-liquid-staking": "Liquid Staking",
"subcategory-dex": "DEX",
"subcategory-insurance": "Versicherung",
"subcategory-prediction": "Prognose",
"subcategory-rwa": "RWA",
"subcategory-ip": "IP",
"subcategory-art": "Kunst",
"subcategory-gaming": "Gaming",
"subcategory-media": "Medien",
"subcategory-membership": "Mitgliedschaft",
"subcategory-market": "Markt",
"subcategory-social-network": "Soziales Netzwerk",
"subcategory-video": "Video",
"subcategory-messaging": "Messaging",
"subcategory-identity": "Identität",
"subcategory-native": "Nativ",
"subcategory-validator-or-oracle": "Validator oder Orakel",
"subcategory-generalized-message-passing": "Generalisierte Nachrichtenübermittlung",
"subcategory-liquidity-network": "Liquiditätsnetzwerk",
"subcategory-chain-abstraction": "Chain-Abstraktion",
"subcategory-dns": "DNS",
"subcategory-pools": "Pools",
"subcategory-payments": "Zahlungen",
"subcategory-rpc": "RPC",
"subcategory-stealth-address": "Stealth-Adresse",
"subcategory-governance": "Governance",
"subcategory-delegation": "Delegation",
"subcategory-offchain-voting": "Off-Chain-Abstimmung",
"subcategory-organization": "Organisation"
}
35 changes: 34 additions & 1 deletion src/intl/en/app-subcategories.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,38 @@
"subcategory-text-based": "Text-based",
"subcategory-roguelike": "Roguelike",
"subcategory-shooter": "Shooter",
"subcategory-metaverse": "Metaverse"
"subcategory-metaverse": "Metaverse",
"subcategory-simulation-and-management": "Simulation and management",
"subcategory-sports-and-fantasy": "Sports and fantasy",
"subcategory-lending": "Lending",
"subcategory-lending-and-borrowing": "Lending and borrowing",
"subcategory-liquid-staking": "Liquid staking",
"subcategory-dex": "DEX",
"subcategory-insurance": "Insurance",
"subcategory-prediction": "Prediction",
"subcategory-rwa": "RWA",
"subcategory-ip": "IP",
"subcategory-art": "Art",
"subcategory-gaming": "Gaming",
"subcategory-media": "Media",
"subcategory-membership": "Membership",
"subcategory-market": "Market",
"subcategory-social-network": "Social network",
"subcategory-video": "Video",
"subcategory-messaging": "Messaging",
"subcategory-identity": "Identity",
"subcategory-native": "Native",
"subcategory-validator-or-oracle": "Validator or oracle",
"subcategory-generalized-message-passing": "Generalized message passing",
"subcategory-liquidity-network": "Liquidity network",
"subcategory-chain-abstraction": "Chain abstraction",
"subcategory-dns": "DNS",
"subcategory-pools": "Pools",
"subcategory-payments": "Payments",
"subcategory-rpc": "RPC",
"subcategory-stealth-address": "Stealth address",
"subcategory-governance": "Governance",
"subcategory-delegation": "Delegation",
"subcategory-offchain-voting": "Offchain voting",
"subcategory-organization": "Organization"
}
Loading
Loading