Commit 8e4daaf7 authored by BBeretta's avatar BBeretta

feat/language-translation (small updates, card img language, modals)

parent c0b1d41c
Pipeline #27739 failed with stages
in 8 minutes and 22 seconds
......@@ -7,6 +7,7 @@ import { proxy, useSnapshot } from "valtio";
import { sendSelectPositionResponse, ygopro } from "@/api";
import { NeosModal } from "../NeosModal";
import { useTranslation } from "react-i18next";
interface PositionModalProps {
isOpen: boolean;
......@@ -16,15 +17,19 @@ const defaultProps = { isOpen: false, positions: [] };
const localStore = proxy<PositionModalProps>(defaultProps);
const language = localStorage.getItem('language');
const title = language != 'cn' ? 'Please select a position' : '请选择表示形式';
export const PositionModal = () => {
const { isOpen, positions } = useSnapshot(localStore);
const [selected, setSelected] = useState<ygopro.CardPosition | undefined>(
undefined,
);
return (
<NeosModal
title="请选择表示形式"
title={title}
open={isOpen}
footer={
<Button
......@@ -51,7 +56,7 @@ export const PositionModal = () => {
{positions.map((position, idx) => (
<CheckCard
key={idx}
title={cardPositionToChinese(position)}
title={cardPosition(position)}
value={position}
/>
))}
......@@ -60,20 +65,24 @@ export const PositionModal = () => {
);
};
function cardPositionToChinese(position: ygopro.CardPosition): string {
function cardPosition(position: ygopro.CardPosition): string {
const faceUpAtk = language != 'cn' ? 'Face-Up Attack' : "正面攻击形式";
const faceUpDef = language != 'cn' ? 'Face-Up Defense' : "正面防守形式";
const faceDownAtk = language != 'cn' ? 'Face-Down Attack' : "背面攻击形式";
const faceDownDef = language != 'cn' ? 'Face-Down Defense' : "背面防守形式";
switch (position) {
// TODO: i18n
case ygopro.CardPosition.FACEUP_ATTACK: {
return "正面攻击形式";
return faceUpAtk;
}
case ygopro.CardPosition.FACEUP_DEFENSE: {
return "正面防守形式";
return faceUpDef;
}
case ygopro.CardPosition.FACEDOWN_ATTACK: {
return "背面攻击形式";
return faceDownAtk;
}
case ygopro.CardPosition.FACEDOWN_DEFENSE: {
return "背面防守形式";
return faceDownDef;
}
default: {
return "[?]";
......
......@@ -13,6 +13,7 @@ import { groupBy } from "../../utils";
import { showCardModal } from "../CardModal";
import { NeosModal } from "../NeosModal";
import styles from "./index.module.scss";
import { useTranslation } from "react-i18next";
export interface SelectCardsModalProps {
isOpen: boolean;
......@@ -57,6 +58,8 @@ export const SelectCardsModal: React.FC<SelectCardsModalProps> = ({
const minMaxText = min === max ? min : `${min}-${max}`;
const { t: i18n } = useTranslation("SelectCardModal");
useEffect(() => {
const initial: [ygopro.CardZone, Option[]][] = grouped.map(([zone, _]) => [
zone,
......@@ -107,8 +110,8 @@ export const SelectCardsModal: React.FC<SelectCardsModalProps> = ({
<>
<span>{preHintMsg}</span>
<span>{selectHintMsg}</span>
<span>(请选择 {minMaxText} 张卡)</span>
<span>{single ? "每次选择一张" : ""}</span>
<span>({i18n("PleaseSelect")} {minMaxText} {i18n("Cards")})</span>
<span>{single ? i18n("SelectOneCardAtTime") : ""}</span>
</>
} // TODO: 这里可以再细化一些
width={"38.25rem"}
......
......@@ -38,6 +38,19 @@ import { useTranslation } from "react-i18next";
const { useToken } = theme;
const FINISH_CANCEL_RESPONSE = -1;
const language = localStorage.getItem('language');
const drawPhase = language != 'cn' ? 'Draw' : '抽卡阶段';
const standbyPhase = language != 'cn' ? 'Standhy Phase' : '准备阶段';
const mainPhase1 = language != 'cn' ? 'Main Phase 1' : '主要阶段 1';
const battlePhase = language != 'cn' ? 'Battle Phase' : '战斗阶段';
const battleStart = language != 'cn' ? 'Battle Start' : '战斗开始';
const battleStep = language != 'cn' ? 'Battle Step' : '战斗步骤';
const damage = language != 'cn' ? 'Damage Step' : '伤害步骤';
const damageCalc = language != 'cn' ? 'Damage Step (Damage Calculation)' : '伤害步骤(伤害计算)';
const mainPhase2 = language != 'cn' ? 'Main Phase 2' : '主要阶段 2';
const endPhase = language != 'cn' ? 'End Phase' : '结束阶段';
const unknown = language != 'cn' ? 'Unknown' : '未知阶段';
// PhaseType, 中文, response, 是否显示,是否禁用
const initialPhaseBind: [
......@@ -47,17 +60,17 @@ const initialPhaseBind: [
show: boolean,
disabled: boolean,
][] = [
[PhaseType.DRAW, "抽卡阶段", -1, true, true],
[PhaseType.STANDBY, "准备阶段", -1, true, true],
[PhaseType.MAIN1, "主要阶段 1", -1, true, true],
[PhaseType.BATTLE, "战斗阶段", 6, true, false],
[PhaseType.BATTLE_START, "战斗开始", 3, false, true],
[PhaseType.BATTLE_STEP, "战斗步骤", 3, false, true],
[PhaseType.DAMAGE, "伤害步骤", 3, false, true],
[PhaseType.DAMAGE_GAL, "伤害步骤(伤害计算)", 3, false, true],
[PhaseType.MAIN2, "主要阶段 2", 2, true, false],
[PhaseType.END, "结束阶段", 7, true, false],
[PhaseType.UNKNOWN, "未知阶段", -1, false, true],
[PhaseType.DRAW, drawPhase, -1, true, true],
[PhaseType.STANDBY, standbyPhase, -1, true, true],
[PhaseType.MAIN1, mainPhase1, -1, true, true],
[PhaseType.BATTLE, battlePhase, 6, true, false],
[PhaseType.BATTLE_START, battleStart, 3, false, true],
[PhaseType.BATTLE_STEP, battleStep, 3, false, true],
[PhaseType.DAMAGE, damage, 3, false, true],
[PhaseType.DAMAGE_GAL, damageCalc, 3, false, true],
[PhaseType.MAIN2, mainPhase2, 2, true, false],
[PhaseType.END, endPhase, 7, true, false],
[PhaseType.UNKNOWN, unknown, -1, false, true],
];
export const Menu = () => {
......@@ -123,10 +136,14 @@ export const Menu = () => {
setPhaseSwitchItems(newPhaseSwitchItems);
}, [phaseBind]);
const allChain = language != 'cn' ? 'All Chain' : '';
const ignoreChain = language != 'cn' ? 'Ignore Chain' : '';
const smartChain = language != 'cn' ? 'Smart Chain' : '';
const chainSettingTexts = [
[ChainSetting.CHAIN_ALL, "全部连锁"],
[ChainSetting.CHAIN_IGNORE, "忽略连锁"],
[ChainSetting.CHAIN_SMART, "智能连锁"],
[ChainSetting.CHAIN_ALL, allChain],
[ChainSetting.CHAIN_IGNORE, ignoreChain],
[ChainSetting.CHAIN_SMART, smartChain],
] as const;
const chainSettingItems: MenuProps["items"] = chainSettingTexts.map(
([key, text]) => ({
......@@ -155,7 +172,7 @@ export const Menu = () => {
<div className={styles["menu-container"]}>
<SelectManager />
<DropdownWithTitle
title="请选择要进入的阶段"
title={i18n("SelectPhase")}
menu={{ items: phaseSwitchItems }}
disabled={globalDisable}
>
......@@ -177,7 +194,7 @@ export const Menu = () => {
type="text"
></Button>
</DropdownWithTitle>
<Tooltip title="聊天室">
<Tooltip title={i18n("ChatRoom")}>
<Button
icon={<MessageFilled />}
onClick={openChatBox}
......@@ -247,6 +264,7 @@ const ChainIcon: React.FC<{ chainSetting: ChainSetting }> = ({
};
const SelectManager: React.FC = () => {
const { t: i18n } = useTranslation("Menu");
const { finishable, cancelable } = useSnapshot(matStore.selectUnselectInfo);
const onFinishOrCancel = () => {
sendSelectSingleResponse(FINISH_CANCEL_RESPONSE);
......@@ -259,7 +277,7 @@ const SelectManager: React.FC = () => {
disabled={!cancelable && !finishable}
onClick={onFinishOrCancel}
>
{finishable ? "完成选择" : "取消选择"}
{finishable ? i18n("SelectionComplete") : i18n("Deselect")}
</Button>
</div>
);
......
......@@ -6,15 +6,15 @@ import CardPosition = ygopro.CardPosition;
const language = localStorage.getItem('language');
const sSet = language === 'en' ? 'Set' : '后场放置';
const summon = language === 'en' ? 'Normal Summon' : '普通召唤';
const spSummon = language === 'en' ? 'Special Summon' : '特殊召唤';
const posChange = language === 'en' ? 'Change Position' : '改变表示形式';
const mSet = language === 'en' ? 'Set' : '前场放置';
const activate = language === 'en' ? 'Activate' : '发动效果';
const attack = language === 'en' ? 'Attack' : '攻击';
export function interactTypeToString(t: InteractType): string {
const sSet = language != 'cn' ? 'Set' : '后场放置';
const summon = language != 'cn' ? 'Normal Summon' : '普通召唤';
const spSummon = language != 'cn' ? 'Special Summon' : '特殊召唤';
const posChange = language != 'cn' ? 'Change Position' : '改变表示形式';
const mSet = language != 'cn' ? 'Set' : '前场放置';
const activate = language != 'cn' ? 'Activate' : '发动效果';
const attack = language != 'cn' ? 'Attack' : '攻击';
switch (t) {
case InteractType.SUMMON:
return summon;
......
......@@ -177,6 +177,15 @@
"Menu": {
"DoYouSurrunder": "是否投降?",
"Cancel": "取消",
"Confirm": "确定"
"Confirm": "确定",
"SelectPhase": "请选择要进入的阶段",
"Deselect": "取消选择",
"SelectionComplete": "完成选择",
"ChatRoom": "聊天室"
},
"SelectCardModal": {
"PleaseSelect": "请选择",
"Cards": "张卡",
"SelectOneCardAtTime": "每次选择一张"
}
}
\ No newline at end of file
......@@ -177,6 +177,15 @@
"Menu": {
"DoYouSurrunder": "Do you surrender?",
"Cancel": "Cancel",
"Confirm": "Confirm"
"Confirm": "Confirm",
"SelectPhase": "Please select the phase",
"Deselect": "Deselect",
"SelectionComplete": "Selection complete",
"ChatRoom": "Chat Room"
},
"SelectCardModal": {
"PleaseSelect": "Please select",
"Cards": "Cards",
"SelectOneCardAtTime": "Select one card at a time"
}
}
\ No newline at end of file
......@@ -30,6 +30,7 @@ const resources = {
ReplayModal: translationChinese.ReplayModal,
Popover: translationChinese.Popover,
Menu: translationChinese.Menu,
SelectCardModal: translationChinese.SelectCardModal,
},
en: {
Header: translationEnglish.Header,
......@@ -47,6 +48,7 @@ const resources = {
ReplayModal: translationEnglish.ReplayModal,
Popover: translationEnglish.Popover,
Menu: translationEnglish.Menu,
SelectCardModal: translationEnglish.SelectCardModal,
},
es: {
Header: translationSpanish.Header,
......
......@@ -66,6 +66,18 @@ export function getCardImgUrl(code: number, back = false) {
if (isSuperReleaseCard(code)) {
return `${NeosConfig.preReleaseImgUrl}/${code}.jpg`;
} else {
const language = localStorage.getItem("language");
if (
language === "en" ||
language === "br" ||
language === "pt" ||
language === "fr"
) {
NeosConfig.releaseImgUrl = NeosConfig.releaseImgUrl.replace(
"zh-CN",
"en-US",
);
}
return `${NeosConfig.releaseImgUrl}/${code}.jpg`;
}
}
......@@ -37,7 +37,6 @@ 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();
......@@ -262,7 +261,6 @@ const Controller: React.FC<{ onDeckChange: (deckName: string) => void }> = ({
const snapRoom = useSnapshot(roomStore);
return (
<Space>
<I18NSelector />
<Select
title={ i18n("Deck") }
showSearch
......
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