Commit 829c69f7 authored by BBeretta's avatar BBeretta

feat/language-translation (Wait Room page) and storage language changed

parent 8c215ebd
Pipeline #27363 failed with stages
in 6 minutes and 27 seconds
import React, { createContext, useContext, useState } from "react"; import React, { createContext, useContext, useEffect, useState } from "react";
interface I18NContextType { interface I18NContextType {
language: string; language: string;
...@@ -10,12 +10,21 @@ const I18NContext = createContext<I18NContextType | undefined>(undefined); ...@@ -10,12 +10,21 @@ const I18NContext = createContext<I18NContextType | undefined>(undefined);
export const I18NProvider: React.FC<{ children: React.ReactNode }> = ({ export const I18NProvider: React.FC<{ children: React.ReactNode }> = ({
children, children,
}) => { }) => {
const [language, setLanguage] = useState<string>("cn"); // default language //const [language, setLanguage] = useState<string>("cn"); // default language
const [language, setLanguage] = useState<string>(() => {
// Get the language from localStorage if it exists, otherwise default to "cn"
return localStorage.getItem("language") || "cn";
});
const changeLanguage = (newLanguage: string) => { const changeLanguage = (newLanguage: string) => {
setLanguage(newLanguage); setLanguage(newLanguage);
localStorage.setItem("language", newLanguage);
}; };
useEffect(() => {
localStorage.setItem("language", language);
}, [language]);
return ( return (
<I18NContext.Provider value={{ language, changeLanguage }}> <I18NContext.Provider value={{ language, changeLanguage }}>
{children} {children}
......
...@@ -2,17 +2,21 @@ import React, { useEffect } from "react"; ...@@ -2,17 +2,21 @@ import React, { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Select } from "@/ui/Shared"; import { Select } from "@/ui/Shared";
import { useI18N } from "../I18NContext";
export const I18NSelector: React.FC = () => { export const I18NSelector: React.FC = () => {
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const { language, changeLanguage } = useI18N();
const onClickLanguageChange = (language: any) => { const onClickLanguageChange = (language: any) => {
changeLanguage(language);
i18n.changeLanguage(language); i18n.changeLanguage(language);
}; };
useEffect(() => { useEffect(() => {
// Adding language state as a dependency to force re-render // Adding language state as a dependency to force re-render
// when the language changes // when the language changes
i18n.changeLanguage(language);
}, [i18n.language]); }, [i18n.language]);
return ( return (
......
...@@ -86,6 +86,22 @@ ...@@ -86,6 +86,22 @@
"PendulumEffect": "灵摆效果", "PendulumEffect": "灵摆效果",
"CardEffect": "卡片效果" "CardEffect": "卡片效果"
}, },
"WaitRoom": {
"Deck": "卡组",
"JoinDuelist": "加入决斗者",
"JoinSpectator": "加入观战",
"DuelReady": "决斗准备",
"CancelReady": "取消准备",
"LeaveRoom": "退出房间",
"Expand": "展开",
"Collapse": "收起",
"Sidebar": "侧栏",
"StartGame": "开始游戏",
"PlsRockPaperScissors": "请猜拳",
"WaitOpponentPlayRockPaperScissors": "等待对方猜拳",
"PlsChooseWhoGoesFirst": "请选择先后手",
"WaitingForGameToStart": "等待游戏开始"
},
"Store": { "Store": {
"CannotAddTokens": "不能添加衍生物", "CannotAddTokens": "不能添加衍生物",
"CardTypeDoesNotMatch": "卡片种类不符合" "CardTypeDoesNotMatch": "卡片种类不符合"
......
...@@ -86,6 +86,22 @@ ...@@ -86,6 +86,22 @@
"PendulumEffect": "Pendulum Effect", "PendulumEffect": "Pendulum Effect",
"CardEffect": "Card Effect" "CardEffect": "Card Effect"
}, },
"WaitRoom": {
"Deck": "Deck",
"JoinDuelist": "Join Duelist",
"JoinSpectator": "Join Spectator",
"DuelReady": "Duel Ready",
"CancelReady": "Cancel Ready",
"LeaveRoom": "Leave Room",
"Expand": "Expand",
"Collapse": "Collapse",
"Sidebar": "Sidebar",
"StartGame": "Start Game",
"PlsRockPaperScissors": "Please play Rock, Paper, Scissors",
"WaitOpponentPlayRockPaperScissors": "Wait for the opponent to play Rock, Paper, Scissors",
"PlsChooseWhoGoesFirst": "Please choose who goes first",
"WaitingForGameToStart": "Waiting for the game to start"
},
"Store": { "Store": {
"CannotAddTokens": "Cannot add Tokens", "CannotAddTokens": "Cannot add Tokens",
"CardTypeDoesNotMatch": "The card type does not match" "CardTypeDoesNotMatch": "The card type does not match"
......
...@@ -21,6 +21,7 @@ const resources = { ...@@ -21,6 +21,7 @@ const resources = {
BuildDeck: translationChinese.BuildDeck, BuildDeck: translationChinese.BuildDeck,
Filter: translationChinese.Filter, Filter: translationChinese.Filter,
CardDetails: translationChinese.CardDetails, CardDetails: translationChinese.CardDetails,
WaitRoom: translationChinese.WaitRoom,
Store: translationChinese.Store, Store: translationChinese.Store,
}, },
en: { en: {
...@@ -30,6 +31,7 @@ const resources = { ...@@ -30,6 +31,7 @@ const resources = {
BuildDeck: translationEnglish.BuildDeck, BuildDeck: translationEnglish.BuildDeck,
Filter: translationEnglish.Filter, Filter: translationEnglish.Filter,
CardDetails: translationEnglish.CardDetails, CardDetails: translationEnglish.CardDetails,
WaitRoom: translationEnglish.WaitRoom,
Store: translationChinese.Store, Store: translationChinese.Store,
}, },
es: { es: {
......
...@@ -36,10 +36,13 @@ import { Background, IconFont, Select, SpecialButton } from "@/ui/Shared"; ...@@ -36,10 +36,13 @@ import { Background, IconFont, Select, SpecialButton } from "@/ui/Shared";
import { Chat } from "./Chat"; import { Chat } from "./Chat";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { Mora, MoraPopover, Tp, TpPopover } from "./Popover"; import { Mora, MoraPopover, Tp, TpPopover } from "./Popover";
import { useTranslation } from "react-i18next";
import { I18NSelector } from "../I18N";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const Component: React.FC = () => { export const Component: React.FC = () => {
const { t: i18n } = useTranslation("WaitRoom");
const { message } = App.useApp(); const { message } = App.useApp();
const { user } = useSnapshot(accountStore); const { user } = useSnapshot(accountStore);
const [collapsed, setCollapsed] = useState(false); const [collapsed, setCollapsed] = useState(false);
...@@ -135,8 +138,8 @@ export const Component: React.FC = () => { ...@@ -135,8 +138,8 @@ export const Component: React.FC = () => {
onClick={onReady} onClick={onReady}
> >
{me?.state === PlayerState.NO_READY {me?.state === PlayerState.NO_READY
? "决斗准备" ? i18n("DuelReady")
: "取消准备"} : i18n("CancelReady")}
</Button> </Button>
) : ( ) : (
<MoraAvatar <MoraAvatar
...@@ -254,12 +257,14 @@ const MoraAvatar: React.FC<{ mora?: Mora }> = ({ mora }) => ( ...@@ -254,12 +257,14 @@ const MoraAvatar: React.FC<{ mora?: Mora }> = ({ mora }) => (
const Controller: React.FC<{ onDeckChange: (deckName: string) => void }> = ({ const Controller: React.FC<{ onDeckChange: (deckName: string) => void }> = ({
onDeckChange, onDeckChange,
}) => { }) => {
const { t: i18n } = useTranslation("WaitRoom");
const snapDeck = useSnapshot(deckStore); const snapDeck = useSnapshot(deckStore);
const snapRoom = useSnapshot(roomStore); const snapRoom = useSnapshot(roomStore);
return ( return (
<Space> <Space>
<I18NSelector />
<Select <Select
title="卡组" title={ i18n("Deck") }
showSearch showSearch
style={{ width: "15.6rem" }} style={{ width: "15.6rem" }}
defaultValue={snapDeck.decks[0].deckName} defaultValue={snapDeck.decks[0].deckName}
...@@ -283,7 +288,7 @@ const Controller: React.FC<{ onDeckChange: (deckName: string) => void }> = ({ ...@@ -283,7 +288,7 @@ const Controller: React.FC<{ onDeckChange: (deckName: string) => void }> = ({
} }
}} }}
> >
{snapRoom.selfType === SelfType.OBSERVER ? "加入决斗者" : "加入观战"} {snapRoom.selfType === SelfType.OBSERVER ? i18n("JoinDuelist") : i18n("JoinSpectator") }
{!!snapRoom.observerCount && ( {!!snapRoom.observerCount && (
<Avatar size="small" style={{ marginLeft: 8 }}> <Avatar size="small" style={{ marginLeft: 8 }}>
{snapRoom.observerCount} {snapRoom.observerCount}
...@@ -299,6 +304,7 @@ const SideButtons: React.FC<{ ...@@ -299,6 +304,7 @@ const SideButtons: React.FC<{
collapsed: boolean; collapsed: boolean;
}> = ({ switchCollapse, collapsed }) => { }> = ({ switchCollapse, collapsed }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const { t: i18n } = useTranslation("WaitRoom");
return ( return (
<div className={styles["btns-side"]}> <div className={styles["btns-side"]}>
<Button <Button
...@@ -307,7 +313,7 @@ const SideButtons: React.FC<{ ...@@ -307,7 +313,7 @@ const SideButtons: React.FC<{
icon={ icon={
<span className={styles["btn-icon"]}> <span className={styles["btn-icon"]}>
<IconFont type="icon-exit" size={17} /> <IconFont type="icon-exit" size={17} />
<span className={styles["btn-text"]}>&#20;&#20;退出房间</span> <span className={styles["btn-text"]}>&nbsp;&nbsp;{i18n("LeaveRoom")}</span>
</span> </span>
} }
onClick={() => { onClick={() => {
...@@ -325,7 +331,7 @@ const SideButtons: React.FC<{ ...@@ -325,7 +331,7 @@ const SideButtons: React.FC<{
<span className={styles["btn-icon"]}> <span className={styles["btn-icon"]}>
<IconFont type="icon-side-bar-fill" size={16} /> <IconFont type="icon-side-bar-fill" size={16} />
<span className={styles["btn-text"]}> <span className={styles["btn-text"]}>
&#20;&#20;{collapsed ? "展开" : "收起"}侧栏 &nbsp;&nbsp;{collapsed ? i18n("Expand") : i18n("Collapse")}{/* {i18n("Sidebar")} */}
</span> </span>
</span> </span>
} }
...@@ -341,6 +347,7 @@ const ActionButton: React.FC<{ ...@@ -341,6 +347,7 @@ const ActionButton: React.FC<{
}> = ({ onMoraSelect, onTpSelect }) => { }> = ({ onMoraSelect, onTpSelect }) => {
const room = useSnapshot(roomStore); const room = useSnapshot(roomStore);
const { stage, isHost } = room; const { stage, isHost } = room;
const { t: i18n } = useTranslation("WaitRoom");
return ( return (
<MoraPopover onSelect={onMoraSelect}> <MoraPopover onSelect={onMoraSelect}>
<TpPopover onSelect={onTpSelect}> <TpPopover onSelect={onTpSelect}>
...@@ -360,32 +367,32 @@ const ActionButton: React.FC<{ ...@@ -360,32 +367,32 @@ const ActionButton: React.FC<{
{stage === RoomStage.WAITING ? ( {stage === RoomStage.WAITING ? (
<> <>
<IconFont type="icon-play" size={12} /> <IconFont type="icon-play" size={12} />
<span>开始游戏</span> <span>{i18n("StartGame")}</span>
</> </>
) : stage === RoomStage.HAND_SELECTING ? ( ) : stage === RoomStage.HAND_SELECTING ? (
<> <>
<IconFont type="icon-mora" size={20} /> <IconFont type="icon-mora" size={20} />
<span>请猜拳</span> <span>{i18n("PlsRockPaperScissors")}</span>
</> </>
) : stage === RoomStage.HAND_SELECTED ? ( ) : stage === RoomStage.HAND_SELECTED ? (
<> <>
<LoadingOutlined /> <LoadingOutlined />
<span>等待对方猜拳</span> <span>{i18n("WaitOpponentPlayRockPaperScissors")}</span>
</> </>
) : stage === RoomStage.TP_SELECTING ? ( ) : stage === RoomStage.TP_SELECTING ? (
<> <>
<IconFont type="icon-one" size={18} /> <IconFont type="icon-one" size={18} />
<span>请选择先后手</span> <span>{i18n("PlsChooseWhoGoesFirst")}</span>
</> </>
) : stage === RoomStage.TP_SELECTED ? ( ) : stage === RoomStage.TP_SELECTED ? (
<> <>
<LoadingOutlined /> <LoadingOutlined />
<span>等待游戏开始</span> <span>{i18n("WaitingForGameToStart")}</span>
</> </>
) : ( ) : (
<> <>
<LoadingOutlined /> <LoadingOutlined />
<span>等待游戏开始</span> <span>{i18n("WaitingForGameToStart")}</span>
</> </>
)} )}
</SpecialButton> </SpecialButton>
......
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