The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "translations"

Luna 55012758 9cbf4473

+49 -248
+14 -24
app/(home)/page.tsx
··· 7 7 import Badge from "@/components/badge"; 8 8 import Box from "@/components/box"; 9 9 import { StatsBar } from "@/components/counter"; 10 - import Highlight from "@/components/discord/Markdown"; 11 - import DiscordMessage from "@/components/discord/Message"; 10 + import Highlight from "@/components/discord/markdown"; 11 + import DiscordMessage from "@/components/discord/message"; 12 12 import DiscordMessageEmbed from "@/components/discord/message-embed"; 13 - import DiscordMessageFile from "@/components/discord/Message-file"; 13 + import DiscordMessageFile from "@/components/discord/message-file"; 14 14 import ServerGrid from "@/components/guild-grid"; 15 15 import { ServerButton } from "@/components/server-button"; 16 16 import ArrowPic from "@/public/arroww.webp"; ··· 21 21 import { ApiV1StatisticsGetResponse, ApiV1TopguildsGetResponse } from "@/typings"; 22 22 import cn from "@/utils/cn"; 23 23 import { convertMonthToName } from "@/utils/time"; 24 - 25 - import { Translation } from "../provider"; 26 - 27 24 28 25 const montserrat = Montserrat({ subsets: ["latin"] }); 29 26 const handwritten = Patrick_Hand({ subsets: ["latin"], weight: "400" }); ··· 75 72 className="button-primary" 76 73 > 77 74 <span className="block sm:hidden">Invite</span> 78 - <span className="hidden sm:block"> 79 - <Translation t="index.invite" /> 80 - </span> 75 + <span className="hidden sm:block">Invite Wamellow</span> 81 76 </ServerButton> 82 77 ); 83 78 ··· 102 97 103 98 <div className="md:text-xl text-lg lg:flex w-full mt-4"> 104 99 <span className="font-medium"> 105 - <Translation t="index.desc" /> 100 + Experience the next-gen revolution, offering a list of features and extensive customization, providing a superior alternative to popular bots. 106 101 </span> 107 102 108 103 <div className="flex flex-col min-w-full lg:min-w-[420px]"> ··· 116 111 size="lg" 117 112 > 118 113 <span className="block sm:hidden">Invite</span> 119 - <span className="hidden sm:block"> 120 - <Translation t="index.invite" /> 121 - </span> 114 + <span className="hidden sm:block">Invite Wamellow</span> 122 115 </ServerButton> 123 116 <ServerButton 124 117 as={Link} ··· 128 121 size="lg" 129 122 > 130 123 <span className="block sm:hidden">Support</span> 131 - <span className="hidden sm:block"> 132 - <Translation t="index.support" /> 133 - </span> 124 + <span className="hidden sm:block">Join support</span> 134 125 </ServerButton> 135 126 </div> 136 127 137 128 138 129 <span className={`lg:ml-auto flex gap-2 text-neutral-500 font-mediumr ${handwritten.className} mt-3 opacity-80 pl-20 lg:pr-20 rotate-2`}> 139 130 <Image src={ArrowPic} width={24} height={24} alt="arrow up" className="h-5 w-5 relative top-px" draggable={false} /> 140 - <Translation t="index.getStarted" /> 131 + Get started here in seconds 141 132 </span> 142 133 143 134 </div> ··· 149 140 <article itemScope itemType="http://schema.org/Article" className="flex flex-col gap-28 mb-10"> 150 141 151 142 <div> 152 - <h2 className={styles.h2}> 153 - <Translation t="index.fun" />🦄</h2> 143 + <h2 className={styles.h2}>Fun leveling and leaderboards 🦄</h2> 154 144 <div className="my-8 max-w-md font-medium"> 155 - {/* Have you ever dreamed of not using <span className="line-through">MEE6&trade;</span>? Just use <span className="font-bold">Wamellow</span> instead and don{"'"}t pay premium to personalise your cards and webpages! */} 156 - <Translation t="index.fun.desc" /> 145 + Have you ever dreamed of not using <span className="line-through">MEE6&trade;</span>? Just use <span className="font-bold">Wamellow</span> instead and don{"'"}t pay premium to personalise your cards and webpages! 157 146 </div> 158 147 159 148 <Box className="flex flex-col md:flex-row gap-10 items-center"> 160 149 <div className="md:w-1/2"> 161 150 <Badge 162 151 before={<HiCash />} 163 - translation="index.free" 152 + text="100% free forever" 164 153 classname="mr-auto ml-0 mb-4" 165 154 /> 166 155 <h3 className={styles.h3}>/leaderboard & /rank</h3> 167 156 <div className="pt-6"> 168 - <Translation t="index.leaderboard.desc" /> 157 + Enhance your server{"’"}s engagement with our text-, voice- and invite based leaderboards, tailored to track and reward your most active members. 158 + By motivating your members to communicate, you{"’"}ll cultivate a more active server community. 169 159 </div> 170 160 <div className="flex gap-2 mt-6"> 171 161 <Invite /> ··· 175 165 startContent={<HiArrowRight />} 176 166 href="/leaderboard/1055188344188973066" 177 167 > 178 - <Translation t="index.viewLeaderboard" /> 168 + View Leaderboard 179 169 </ServerButton> 180 170 </div> 181 171 </div>
+29 -36
app/layout.tsx
··· 1 + 1 2 import "./globals.css"; 2 3 3 4 import { Metadata, Viewport } from "next"; 4 5 import { Montserrat, Outfit } from "next/font/google"; 5 - import { cookies } from "next/headers"; 6 6 import Image from "next/image"; 7 7 import Link from "next/link"; 8 8 import { SiKofi } from "react-icons/si"; 9 9 10 - import { LanguageLocale, translationsConfig } from "@/common/languages"; 11 - import Header from "@/components/Header"; 10 + import Header from "@/components/header"; 12 11 import TopggIcon from "@/components/icons/topgg"; 13 12 import { getBaseUrl } from "@/utils/urls"; 14 13 15 - import { Provider, Translation, TranslationProvider } from "./provider"; 16 - import { loadFile } from "./translations"; 14 + import { Provider } from "./provider"; 17 15 18 16 const outfit = Outfit({ subsets: ["latin"] }); 19 17 const montserrat = Montserrat({ subsets: ["latin"] }); ··· 77 75 }; 78 76 }; 79 77 80 - export default async function RootLayout({ 78 + export default function RootLayout({ 81 79 children 82 80 }: { 83 81 children: React.ReactNode 84 82 }) { 85 - const locale = (cookies().get(translationsConfig.localeCookieName)?.value || translationsConfig.defaultLocale) as LanguageLocale; 86 - const file = await loadFile(locale); 87 - 88 83 return ( 89 84 <html lang="en" className="dark flex justify-center min-h-screen max-w-screen overflow-x-hidden bg-[var(--background-rgb)]"> 90 85 <body className={`${outfit.className} w-full max-w-7xl`}> 91 - <TranslationProvider file={file} cookieLocale={locale}> 92 86 93 - <div className="absolute left-0 bg-gradient-to-r from-indigo-400 to-pink-400 h-8 w-full flex items-center justify-center text-white font-medium text-sm"> 94 - <div className="hidden md:block"> 95 - Please note that this is an <span className="underline decoration-dotted break-word">early alpha version</span> of the bot and the website! 96 - </div> 97 - <div className="block md:hidden"> 98 - This is an <span className="underline decoration-dotted break-word">early alpha version</span>! 99 - </div> 87 + <div className="absolute left-0 bg-gradient-to-r from-indigo-400 to-pink-400 h-8 w-full flex items-center justify-center text-white font-medium text-sm"> 88 + <div className="hidden md:block"> 89 + Please note that this is an <span className="underline decoration-dotted break-word">early alpha version</span> of the bot and the website! 90 + </div> 91 + <div className="block md:hidden"> 92 + This is an <span className="underline decoration-dotted break-word">early alpha version</span>! 100 93 </div> 94 + </div> 101 95 102 - <nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none mt-7 h-20"> 103 - <Link href="/" className={`${montserrat.className} font-semibold flex items-center mr-2`}> 104 - <Image src="/waya-v3-small.webp" width={34} height={34} alt="" className="rounded-full mr-2" /> 105 - <span className="text-xl dark:text-neutral-100 text-neutral-900">Wamellow</span> 96 + <nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none mt-7 h-20"> 97 + <Link href="/" className={`${montserrat.className} font-semibold flex items-center mr-2`}> 98 + <Image src="/waya-v3-small.webp" width={34} height={34} alt="" className="rounded-full mr-2" /> 99 + <span className="text-xl dark:text-neutral-100 text-neutral-900">Wamellow</span> 100 + </Link> 101 + 102 + <div className="hidden sm:flex gap-1"> 103 + <Link href="https://lunish.nl/kofi" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-2 rounded-md duration-200 flex items-center gap-2 group"> 104 + <SiKofi className="group-hover:text-[#ff6c6b] duration-200" /> Support us 106 105 </Link> 107 - 108 - <div className="hidden sm:flex gap-1"> 109 - <Link href="https://lunish.nl/kofi" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-2 rounded-md duration-200 flex items-center gap-2 group"> 110 - <SiKofi className="group-hover:text-[#ff6c6b] duration-200" /> <Translation t="header.supportUs" /> 111 - </Link> 112 - <Link href="https://top.gg/bot/1125449347451068437/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-2 rounded-md duration-200 flex items-center gap-2 group"> 113 - <TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5" /> <Translation t="header.vote" /> 114 - </Link> 115 - </div> 106 + <Link href="https://top.gg/bot/1125449347451068437/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-2 rounded-md duration-200 flex items-center gap-2 group"> 107 + <TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5" /> Vote 108 + </Link> 109 + </div> 116 110 117 - <Header className="ml-auto flex gap-4 items-center" /> 118 - </nav> 111 + <Header className="ml-auto" /> 112 + </nav> 119 113 120 - <Provider> 121 - {children} 122 - </Provider> 114 + <Provider> 115 + {children} 116 + </Provider> 123 117 124 - </TranslationProvider> 125 118 </body> 126 119 </html> 127 120 );
+1 -53
app/provider.tsx
··· 1 1 "use client"; 2 - import { NextUIProvider } from "@nextui-org/react"; 3 - import { createContext, useContext, useState } from "react"; 4 2 5 - import { LanguageLocale, translationsConfig } from "@/common/languages"; 3 + import { NextUIProvider } from "@nextui-org/react"; 6 4 7 5 interface Props { 8 6 children: React.ReactNode; ··· 16 14 </main> 17 15 </NextUIProvider> 18 16 ); 19 - } 20 - 21 - // Translation 22 - 23 - interface TranslationContext { 24 - t: (key: string) => string; 25 - setLanguage: (language: LanguageLocale) => void; 26 - locale: string; 27 - } 28 - 29 - const TranslationContext = createContext<TranslationContext>({ 30 - locale: "en", 31 - setLanguage: () => "en", 32 - t: (key: string) => key 33 - }); 34 - 35 - export function TranslationProvider({ children, file: serverFile, cookieLocale }: Props & { file: Record<string, string>, cookieLocale: LanguageLocale }) { 36 - const [locale, setLocale] = useState<LanguageLocale>(cookieLocale); 37 - const [file, setFile] = useState(serverFile); 38 - 39 - function t(key: string) { 40 - return file[key] || key; 41 - } 42 - 43 - function setLanguage(language: LanguageLocale) { 44 - setLocale(language); 45 - document.cookie = `${translationsConfig.localeCookieName}=${language}; path=/;`; 46 - fetch(`/locales/${language}.json`).then((res) => res.json()).then(setFile); 47 - } 48 - 49 - return ( 50 - <TranslationContext.Provider value={{ 51 - locale, 52 - setLanguage, 53 - t 54 - }}> 55 - {children} 56 - </TranslationContext.Provider> 57 - ); 58 - } 59 - 60 - export function useTranslation() { 61 - return useContext(TranslationContext); 62 - } 63 - 64 - // in case you have server component, just use this component inside, otherwise use hook: `const { t } = useTranslation();` 65 - export function Translation({ t }: { t: string }) { // cannot do `key`, cause it's reserved react thing lol 66 - const { t: tFunc } = useTranslation(); 67 - 68 - return <>{tFunc(t)}</>; 69 17 }
-14
app/translations.ts
··· 1 - "use server"; 2 - 3 - import { translationsConfig } from "@/common/languages"; 4 - 5 - export async function loadFile(locale: string) { 6 - console.log("Loading locale", locale); 7 - 8 - return await import(`../public/locales/${locale}.json`) 9 - .then((res) => res.default).catch(async (err) => { 10 - console.error(`Locale ${locale} not found!`, err); 11 - return await import(`../public/locales/${translationsConfig.defaultLocale}.json`).then((res) => res.default); // load default locale, if not found 12 - }); 13 - 14 - }
-28
common/languages.ts
··· 1 - const languages = [ 2 - { 3 - name: "English", 4 - locale: "en" 5 - }, 6 - { 7 - name: "German", 8 - locale: "de" 9 - }, 10 - { 11 - name: "Polish", 12 - locale: "pl" 13 - } 14 - ] as const; 15 - 16 - export const translationsConfig: TranslationConfig = { 17 - languages, 18 - localeCookieName: "locale", 19 - defaultLocale: "en" 20 - }; 21 - 22 - export type LanguageLocale = typeof languages[number]["locale"]; 23 - 24 - interface TranslationConfig { 25 - languages: typeof languages; 26 - localeCookieName: string; 27 - defaultLocale: LanguageLocale 28 - }
+2 -34
components/Header.tsx
··· 1 1 "use client"; 2 2 3 - import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Skeleton } from "@nextui-org/react"; 3 + import { Button, Skeleton } from "@nextui-org/react"; 4 4 import { AnimatePresence, motion, MotionConfig } from "framer-motion"; 5 5 import Link from "next/link"; 6 6 import { usePathname } from "next/navigation"; 7 7 import React, { useEffect, useState } from "react"; 8 8 import { HiArrowNarrowRight, HiBeaker, HiChartPie, HiChevronDown, HiEyeOff, HiIdentification, HiViewGridAdd } from "react-icons/hi"; 9 - import { RiTranslate2 } from "react-icons/ri"; 10 9 11 - import { useTranslation } from "@/app/provider"; 12 10 import { guildStore } from "@/common/guilds"; 13 - import { translationsConfig } from "@/common/languages"; 14 11 import { userStore } from "@/common/user"; 15 12 import { webStore } from "@/common/webstore"; 16 13 import LoginButton from "@/components/login-button"; 17 14 import authorizeUser from "@/utils/authorize-user"; 18 15 import cn from "@/utils/cn"; 19 16 20 - import Badge from "./badge"; 21 17 import ImageReduceMotion from "./image-reduce-motion"; 22 18 23 19 export default function Header(props: React.ComponentProps<"div">) { 20 + 24 21 const [loggedin, setLoggedin] = useState<boolean>(); 25 22 const [menu, setMenu] = useState(false); 26 23 const [loginstate, setLoginstate] = useState<"LOADING" | "ERRORED" | undefined>("LOADING"); ··· 205 202 return ( 206 203 <div {...props}> 207 204 208 - <LanguageSwitcher /> 209 - 210 205 {loggedin && loginstate !== "ERRORED" ? UserButton : <LoginButton loginstate={loginstate} />} 211 206 212 207 <MotionConfig ··· 227 222 228 223 </div> 229 224 ); 230 - } 231 - function LanguageSwitcher() { 232 - const { setLanguage } = useTranslation(); 233 - 234 - return <> 235 - <Dropdown> 236 - <DropdownTrigger> 237 - <Button 238 - variant="light" 239 - className="min-w-0 mr-2" 240 - > 241 - <RiTranslate2 /> 242 - </Button> 243 - </DropdownTrigger> 244 - <DropdownMenu aria-label="Change Language"> 245 - {translationsConfig.languages.map((lang) => 246 - <DropdownItem 247 - key={lang.name} 248 - onClick={() => setLanguage(lang.locale)} 249 - endContent={lang.locale !== "en-EN" && <Badge text="Beta" />} 250 - > 251 - {lang.name} 252 - </DropdownItem> 253 - )} 254 - </DropdownMenu> 255 - </Dropdown> 256 - </>; 257 225 }
+3 -8
components/badge.tsx
··· 1 - "use client"; 2 1 import { FunctionComponent } from "react"; 3 2 4 - import { useTranslation } from "@/app/provider"; 5 3 import cn from "@/utils/cn"; 6 4 7 5 interface Props { 8 6 before?: React.ReactNode; 9 - text?: string; 10 - translation?: string 7 + text: string; 11 8 classname?: string; 12 9 } 13 10 14 - const Badge: FunctionComponent<Props> = ({ before, text, classname, translation }) => { 15 - const { t } = useTranslation(); 16 - 11 + const Badge: FunctionComponent<Props> = ({ before, text, classname }) => { 17 12 return ( 18 13 <span className={cn("max-w-fit flex gap-2 items-center whitespace-nowrap rounded-full dark:bg-violet-400/40 bg-violet-600/40 px-[0.7em] pb-[0.25em] pt-[0.35em] text-center text-[0.75em] font-medium leading-none dark:text-violet-300 text-violet-700/60 ml-auto", classname)}> 19 14 {before} 20 - {text || t(translation as string)} 15 + {text} 21 16 </span> 22 17 ); 23 18 };
-17
public/locales/de.json
··· 1 - { 2 - "ping": "huhersohn", 3 - 4 - "header.supportUs": "Unterstütze uns", 5 - "header.vote": "Vote", 6 - "header.login": "Mit Discord einloggen", 7 - 8 - "index.desc": "Erlebe die nächste Generation der Discord Bots, mit einer Vielzahl an Features und umfangreichen Anpassungsmöglichkeiten, die eine überlegene Alternative zu populären Bots bietet.", 9 - "index.getStarted": "In Sekunden loslegen", 10 - "index.invite": "Wamellow einladen", 11 - "index.support": "Support beitreten", 12 - "index.fun": "Spaß mit Leveln und Leaderboards", 13 - "index.fun.desc": "Hast du jemals davon geträumt, MEE6™ nicht zu benutzen? Benutze einfach Wamellow und zahle nicht für Premium, um deine Karten und Webseiten zu personalisieren!", 14 - "index.free": "100% kostenlos für immer", 15 - "index.leaderboard.desc": "Verbessere die Aktivität deines Servers mit unseren Text-, Sprach- und Einladungs-Leaderboards, die darauf ausgelegt sind, deine aktivsten Mitglieder zu verfolgen und zu belohnen. Indem du deine Mitglieder dazu motivierst, zu kommunizieren, wirst du eine aktivere Server-Community aufbauen.", 16 - "index.viewLeaderboard": "Leaderboard ansehen" 17 - }
-17
public/locales/en.json
··· 1 - { 2 - "ping": "pong", 3 - 4 - "header.supportUs": "Support us", 5 - "header.vote": "Vote", 6 - "header.login": "Login with Discord", 7 - 8 - "index.desc": "Experience the next-gen revolution, offering a list of features and extensive customization, providing a superior alternative to popular bots.", 9 - "index.getStarted": "Get started here in seconds", 10 - "index.invite": "Invite Wamellow", 11 - "index.support": "Join support", 12 - "index.fun": "Fun leveling and leaderboards", 13 - "index.fun.desc": "Have you ever dreamed of not using MEE6™? Just use Wamellow instead and don't pay premium to personalise your cards and webpages!", 14 - "index.free": "100% free forever", 15 - "index.leaderboard.desc": "Enhance your server’s engagement with our text-, voice- and invite based leaderboards, tailored to track and reward your most active members. By motivating your members to communicate, you’ll cultivate a more active server community.", 16 - "index.viewLeaderboard": "View Leaderboard" 17 - }
-17
public/locales/pl.json
··· 1 - { 2 - "ping": "ara ara", 3 - 4 - "header.supportUs": "Wesprzyj nas", 5 - "header.vote": "Zagłosuj", 6 - "header.login": "Zaloguj się przez Discorda", 7 - 8 - "index.desc": "Doświadcz rewolucji następnej generacji, oferującej listę funkcji i rozszerzonej personalizacji, zapewniającej doskonałą alternatywę dla popularnych botów.", 9 - "index.getStarted": "Zacznij tutaj w kilka sekund", 10 - "index.invite": "Zaproś Wamellow", 11 - "index.support": "Dołącz do supportu", 12 - "index.fun": "Zabawne poziomy i tablice wyników", 13 - "index.fun.desc": "Czy kiedykolwiek marzyłeś o nie używaniu MEE6™? Po prostu użyj Wamellow zamiast tego i nie płać premium, aby spersonalizować swoje karty i strony internetowe!", 14 - "index.free": "100% darmowy na zawsze", 15 - "index.leaderboard.desc": "Zwiększ zaangażowanie na swoim serwerze dzięki naszym tablicom wyników opartym na tekście, głosie i zaproszeniach, dostosowanym do śledzenia i nagradzania Twoich najbardziej aktywnych członków. Motywując członków do komunikacji, będziesz pielęgnować bardziej aktywną społeczność serwera.", 16 - "index.viewLeaderboard": "Zobacz tablicę wyników" 17 - }