diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 8f389160..cc2d37a3 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -4,5 +4,55 @@
"title": "Welcome, streamer",
"description": "Unlock the Ultimate Dota 2 Streaming Experience with Dotabod! Boost your stream's engagement, showcase real-time stats, and delight your audience with our all-in-one streaming toolkit. Elevate your game and become the streamer you were meant to be!"
},
- "live": "Live"
+ "live": "Live",
+ "button": {
+ "getStarted": "Get started",
+ "goToDashboard": "Go to dashboard",
+ "joinDiscord": "Join Discord"
+ },
+ "languageCard": {
+ "title": "Language",
+ "subtitle": "The @dotabod Twitch chat bot will speak in this language.",
+ "usedBy": "Used by",
+ "dotabods": "dotabods",
+ "percentTranslated": "% translated",
+ "onlyOneUsing": "You're the only one using this language",
+ "helpComplete": "Help complete on Crowdin",
+ "fixLocaleIssues": "Fix locale issues on Crowdin"
+ },
+ "dashboard": {
+ "setup": {
+ "title": "Setup",
+ "subtitle": "Let's get Dotabod working for you right away",
+ "twitch": "Twitch",
+ "dota2": "Dota 2",
+ "obs": "OBS",
+ "allDone": "All done!",
+ "streamOfflineWarning": "Your stream is offline, and Dotabod will only work once you start streaming and go online.",
+ "thatsIt": "That's it! You're all set up.",
+ "hopIntoMatch": "You can either hop into a match right away, or you can test Dotabod first.",
+ "howToTest": "How to test Dotabod",
+ "demoHeroStep": "Demo any hero to get Dotabod to recognize your Steam account.",
+ "livePreviewStep": "While demoing, visit the Live Preview page to confirm the overlay is showing.",
+ "troubleshootingStep": "Having trouble? Visit the Troubleshooting page to get help."
+ },
+ "features": {
+ "main": {
+ "title": "Main features",
+ "subtitle": "Customize the options your stream receives."
+ },
+ "advanced": {
+ "title": "Advanced features",
+ "subtitle": "Looking for even more? They'll be here"
+ },
+ "chat": {
+ "title": "Chat features",
+ "subtitle": "The bot reacts with chat messages to your game events as you play your match."
+ },
+ "overlay": {
+ "title": "Overlay features",
+ "subtitle": "Enhance your stream with these overlay features"
+ }
+ }
+ }
}
diff --git a/src/components/Button.jsx b/src/components/Button.jsx
index 054a7367..2db78d91 100644
--- a/src/components/Button.jsx
+++ b/src/components/Button.jsx
@@ -1,6 +1,7 @@
import clsx from 'clsx'
import Link from 'next/link'
import { forwardRef } from 'react'
+import { useTranslation } from 'next-i18next'
const baseStyles = {
solid:
@@ -25,6 +26,7 @@ export const Button = forwardRef(function Button(
{ variant = 'solid', color = 'gray', className, href, ...props },
ref
) {
+ const { t } = useTranslation('common')
className = clsx(
baseStyles[variant],
variantStyles[variant][color],
@@ -32,8 +34,12 @@ export const Button = forwardRef(function Button(
)
return href ? (
-
+
+ {t(props.children)}
+
) : (
-
+
)
})
diff --git a/src/components/Card.tsx b/src/components/Card.tsx
index 8f1dfa79..86b0ab57 100644
--- a/src/components/Card.tsx
+++ b/src/components/Card.tsx
@@ -1,6 +1,9 @@
import clsx from 'clsx'
+import { useTranslation } from 'next-i18next'
export const Card = ({ children = null, className = '', ...props }) => {
+ const { t } = useTranslation('common')
+
return (
{
)}
{...props}
>
- {children}
+ {t(children)}
)
}
diff --git a/src/components/Dashboard/CommandDetail.tsx b/src/components/Dashboard/CommandDetail.tsx
index ba4ea2b1..14fc58cd 100644
--- a/src/components/Dashboard/CommandDetail.tsx
+++ b/src/components/Dashboard/CommandDetail.tsx
@@ -2,727 +2,699 @@ import { chatterInfo } from '@/components/Dashboard/Features/ChatterCard'
import TwitchChat from '@/components/TwitchChat'
import { Settings } from '@/lib/defaultSettings'
import Image from 'next/image'
+import { useTranslation } from 'next-i18next'
-const CommandDetail = {
- [Settings.commandDisable]: {
- title: 'Disable Dotabod',
- description:
- 'Toggle to stop or start responding to game events and commands.',
- cmd: '!toggle',
- alias: ['enable', 'disable'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandOnline]: {
- title: 'Online or offline status',
- description:
- 'Updates the status of your stream that Dotabod sees to online or offline.',
- cmd: '!online',
- alias: ['offline', 'forceonline', 'forceoffline'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.chatter]: {
- title: 'Mute Dotabod',
- description:
- 'Will prevent Dotabod from auto sending chatters, but will still respond to commands.',
- cmd: '!mute',
- alias: ['unmute'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- fixparty: {
- title: 'Fix party match',
- description:
- "Dotabod can't detect party games right now (sadge). So if it does 25 mmr for a completed match, use !fixparty to adjust it to 20. You must type this after every party match.",
- cmd: '!fixparty',
- alias: ['fixsolo'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- refresh: {
- title: 'Refresh',
- description:
- 'Refreshes your OBS overlay without having to do it from OBS. Used in case the overlay is messed up.',
- cmd: '!refresh',
- alias: [],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandSteam]: {
- key: Settings.commandSteam,
- title: 'Steam ID',
- description:
- "Retrieve the steam ID of the account you're currently playing on.",
- cmd: '!steam',
- alias: ['steamid', 'account'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- setmmr: {
- title: 'Set MMR',
- description: 'Manually set your MMR.',
- cmd: '!setmmr',
- alias: ['mmr=', 'mmrset'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- beta: {
- title: 'Dotabod Beta',
- description:
- 'Want to join the beta? You will get the latest features and updates before anyone else.',
- cmd: '!beta',
- alias: ['joinbeta', 'leavebeta', 'betaoff', 'betaon'],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandPleb]: {
- key: Settings.commandPleb,
- title: 'Pleb',
- description:
- 'When you have sub only mode turned on, use !pleb to let one non-sub send a message. Then all your subs can point and laugh 😂.',
- cmd: '!pleb',
- alias: [],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandModsonly]: {
- key: Settings.commandModsonly,
- title: 'Mods only',
- description:
- 'Only allow mods to send messages in chat. Turns sub only mode on and deletes messages from subs.',
- cmd: '!modsonly',
- alias: [],
- allowed: 'mods',
- response: (props: Record = {}) => (
-
- Mods only mode is now on
-
-
- . Only mods can type.
- >
- }
- />
- ),
- },
- [Settings.commandCommands]: {
- key: Settings.commandCommands,
- title: 'Command list',
- description:
- 'All available commands with Dotabod. This list is filtered to only the commands you enabled. If a mod uses !commands, it will show mod only commands as well.',
- cmd: '!commands',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandRanked]: {
- key: Settings.commandRanked,
- title: 'Ranked or not?',
- description: 'Chatters can find out if this match is ranked or not.',
- cmd: '!ranked',
- alias: ['isranked'],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandAvg]: {
- key: Settings.commandAvg,
- title: 'Average MMR',
- description:
- 'For the current game, show the average MMR of all players. Only works if not immortal.',
- cmd: '!avg',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandOpendota]: {
- key: Settings.commandOpendota,
- title: 'Opendota',
- description:
- 'Shows the Opendota link for your currently logged in steam account.',
- cmd: '!opendota',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
-
- [Settings.commandDotabuff]: {
- key: Settings.commandDotabuff,
- title: 'Dotabuff',
- description:
- 'Shows the Dotabuff link for your currently logged in steam account.',
- cmd: '!dotabuff',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandXPM]: {
- key: Settings.commandXPM,
- title: 'XPM',
- description: 'Live experience per minute for your chatters on demand.',
- cmd: '!xpm',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandWL]: {
- key: Settings.commandWL,
- title: 'Win / Loss',
- description:
- 'Says the total wins and losses for current stream duration. Disabling this command will hide these statistics in the stream overlay.',
- cmd: '!wl',
- alias: ['score', 'winrate', 'wr'],
- allowed: 'all',
- response: (props: Record = {}, all = true) => (
- <>
-
- {all && (
-
- )}
- >
- ),
- },
- [Settings.commandMmr]: {
- key: Settings.commandMmr,
- title: 'MMR',
- description:
- 'Using chat command !mmr, viewers can get an accurate mmr update in chat. Auto updates immediately with every match!',
- cmd: '!mmr',
- alias: ['rank', 'medal'],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandGPM]: {
- key: Settings.commandGPM,
- title: 'GPM',
- description:
- 'At any time, chatters can request your live gold per minute with !gpm. Playing alch or anti-mage? Show off your gpm!',
- cmd: '!gpm',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
- [Settings.commandAPM]: {
- key: Settings.commandAPM,
- title: 'APM',
- description:
- 'Actions per minute. A good indicator of speed and efficiency.',
- cmd: '!apm',
- alias: [],
- allowed: 'all',
- response: (props: Record = {}) => (
-
- ),
- },
+const CommandDetail = () => {
+ const { t } = useTranslation('common')
- [Settings.commandNP]: {
- key: Settings.commandNP,
- title: 'Notable players',
- description: 'Find out if your match has any pros.',
- cmd: '!np',
- alias: ['who', 'players'],
- allowed: 'all',
- response: (props: Record = {}, all = true) => (
-
- Unlock the Ultimate Dota 2 Streaming Experience with Dotabod!
- Boost your stream's engagement, showcase real-time stats, and
- delight your audience with our all-in-one streaming toolkit.
- Elevate your game and become the streamer you were meant to be!
+ {t('hero.description')}
@@ -180,9 +179,9 @@ export function Hero() {
{session?.status === 'authenticated' ? (
- Go to dashboard
+ {t('button.goToDashboard')}
) : (
- Get started
+ {t('button.getStarted')}
)}
@@ -194,7 +193,7 @@ export function Hero() {
>
- Join Discord
+ {t('button.joinDiscord')}
@@ -228,8 +227,7 @@ export function Hero() {
alt="twitch logo"
/>
- Featured in over {new Intl.NumberFormat().format(20000)}{' '}
- Twitch streamers
+ {t('hero.featuredIn', { count: new Intl.NumberFormat().format(20000) })}
@@ -263,7 +261,7 @@ export function Hero() {
- Top streamers using Dotabod:
+ {t('hero.topStreamers')}
@@ -289,7 +287,7 @@ export function Hero() {
- Random Dotabod streamers:
+ {t('hero.randomStreamers')}
diff --git a/src/pages/dashboard/commands.tsx b/src/pages/dashboard/commands.tsx
index 189f7ccd..3ddc6916 100644
--- a/src/pages/dashboard/commands.tsx
+++ b/src/pages/dashboard/commands.tsx
@@ -7,8 +7,10 @@ import { Empty, Input, Segmented } from 'antd'
import Head from 'next/head'
import { type ReactElement, useState } from 'react'
import CommandDetail from '../../components/Dashboard/CommandDetail'
+import { useTranslation } from 'next-i18next'
const CommandsPage = () => {
+ const { t } = useTranslation('common')
const [permission, setPermission] = useState('All')
const [enabled, setEnabled] = useState('All')
const { data } = useUpdate({ path: '/api/settings' })
@@ -63,26 +65,26 @@ const CommandsPage = () => {
return (
<>
- Dotabod | Commands
+ Dotabod | {t('commands.title')}
- Demo any hero to get Dotabod to recognize your Steam
- account.
+ {t('dashboard.setup.livePreviewStep')}{' '}
+ {t('dashboard.setup.livePreviewPage')}
- While demoing, visit the{' '}
- Live Preview page to
- confirm the overlay is showing.
-
-
- Having trouble? Visit the{' '}
-
- Troubleshooting page
- {' '}
- to get help.
+ {t('dashboard.setup.troubleshootingStep')}{' '}
+ {t('dashboard.setup.troubleshootingPage')}