Commit 829c69f7 authored by BBeretta's avatar BBeretta

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

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