Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
432 changes: 432 additions & 0 deletions i18n/de/code.json

Large diffs are not rendered by default.

432 changes: 432 additions & 0 deletions i18n/en/code.json

Large diffs are not rendered by default.

432 changes: 432 additions & 0 deletions i18n/es/code.json

Large diffs are not rendered by default.

432 changes: 432 additions & 0 deletions i18n/fr/code.json

Large diffs are not rendered by default.

432 changes: 432 additions & 0 deletions i18n/pt/code.json

Large diffs are not rendered by default.

61 changes: 53 additions & 8 deletions src/components/landing/Hero/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import shared from '../styles/shared.module.css';
import styles from './styles.module.css';

Expand All @@ -17,38 +19,81 @@ function roundedServerCount(raw: number | undefined): number {
return Math.floor(raw / PRE_TITLE_STEP) * PRE_TITLE_STEP;
}

const LOCALE_TO_BCP47: Record<string, string> = {
fr: 'fr-FR',
en: 'en-US',
de: 'de-DE',
es: 'es-ES',
pt: 'pt-PT',
};

export default function Hero({serverCount}: HeroProps): ReactNode {
const formatted = roundedServerCount(serverCount).toLocaleString('fr-FR');
const {
i18n: {currentLocale},
} = useDocusaurusContext();
const bcp47 = LOCALE_TO_BCP47[currentLocale] ?? currentLocale;
const formatted = roundedServerCount(serverCount).toLocaleString(bcp47);
return (
<section className={clsx(shared.landing, styles.section)}>
<div className={shared.container}>
<div className={styles.content}>
<div className={styles.preTitleWrap}>
<div className={styles.preTitleText}>
Utilisé par plus de {formatted} serveurs
<Translate
id="hero.preTitle"
description="Hero pre-title displayed above the main title; {count} is a locale-formatted number of servers"
values={{count: formatted}}>
{'Utilisé par plus de {count} serveurs'}
</Translate>
</div>
</div>
<h1 className={styles.title}>
Le meilleur bot Discord de{' '}
<span className={shared.textGradient}>sécurité</span>
<Translate
id="hero.title"
description="Hero main title; {highlight} renders the gradient-highlighted word"
values={{
highlight: (
<span className={shared.textGradient}>
<Translate
id="hero.title.highlight"
description="The highlighted word inside the hero title (security)">
sécurité
</Translate>
</span>
),
}}>
{'Le meilleur bot Discord de {highlight}'}
</Translate>
</h1>
<p className={styles.description}>
Empêchez les utilisateurs malintentionnés de nuire à votre serveur
Discord.
<Translate
id="hero.description"
description="Hero description below the title">
Empêchez les utilisateurs malintentionnés de nuire à votre serveur
Discord.
</Translate>
</p>
<div className={styles.buttonList}>
<a
href="https://raidprotect.bot/invite"
target="_blank"
rel="noopener noreferrer"
className={shared.btnPrimary}>
Ajouter à Discord
<Translate
id="hero.cta.primary"
description="Primary CTA: invite the bot to Discord">
Ajouter à Discord
</Translate>
</a>
<a
href="#features"
rel="noopener noreferrer"
className={shared.btnSecondary}>
Voir les fonctionnalités
<Translate
id="hero.cta.secondary"
description="Secondary CTA: scroll to the features section">
Voir les fonctionnalités
</Translate>
</a>
</div>
</div>
Expand Down
80 changes: 59 additions & 21 deletions src/components/landing/Servers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import Translate from '@docusaurus/Translate';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import shared from '../styles/shared.module.css';
import styles from './styles.module.css';

Expand All @@ -10,7 +12,8 @@ type Server = {
icon: string;
alt: string;
href: string;
members: string;
/** Raw member count (rounded). Localised at render time. */
members: number;
badge: Badge;
};

Expand All @@ -20,123 +23,131 @@ const SERVERS: Server[] = [
icon: '/img/landing/iconWankilStudio.webp',
alt: 'Wankil Studio Discord server icon',
href: 'https://discord.com/invite/wankilstudio',
members: '40 000 membres',
members: 40000,
badge: 'verified',
},
{
name: 'Rocket League France',
icon: '/img/landing/iconRocketLeagueFrance.webp',
alt: 'Rocket League France Discord server icon',
href: 'https://discord.com/invite/rlfr',
members: '196 500 membres',
members: 196500,
badge: 'partner',
},
{
name: 'Slash FR',
icon: '/img/landing/iconSlashFR.webp',
alt: 'Slash FR Discord server icon',
href: 'https://discord.com/invite/fr',
members: '48 500 membres',
members: 48500,
badge: null,
},
{
name: "ZetFar's Family",
icon: '/img/landing/iconZetFar.webp',
alt: 'ZetFar Discord server icon',
href: 'https://discord.com/invite/zetfar',
members: '135 000 membres',
members: 135000,
badge: 'verified',
},
{
name: 'Ligue 1 McDonald’s',
icon: '/img/landing/iconLigue1.webp',
alt: 'Ligue 1 Discord server icon',
href: 'https://discord.com/invite/ligue1',
members: '15 000 membres',
members: 15000,
badge: 'verified',
},
{
name: 'Jobless',
icon: '/img/landing/iconJobless.webp',
alt: 'Jobless Discord server icon',
href: 'https://discord.com/invite/jobless',
members: '56 500 membres',
members: 56500,
badge: 'partner',
},
{
name: 'Blox Fruits FR',
icon: '/img/landing/iconBloxFruitsFR.webp',
alt: 'Blox Fruits FR Discord server icon',
href: 'https://discord.com/invite/bloxfruitsfr',
members: '124 000 membres',
members: 124000,
badge: null,
},
{
name: 'CYRILmp4',
icon: '/img/landing/iconCyrilmp4.webp',
alt: 'CYRILmp4 Discord server icon',
href: 'https://discord.com/invite/cyrilmp4',
members: '22 500 membres',
members: 22500,
badge: 'partner',
},
{
name: 'Fortnite House',
icon: '/img/landing/iconFortniteHouse.webp',
alt: 'Fortnite House Discord server icon',
href: 'https://discord.com/invite/officiel',
members: '66 500 membres',
members: 66500,
badge: 'partner',
},
{
name: 'PUBG MOBILE FRANCE',
icon: '/img/landing/iconPUBGMobileFrance.webp',
alt: 'PUBG MOBILE FRANCE Discord server icon',
href: 'https://discord.com/invite/pubgmfr',
members: '18 000 membres',
members: 18000,
badge: 'verified',
},
{
name: 'NationGlory',
icon: '/img/landing/iconNationsGlory.webp',
alt: 'NationsGlory server icon',
href: 'https://discord.com/invite/nationsglory',
members: '51 000 membres',
members: 51000,
badge: 'partner',
},
{
name: 'MASTU',
icon: '/img/landing/iconMastu.webp',
alt: 'MASTU Discord server icon',
href: 'https://discord.com/invite/mastu',
members: '17 000 membres',
members: 17000,
badge: 'partner',
},
{
name: 'Clash Royale FR',
icon: '/img/landing/iconClashRoyaleFR.webp',
alt: 'Clash Royale FR Discord server icon',
href: 'https://discord.com/invite/clashfr',
members: '34 000 membres',
members: 34000,
badge: 'partner',
},
{
name: 'TEAM VITALITY',
icon: '/img/landing/iconTeamVitality.webp',
alt: 'TEAM VITALITY Discord server icon',
href: 'https://discord.com/invite/teamvitality',
members: '19 500 membres',
members: 19500,
badge: null,
},
{
name: 'Genshin Impact FR',
icon: '/img/landing/iconGenshinImpactFR.webp',
alt: 'Genshin Impact FR Discord server icon',
href: 'https://discord.com/invite/genshinimpactfr',
members: '55 000 membres',
members: 55000,
badge: 'partner',
},
];

const LOCALE_TO_BCP47: Record<string, string> = {
fr: 'fr-FR',
en: 'en-US',
de: 'de-DE',
es: 'es-ES',
pt: 'pt-PT',
};

function BadgeImg({badge}: {badge: Badge}) {
if (!badge) return null;
const src =
Expand All @@ -159,7 +170,10 @@ function BadgeImg({badge}: {badge: Badge}) {
);
}

function ServerCard({server}: {server: Server}) {
function ServerCard({server, locale}: {server: Server; locale: string}) {
const formatted = server.members.toLocaleString(
LOCALE_TO_BCP47[locale] ?? locale,
);
return (
<a
href={server.href}
Expand All @@ -178,28 +192,52 @@ function ServerCard({server}: {server: Server}) {
<div className={styles.name}>{server.name}</div>
<BadgeImg badge={server.badge} />
</div>
<div className={styles.memberCount}>{server.members}</div>
<div className={styles.memberCount}>
<Translate
id="servers.memberCount"
description="Server card: number of members (e.g. '40 000 members'); {count} is locale-formatted"
values={{count: formatted}}>
{'{count} membres'}
</Translate>
</div>
</div>
</div>
</a>
);
}

export default function Servers(): ReactNode {
const {
i18n: {currentLocale},
} = useDocusaurusContext();
return (
<section className={clsx(shared.landing, styles.section)}>
<div className={shared.container}>
<p className={styles.title}>Nous protégeons les plus grands</p>
<p className={styles.title}>
<Translate
id="servers.title"
description="Servers marquee title: 'We protect the biggest'">
Nous protégeons les plus grands
</Translate>
</p>
<div className={styles.marqueeWrap} aria-hidden={false}>
<div className={styles.track}>
<div className={styles.group}>
{SERVERS.map((server) => (
<ServerCard key={`a-${server.name}`} server={server} />
<ServerCard
key={`a-${server.name}`}
server={server}
locale={currentLocale}
/>
))}
</div>
<div className={styles.group} aria-hidden="true">
{SERVERS.map((server) => (
<ServerCard key={`b-${server.name}`} server={server} />
<ServerCard
key={`b-${server.name}`}
server={server}
locale={currentLocale}
/>
))}
</div>
</div>
Expand Down
39 changes: 33 additions & 6 deletions src/pages/frame/cta.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {type ReactNode} from 'react';
import Head from '@docusaurus/Head';
import Translate from '@docusaurus/Translate';
import clsx from 'clsx';
import shared from '@site/src/components/landing/styles/shared.module.css';
import frame from './frame.module.css';
Expand All @@ -19,27 +20,53 @@ export default function FrameCta(): ReactNode {
<div className={styles.wrap}>
<div className={styles.contentWrap}>
<h2 className={styles.title}>
Garder une longueur{' '}
<span className={shared.textGradient}>d'avance</span>
<Translate
id="frame.cta.title"
description="Frame CTA title; {highlight} renders the gradient-highlighted word"
values={{
highlight: (
<span className={shared.textGradient}>
<Translate
id="frame.cta.title.highlight"
description="Highlighted word inside the frame CTA title">
d'avance
</Translate>
</span>
),
}}>
{'Garder une longueur {highlight}'}
</Translate>
</h2>
<p className={styles.description}>
Ajoutez RaidProtect et commencez à protéger votre serveur dès
aujourd'hui.
<Translate
id="frame.cta.description"
description="Frame CTA description">
Ajoutez RaidProtect et commencez à protéger votre serveur
dès aujourd'hui.
</Translate>
</p>
<div className={styles.buttonList}>
<a
href="https://raidprotect.bot/invite"
target="_blank"
rel="noopener noreferrer"
className={shared.btnPrimary}>
Ajouter le bot
<Translate
id="frame.cta.primary"
description="Frame CTA primary button: add the bot to Discord">
Ajouter le bot
</Translate>
</a>
<a
href="https://raidprotect.bot/discord"
target="_blank"
rel="noopener noreferrer"
className={shared.btnSecondary}>
Rejoindre le serveur
<Translate
id="frame.cta.secondary"
description="Frame CTA secondary button: join the Discord server">
Rejoindre le serveur
</Translate>
</a>
</div>
</div>
Expand Down
Loading