Commit 12916da4 authored by BBeretta's avatar BBeretta

feat/language-translation (My Custom Room and Spectator List)

parent 829c69f7
Pipeline #27366 failed with stages
in 6 minutes and 44 seconds
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
"ReplayTitle": "录像回放", "ReplayTitle": "录像回放",
"ReplayDesc": "自由查看进行过的决斗,回味那些精彩的逆转瞬间。", "ReplayDesc": "自由查看进行过的决斗,回味那些精彩的逆转瞬间。",
"WIPTitle": "开发中...", "WIPTitle": "开发中...",
"WIPDesc": "其他功能敬请期待。" "WIPDesc": "其他功能敬请期待。",
"EnterSpectatorMode": "进入观战",
"PleaseSelectTheRoomToSpectate": "请选择观战的房间"
}, },
"BuildDeck": { "BuildDeck": {
"EnterTheDeckName": "请输入卡组名字", "EnterTheDeckName": "请输入卡组名字",
...@@ -100,7 +102,42 @@ ...@@ -100,7 +102,42 @@
"PlsRockPaperScissors": "请猜拳", "PlsRockPaperScissors": "请猜拳",
"WaitOpponentPlayRockPaperScissors": "等待对方猜拳", "WaitOpponentPlayRockPaperScissors": "等待对方猜拳",
"PlsChooseWhoGoesFirst": "请选择先后手", "PlsChooseWhoGoesFirst": "请选择先后手",
"WaitingForGameToStart": "等待游戏开始" "WaitingForGameToStart": "等待游戏开始",
"Scissors": "剪刀",
"Rock": "石头",
"Paper": "布"
},
"CustomRoomContent": {
"CreateJoinPrivateRoom": "创建/加入私密房间",
"RoomPassword": "房间密码",
"Initial": "初始",
"InitialHandSize": "初始手牌数",
"DrawPerTurn": "每回合抽卡",
"CardsAllowed": "卡片允许",
"SimplifiedChinese": "简体中文",
"CustomCards": "自制卡",
"ExclusiveCardsProhibited": "专有卡禁止",
"AllCards": "所有卡片",
"DuelMode": "决斗模式",
"SingleMatchMode": "单局模式",
"TournamentMode": "比赛模式",
"DuelRules": "决斗规则",
"MasterRule1": "大师规则1",
"MasterRule2": "大师规则2",
"MasterRule3": "大师规则3",
"NewMasterRule": "新大师规则",
"MasterRule2020": "大师规则2020",
"NoDeckCheck": "不检查卡组",
"NoShuffleDeck": "不切洗卡组",
"40MinutesAutomaticOvertime": "40分自动加时",
"EnterYourFriendsPrivateRoomPassword": "在这输入你朋友的私密房间密码",
"CreatePrivateRoom": "创建私密房间",
"JoinPrivateRoom": "加入私密房间"
},
"WatchContent": {
"SearchRoomByPlayerUsername": "通过玩家用户名搜索房间",
"RankedMatch": "竞技匹配",
"Versus": "与"
}, },
"Store": { "Store": {
"CannotAddTokens": "不能添加衍生物", "CannotAddTokens": "不能添加衍生物",
......
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
"ReplayTitle": "Replay", "ReplayTitle": "Replay",
"ReplayDesc": "Freely watch past duels and relive those exciting moments of reversal.", "ReplayDesc": "Freely watch past duels and relive those exciting moments of reversal.",
"WIPTitle": "Under development...", "WIPTitle": "Under development...",
"WIPDesc": "Stay tuned for other features." "WIPDesc": "Stay tuned for other features.",
"EnterSpectatorMode": "Enter Spectator Mode",
"PleaseSelectTheRoomToSpectate": "Please select the room to spectate"
}, },
"BuildDeck": { "BuildDeck": {
"EnterTheDeckName": "Deck name", "EnterTheDeckName": "Deck name",
...@@ -100,7 +102,42 @@ ...@@ -100,7 +102,42 @@
"PlsRockPaperScissors": "Please play Rock, Paper, Scissors", "PlsRockPaperScissors": "Please play Rock, Paper, Scissors",
"WaitOpponentPlayRockPaperScissors": "Wait for the opponent to play Rock, Paper, Scissors", "WaitOpponentPlayRockPaperScissors": "Wait for the opponent to play Rock, Paper, Scissors",
"PlsChooseWhoGoesFirst": "Please choose who goes first", "PlsChooseWhoGoesFirst": "Please choose who goes first",
"WaitingForGameToStart": "Waiting for the game to start" "WaitingForGameToStart": "Waiting for the game to start",
"Scissors": "Scissors",
"Rock": "Rock",
"Paper": "Paper"
},
"CustomRoomContent": {
"CreateJoinPrivateRoom": "Create/Join Private Room",
"RoomPassword": "Password",
"Initial": "Initial ",
"InitialHandSize": "Initial Hand Size",
"DrawPerTurn": "Draw per Turn",
"CardsAllowed": "Cards Allowed",
"SimplifiedChinese": "Simplified Chinese",
"CustomCards": "Custom Cards",
"ExclusiveCardsProhibited": "Exclusive Cards Prohibited",
"AllCards": "All Cards",
"DuelMode": "Duel Mode",
"SingleMatchMode": "Single Match Mode",
"TournamentMode": "Tournament Mode",
"DuelRules": "Duel Rules",
"MasterRule1": "Master Rule 1",
"MasterRule2": "Master Rule 2",
"MasterRule3": "Master Rule 3",
"NewMasterRule": "New Master Rule",
"MasterRule2020": "Master Rule 2020",
"NoDeckCheck": "No Deck Check",
"NoShuffleDeck": "No Shuffle Deck",
"40MinutesAutomaticOvertime": "40 Minutes Automatic Overtime",
"EnterYourFriendsPrivateRoomPassword": "Enter your friend's private room password here.",
"CreatePrivateRoom": "Create Private Room",
"JoinPrivateRoom": "Join Private Room"
},
"WatchContent": {
"SearchRoomByPlayerUsername": "Search Room by Player Username",
"RankedMatch": "Ranked Match",
"Versus": "vs"
}, },
"Store": { "Store": {
"CannotAddTokens": "Cannot add Tokens", "CannotAddTokens": "Cannot add Tokens",
......
...@@ -23,6 +23,8 @@ const resources = { ...@@ -23,6 +23,8 @@ const resources = {
CardDetails: translationChinese.CardDetails, CardDetails: translationChinese.CardDetails,
WaitRoom: translationChinese.WaitRoom, WaitRoom: translationChinese.WaitRoom,
Store: translationChinese.Store, Store: translationChinese.Store,
CustomRoomContent: translationChinese.CustomRoomContent,
WatchContent: translationChinese.WatchContent,
}, },
en: { en: {
Header: translationEnglish.Header, Header: translationEnglish.Header,
...@@ -32,7 +34,9 @@ const resources = { ...@@ -32,7 +34,9 @@ const resources = {
Filter: translationEnglish.Filter, Filter: translationEnglish.Filter,
CardDetails: translationEnglish.CardDetails, CardDetails: translationEnglish.CardDetails,
WaitRoom: translationEnglish.WaitRoom, WaitRoom: translationEnglish.WaitRoom,
Store: translationChinese.Store, Store: translationEnglish.Store,
CustomRoomContent: translationEnglish.CustomRoomContent,
WatchContent: translationEnglish.WatchContent
}, },
es: { es: {
Header: translationSpanish.Header, Header: translationSpanish.Header,
......
...@@ -9,6 +9,7 @@ import { accountStore } from "@/stores"; ...@@ -9,6 +9,7 @@ import { accountStore } from "@/stores";
import { Select } from "@/ui/Shared"; import { Select } from "@/ui/Shared";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { useTranslation } from "react-i18next";
interface CustomRoomProps { interface CustomRoomProps {
options: Options; options: Options;
...@@ -80,13 +81,13 @@ export const CustomRoomContent: React.FC = () => { ...@@ -80,13 +81,13 @@ export const CustomRoomContent: React.FC = () => {
const onChangePrivateID = (event: ChangeEvent<HTMLInputElement>) => { const onChangePrivateID = (event: ChangeEvent<HTMLInputElement>) => {
mcCustomRoomStore.friendPrivateID = Number(event.target.value); mcCustomRoomStore.friendPrivateID = Number(event.target.value);
}; };
const { t: i18n } = useTranslation("CustomRoomContent");
return ( return (
<div className={styles.container}> <div className={styles.container}>
<p>创建/加入私密房间</p> <p>{i18n("CreateJoinPrivateRoom")}</p>
<div className={styles.clipboard}> <div className={styles.clipboard}>
<div className={styles.title}> <div className={styles.title}>
房间密码 {i18n("RoomPassword")}
<KeyOutlined /> <KeyOutlined />
</div> </div>
<Input <Input
...@@ -98,7 +99,7 @@ export const CustomRoomContent: React.FC = () => { ...@@ -98,7 +99,7 @@ export const CustomRoomContent: React.FC = () => {
<Button icon={<CopyOutlined />} onClick={onCopy} /> <Button icon={<CopyOutlined />} onClick={onCopy} />
</div> </div>
<div className={styles["digit-option"]}> <div className={styles["digit-option"]}>
<div className={styles.title}>初始LP</div> <div className={styles.title}>{i18n("Initial")}LP</div>
<Input <Input
className={styles.input} className={styles.input}
value={options.start_lp} value={options.start_lp}
...@@ -107,7 +108,7 @@ export const CustomRoomContent: React.FC = () => { ...@@ -107,7 +108,7 @@ export const CustomRoomContent: React.FC = () => {
/> />
</div> </div>
<div className={styles["digit-option"]}> <div className={styles["digit-option"]}>
<div className={styles.title}>初始手牌数</div> <div className={styles.title}>{i18n("InitialHandSize")}</div>
<Input <Input
className={styles.input} className={styles.input}
value={options.start_hand} value={options.start_hand}
...@@ -116,7 +117,7 @@ export const CustomRoomContent: React.FC = () => { ...@@ -116,7 +117,7 @@ export const CustomRoomContent: React.FC = () => {
/> />
</div> </div>
<div className={styles["digit-option"]}> <div className={styles["digit-option"]}>
<div className={styles.title}>每回合抽卡</div> <div className={styles.title}>{i18n("DrawPerTurn")}</div>
<Input <Input
className={styles.input} className={styles.input}
value={options.draw_count} value={options.draw_count}
...@@ -126,26 +127,26 @@ export const CustomRoomContent: React.FC = () => { ...@@ -126,26 +127,26 @@ export const CustomRoomContent: React.FC = () => {
</div> </div>
<div className={styles["select-option"]}> <div className={styles["select-option"]}>
<Select <Select
title="卡片允许" title={i18n("CardsAllowed")}
value={options.rule} value={options.rule}
options={[ options={[
{ value: 0, label: "OCG" }, { value: 0, label: "OCG" },
{ value: 1, label: "TCG" }, { value: 1, label: "TCG" },
{ value: 2, label: "简体中文" }, { value: 2, label: i18n("SimplifiedChinese") },
{ value: 3, label: "自制卡" }, { value: 3, label: i18n("CustomCards") },
{ value: 4, label: "专有卡禁止" }, { value: 4, label: i18n("ExclusiveCardsProhibited") },
{ value: 5, label: "所有卡片" }, { value: 5, label: i18n("AllCards") },
]} ]}
onChange={onChangeRule} onChange={onChangeRule}
/> />
</div> </div>
<div className={styles["select-option"]}> <div className={styles["select-option"]}>
<Select <Select
title="决斗模式" title={i18n("DuelMode")}
value={options.mode} value={options.mode}
options={[ options={[
{ value: 0, label: "单局模式" }, { value: 0, label: i18n("SingleMatchMode") },
{ value: 1, label: "比赛模式" }, { value: 1, label: i18n("TournamentMode") },
// {value: 2, label: "TAG"}, // {value: 2, label: "TAG"},
]} ]}
onChange={onChangeMode} onChange={onChangeMode}
...@@ -153,14 +154,14 @@ export const CustomRoomContent: React.FC = () => { ...@@ -153,14 +154,14 @@ export const CustomRoomContent: React.FC = () => {
</div> </div>
<div className={styles["select-option"]}> <div className={styles["select-option"]}>
<Select <Select
title="决斗规则" title={i18n("DuelRules")}
value={options.duel_rule} value={options.duel_rule}
options={[ options={[
{ value: 1, label: "大师规则1" }, { value: 1, label: i18n("MasterRule1") },
{ value: 2, label: "大师规则2" }, { value: 2, label: i18n("MasterRule2") },
{ value: 3, label: "大师规则3" }, { value: 3, label: i18n("MasterRule3") },
{ value: 4, label: "新大师规则" }, { value: 4, label: i18n("NewMasterRule") },
{ value: 5, label: "大师规则2020" }, { value: 5, label: i18n("MasterRule2020") },
]} ]}
onChange={onChangeDuelRule} onChange={onChangeDuelRule}
/> />
...@@ -170,26 +171,26 @@ export const CustomRoomContent: React.FC = () => { ...@@ -170,26 +171,26 @@ export const CustomRoomContent: React.FC = () => {
checked={options.no_check_deck} checked={options.no_check_deck}
onChange={onChangeNoCheckDeck} onChange={onChangeNoCheckDeck}
> >
不检查卡组 {i18n("NoDeckCheck")}
</Checkbox> </Checkbox>
<Checkbox <Checkbox
className={styles.check} className={styles.check}
checked={options.no_shuffle_deck} checked={options.no_shuffle_deck}
onChange={onChangeNoShuffleDeck} onChange={onChangeNoShuffleDeck}
> >
不切洗卡组 {i18n("NoShuffleDeck")}
</Checkbox> </Checkbox>
<Checkbox <Checkbox
className={styles.check} className={styles.check}
checked={options.auto_death} checked={options.auto_death}
onChange={onChangeAutoDeath} onChange={onChangeAutoDeath}
> >
40分自动加时 {i18n("40MinutesAutomaticOvertime")}
</Checkbox> </Checkbox>
<Input <Input
value={friendPrivateID} value={friendPrivateID}
onChange={onChangePrivateID} onChange={onChangePrivateID}
placeholder="在这输入你朋友的私密房间密码" placeholder={i18n("EnterYourFriendsPrivateRoomPassword")}
type="text" type="text"
/> />
</div> </div>
...@@ -200,13 +201,14 @@ export const CustomRoomFooter: React.FC<{ ...@@ -200,13 +201,14 @@ export const CustomRoomFooter: React.FC<{
onCreateRoom: () => void; onCreateRoom: () => void;
onJoinRoom: () => void; onJoinRoom: () => void;
}> = ({ onCreateRoom, onJoinRoom }) => { }> = ({ onCreateRoom, onJoinRoom }) => {
const { t: i18n } = useTranslation("CustomRoomContent");
return ( return (
<div className={styles.footer}> <div className={styles.footer}>
<Button className={styles.btn} onClick={onCreateRoom}> <Button className={styles.btn} onClick={onCreateRoom}>
创建私密房间 {i18n("CreatePrivateRoom")}
</Button> </Button>
<Button className={styles.btn} onClick={onJoinRoom}> <Button className={styles.btn} onClick={onJoinRoom}>
加入私密房间 {i18n("JoinPrivateRoom")}
</Button> </Button>
</div> </div>
); );
......
...@@ -10,6 +10,7 @@ import { useConfig } from "@/config"; ...@@ -10,6 +10,7 @@ import { useConfig } from "@/config";
import { ScrollableArea } from "../../Shared"; import { ScrollableArea } from "../../Shared";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { useTranslation } from "react-i18next";
const { athleticWatchUrl } = useConfig(); const { athleticWatchUrl } = useConfig();
...@@ -30,7 +31,7 @@ export const WatchContent: React.FC = () => { ...@@ -30,7 +31,7 @@ export const WatchContent: React.FC = () => {
// 暂时只支持竞技匹配的观战,TODO:后面需要加上娱乐匹配的支持 // 暂时只支持竞技匹配的观战,TODO:后面需要加上娱乐匹配的支持
const url = new URL(athleticWatchUrl); const url = new URL(athleticWatchUrl);
url.searchParams.set("filter", "started"); url.searchParams.set("filter", "started");
const { t: i18n } = useTranslation("WatchContent");
const { readyState } = useWebSocket(url.toString(), { const { readyState } = useWebSocket(url.toString(), {
onOpen: () => console.log("watch websocket opened."), onOpen: () => console.log("watch websocket opened."),
onClose: () => console.log("watch websocket closed."), onClose: () => console.log("watch websocket closed."),
...@@ -99,7 +100,7 @@ export const WatchContent: React.FC = () => { ...@@ -99,7 +100,7 @@ export const WatchContent: React.FC = () => {
<div className={styles.search}> <div className={styles.search}>
<Input <Input
className={styles.input} className={styles.input}
placeholder="通过玩家用户名搜索房间" placeholder={i18n("SearchRoomByPlayerUsername")}
bordered={false} bordered={false}
suffix={<Button type="text" icon={<SearchOutlined />} />} suffix={<Button type="text" icon={<SearchOutlined />} />}
value={query} value={query}
...@@ -129,10 +130,10 @@ export const WatchContent: React.FC = () => { ...@@ -129,10 +130,10 @@ export const WatchContent: React.FC = () => {
<Avatar src={room.users?.at(1)?.avatar} /> <Avatar src={room.users?.at(1)?.avatar} />
</div> </div>
<div className={styles.title}> <div className={styles.title}>
{`${room.users?.at(0)?.username}${room.users?.at(1) {`${room.users?.at(0)?.username}` + ` ${i18n("Versus")} ` + `${room.users?.at(1)
?.username} 的决斗`} ?.username} 的决斗`}
</div> </div>
<div className={styles.mode}>竞技匹配</div> <div className={styles.mode}>{i18n("RankedMatch")}</div>
</div> </div>
<Divider className={styles.divider} /> <Divider className={styles.divider} />
</div> </div>
......
...@@ -156,7 +156,7 @@ export const Component: React.FC = () => { ...@@ -156,7 +156,7 @@ export const Component: React.FC = () => {
modal.info({ modal.info({
icon: null, icon: null,
width: "40vw", width: "40vw",
okText: "进入观战", okText: i18n("EnterSpectatorMode"),
onOk: async () => { onOk: async () => {
if (watchStore.watchID) { if (watchStore.watchID) {
setWatchLoading(true); setWatchLoading(true);
...@@ -181,7 +181,7 @@ export const Component: React.FC = () => { ...@@ -181,7 +181,7 @@ export const Component: React.FC = () => {
); );
} }
} else { } else {
message.error("请选择观战的房间"); message.error(`${i18n("PleaseSelectTheRoomToSpectate")}`);
} }
}, },
centered: true, centered: true,
......
...@@ -4,6 +4,7 @@ import { useEffect, useState } from "react"; ...@@ -4,6 +4,7 @@ import { useEffect, useState } from "react";
import { eventbus, Task } from "@/infra"; import { eventbus, Task } from "@/infra";
import { IconFont } from "../Shared"; import { IconFont } from "../Shared";
import { useTranslation } from "react-i18next";
export enum Mora { export enum Mora {
Scissors = "scissors", Scissors = "scissors",
...@@ -35,10 +36,12 @@ export const MoraPopover: React.FC< ...@@ -35,10 +36,12 @@ export const MoraPopover: React.FC<
setOpen(false); setOpen(false);
}; };
const { t: i18n } = useTranslation("WaitRoom");
const map = { const map = {
[Mora.Rock]: "石头", [Mora.Rock]: i18n("Rock"),
[Mora.Scissors]: "剪刀", [Mora.Scissors]: i18n("Scissors"),
[Mora.Paper]: "", [Mora.Paper]: i18n("Paper")
}; };
return ( return (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment