From: Benjamin Auder <benjamin.auder@somewhere> Date: Wed, 5 Feb 2020 00:57:37 +0000 (+0100) Subject: Relocate board adjuster + start working on translations X-Git-Url: https://git.auder.net/doc/html/scripts/css/img/current/mini-custom.min.css?a=commitdiff_plain;h=602d6befd30793111d3fda6e733f73e08d8b7a30;p=vchess.git Relocate board adjuster + start working on translations --- diff --git a/client/src/components/BaseGame.vue b/client/src/components/BaseGame.vue index 8fcb77f0..1240bcb2 100644 --- a/client/src/components/BaseGame.vue +++ b/client/src/components/BaseGame.vue @@ -2,10 +2,17 @@ div#baseGame(tabindex=-1 @click="() => focusBg()" @keydown="handleKeys" @wheel="handleScroll") input#modalEog.modal(type="checkbox") - div(role="dialog" data-checkbox="modalEog" aria-labelledby="eogMessage") + div#eogDiv(role="dialog" data-checkbox="modalEog" aria-labelledby="eogMessage") .card.smallpad.small-modal.text-center label.modal-close(for="modalEog") h3#eogMessage.section {{ endgameMessage }} + input#modalAdjust.modal(type="checkbox") + div#adjuster(role="dialog" data-checkbox="modalAdjust" aria-labelledby="labelAdjust") + .card.smallpad.small-modal.text-center + label.modal-close(for="modalAdjust") + label#labelAdjust(for="boardSize") {{ st.tr["Board size"] }} + input#boardSize.slider(type="range" min="0" max="100" value="50" + @input="adjustBoard") #gameContainer #boardContainer Board(:vr="vr" :last-move="lastMove" :analyze="analyze" @@ -23,6 +30,7 @@ div#baseGame(tabindex=-1 @click="() => focusBg()" #downloadDiv(v-if="game.vname!='Dark' || game.score!='*'") a#download(href="#") button(@click="download") {{ st.tr["Download PGN"] }} + button(onClick="doClick('modalAdjust')") ⤢ button(v-if="game.vname!='Dark' && game.mode!='analyze'" @click="analyzePosition") | {{ st.tr["Analyze"] }} @@ -42,6 +50,7 @@ import MoveList from "@/components/MoveList.vue"; import { store } from "@/store"; import { getSquareId } from "@/utils/squareId"; import { getDate } from "@/utils/datetime"; +import { processModalClick } from "@/utils/modalClick"; export default { name: 'my-base-game', @@ -86,7 +95,7 @@ export default { color = "White"; else //if (this.moves[L-1].color == "w") color = "Black"; - return color + " turn"; + return this.st.tr[color + " to move"]; }, analyze: function() { return this.game.mode=="analyze" || @@ -99,6 +108,8 @@ export default { this.re_setVariables(); }, mounted: function() { + [document.getElementById("eogDiv"),document.getElementById("adjuster")] + .forEach(elt => elt.addEventListener("click", processModalClick)); // Take full width on small screens: let boardSize = parseInt(localStorage.getItem("boardSize")); if (!boardSize) @@ -111,12 +122,41 @@ export default { document.getElementById("boardContainer").style.width = boardSize + "px"; let gameContainer = document.getElementById("gameContainer"); gameContainer.style.width = (boardSize + movesWidth) + "px"; + // TODO: find the right formula here: + //document.getElementById("boardSize").value = Math.floor(boardSize / 10); + // timeout to avoid calling too many time the adjust method + let timeoutLaunched = false; + window.addEventListener("resize", (e) => { + if (!timeoutLaunched) + { + timeoutLaunched = true; + setTimeout( () => { + this.adjustBoard(); + timeoutLaunched = false; + }, 500); + } + }); }, methods: { focusBg: function() { // NOTE: small blue border appears... document.getElementById("baseGame").focus(); }, + adjustBoard: function() { + const boardContainer = document.getElementById("boardContainer"); + if (!boardContainer) + return; //no board on page + const k = document.getElementById("boardSize").value; + const movesWidth = (window.innerWidth >= 768 ? 280 : 0); + const minBoardWidth = 240; //TODO: these 240 and 280 are arbitrary... + // Value of 0 is board min size; 100 is window.width [- movesWidth] + const boardSize = minBoardWidth + + k * (window.innerWidth - (movesWidth+minBoardWidth)) / 100; + localStorage.setItem("boardSize", boardSize); + boardContainer.style.width = boardSize + "px"; + document.getElementById("gameContainer").style.width = + (boardSize + movesWidth) + "px"; + }, handleKeys: function(e) { if ([32,37,38,39,40].includes(e.keyCode)) e.preventDefault(); @@ -223,7 +263,7 @@ export default { return pgn + "\n"; }, getScoreMessage: function(score) { - let eogMessage = "Undefined"; + let eogMessage = "Undefined"; //not translated: unused switch (score) { case "1-0": @@ -236,7 +276,7 @@ export default { eogMessage = this.st.tr["Draw"]; break; case "?": - eogMessage = this.st.tr["Unfinished"]; + eogMessage = this.st.tr["Unknown"]; break; } return eogMessage; diff --git a/client/src/components/ChallengeList.vue b/client/src/components/ChallengeList.vue index c57073c0..095c0966 100644 --- a/client/src/components/ChallengeList.vue +++ b/client/src/components/ChallengeList.vue @@ -3,10 +3,10 @@ div table thead tr - th Variant - th From - th To - th Cadence + th {{ st.tr["Variant"] }} + th {{ st.tr["From"] }} + th {{ st.tr["To"] }} + th {{ st.tr["Time control"] }} tbody tr(v-for="c in sortedChallenges" @click="$emit('click-challenge',c)") td(data-label="Variant") {{ c.vname }} diff --git a/client/src/components/Chat.vue b/client/src/components/Chat.vue index 65e0dcb0..752dadaf 100644 --- a/client/src/components/Chat.vue +++ b/client/src/components/Chat.vue @@ -35,8 +35,8 @@ export default { }; const socketCloseListener = () => { store.socketCloseListener(); //reinitialize connexion (in store.js) - this.st.conn.addEventListener('message', socketMessageListener); - this.st.conn.addEventListener('close', socketCloseListener); + this.st.conn.addEventListener("message", socketMessageListener); + this.st.conn.addEventListener("close", socketCloseListener); }; this.st.conn.onmessage = socketMessageListener; this.st.conn.onclose = socketCloseListener; diff --git a/client/src/components/ContactForm.vue b/client/src/components/ContactForm.vue index 45b7c011..ed4729e3 100644 --- a/client/src/components/ContactForm.vue +++ b/client/src/components/ContactForm.vue @@ -43,8 +43,8 @@ export default { if (!!error) return alert(error); if (content.value.trim().length == 0) - return alert("Empty message"); - if (subject.value.trim().length == 0 && !confirm("No subject. Send anyway?")) + return alert(this.st.tr["Empty message"]); + if (subject.value.trim().length == 0 && !confirm(this.st.tr["No subject. Send anyway?"])) return; // Message sending: diff --git a/client/src/components/GameList.vue b/client/src/components/GameList.vue index 0d2fbf46..c1557a23 100644 --- a/client/src/components/GameList.vue +++ b/client/src/components/GameList.vue @@ -3,10 +3,10 @@ div table thead tr - th Variant - th White - th Black - th Time control + th {{ st.tr["Variant"] }} + th {{ st.tr["White"] }} + th {{ st.tr["Black"] }} + th {{ st.tr["Time control"] }} th(v-if="showResult") Result tbody tr(v-for="g in sortedGames" @click="$emit('show-game',g)" diff --git a/client/src/components/Settings.vue b/client/src/components/Settings.vue index 1cfbdc8f..003dc15f 100644 --- a/client/src/components/Settings.vue +++ b/client/src/components/Settings.vue @@ -5,40 +5,25 @@ div aria-labelledby="settingsTitle") .card.smallpad(@change="updateSettings") label.modal-close(for="modalSettings") - h3#settingsTitle.section {{ st.tr["Preferences"] }} fieldset - label(for="setSqSize") - | {{ st.tr["Square size (in pixels). 0 for 'adaptative'"] }} - input#setSqSize(type="number" v-model="st.settings.sqSize") - fieldset - label(for="selectHints") {{ st.tr["Show move hints?"] }} - select#setHints(v-model="st.settings.hints") - option(value="0") {{ st.tr["None"] }} - option(value="1") {{ st.tr["Moves from a square"] }} - option(value="2") {{ st.tr["Pieces which can move"] }} + label(for="setHints") {{ st.tr["Show possible moves?"] }} + input#setHints(type="checkbox" v-model="st.settings.hints") fieldset label(for="setHighlight") - | {{ st.tr["Highlight squares? (Last move & checks)"] }} + | {{ st.tr["Highlight last move and checks?"] }} input#setHighlight(type="checkbox" v-model="st.settings.highlight") fieldset - label(for="setCoords") {{ st.tr["Show board coordinates?"] }} - input#setCoords(type="checkbox" v-model="st.settings.coords") - fieldset - label(for="selectColor") {{ st.tr["Board colors"] }} + label(for="setBcolor") {{ st.tr["Board colors"] }} select#setBcolor(v-model="st.settings.bcolor") option(value="lichess") {{ st.tr["brown"] }} option(value="chesscom") {{ st.tr["green"] }} option(value="chesstempo") {{ st.tr["blue"] }} fieldset - label(for="selectSound") {{ st.tr["Play sounds?"] }} + label(for="setSound") {{ st.tr["Play sounds?"] }} select#setSound(v-model="st.settings.sound") option(value="0") {{ st.tr["None"] }} option(value="1") {{ st.tr["New game"] }} option(value="2") {{ st.tr["All"] }} - fieldset - .slidecontainer - input#myRange.slider(type="range" min="0" max="100" value="50" - @input="adjustBoard") </template> <script> @@ -50,45 +35,13 @@ export default { st: store.state, }; }, - mounted: function() { - const boardSize = localStorage.getItem("boardSize"); - if (!!boardSize) - document.getElementById("myRange").value = Math.floor(boardSize / 10); - // timeout to avoid calling too many time the adjust method - let timeoutLaunched = false; - window.addEventListener("resize", (e) => { - if (!timeoutLaunched) - { - timeoutLaunched = true; - setTimeout( () => { - this.adjustBoard(); - timeoutLaunched = false; - }, 500); - } - }); - }, methods: { updateSettings: function(event) { const propName = event.target.id.substr(3).replace(/^\w/, c => c.toLowerCase()) - localStorage[propName] = ["highlight","coords"].includes(propName) - ? event.target.checked - : event.target.value; - }, - adjustBoard: function() { - const boardContainer = document.getElementById("boardContainer"); - if (!boardContainer) - return; //no board on page - const k = document.getElementById("myRange").value; - const movesWidth = (window.innerWidth >= 768 ? 280 : 0); - const minBoardWidth = 240; //TODO: these 240 and 280 are arbitrary... - // Value of 0 is board min size; 100 is window.width [- movesWidth] - const boardSize = minBoardWidth + - k * (window.innerWidth - (movesWidth+minBoardWidth)) / 100; - localStorage.setItem("boardSize", boardSize); - boardContainer.style.width = boardSize + "px"; - document.getElementById("gameContainer").style.width = - (boardSize + movesWidth) + "px"; + localStorage[propName] = ["bcolor","sound"].includes(propName) + ? event.target.value + : event.target.checked; }, }, }; diff --git a/client/src/components/UpsertUser.vue b/client/src/components/UpsertUser.vue index ecd51fa9..d54014df 100644 --- a/client/src/components/UpsertUser.vue +++ b/client/src/components/UpsertUser.vue @@ -8,27 +8,26 @@ div form#userForm(@submit.prevent="onSubmit()" @keyup.enter="onSubmit") div(v-show="stage!='Login'") fieldset - label(for="username") Name + label(for="username") {{ st.tr["Name"] }} input#username(type="text" v-model="user.name") fieldset - label(for="useremail") Email + label(for="useremail") {{ st.tr["Email"] }} input#useremail(type="email" v-model="user.email") fieldset - label(for="notifyNew") Notify new moves & games + label(for="notifyNew") {{ st.tr["Notifications by email"] }} input#notifyNew(type="checkbox" v-model="user.notify") div(v-show="stage=='Login'") fieldset - label(for="nameOrEmail") Name or Email + label(for="nameOrEmail") {{ st.tr["Name or Email"] }} input#nameOrEmail(type="text" v-model="nameOrEmail") .button-group button#submit(type="button" @click="onSubmit()") - span {{ submitMessage }} - i.material-icons send + span {{ st.tr[submitMessage] }} button(v-if="stage!='Update'" @click="toggleStage()") - span {{ stage=="Login" ? "Register" : "Login" }} + span {{ st.tr[stage=="Login" ? "Register" : "Login"] }} button#logoutBtn(v-else @click="doLogout()") - span Logout - #dialog(:style="{display: displayInfo}") {{ infoMsg }} + span {{ st.tr["Logout"] }} + #dialog(:style="{display: displayInfo}") {{ st.tr[infoMsg] }} </template> <script> @@ -44,6 +43,7 @@ export default { logStage: "Login", //or Register infoMsg: "", enterTime: Number.MAX_SAFE_INTEGER, //for a basic anti-bot strategy + st: store.state, }; }, watch: { diff --git a/client/src/translations/en.js b/client/src/translations/en.js index dbbddd8d..0a7f93db 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -1,72 +1,110 @@ export const translations = { - //jugada ou movimiento ? - //fin de la partida au lieu de final de partida ? - + "Abort": "Abort", + "About": "About", + "Accept draw?": "Accept draw?", + "All": "All", + "Analyze": "Analyze", + "Analyze in Dark mode makes no sense!": "Analyze in Dark mode makes no sense!", + "Apply": "Apply", + "Black": "Black", + "Black to move": "Black to move", + "Black win": "Black win", + "Board colors": "Board colors", + "Board size": "Board size", + "blue": "blue", + "brown": "brown", + "Challenge declined": "Challenge declined", + "Connection token sent. Check your emails!": "Connection token sent. Check your emails!", + "Contact": "Contact", + "Contact form": "Contact form", + "Content": "Content", + "Correspondance challenges": "Correspondance challenges", + "Correspondance games": "Correspondance games", + "Database error:": "Database error:", + "Download PGN": "Download PGN", + "Draw": "Draw", + "Email": "Email", + "Email sent!": "Email sent!", + "Empty message": "Empty message", + "Error while loading database:": "Error while loading database:", + "Forum": "Forum", + "From": "From", + "Game retrieval failed:": "Game retrieval failed:", + "Game removal failed:": "Game removal failed:", + "Go": "Go", + "green": "green", "Hall": "Hall", + "Highlight last move and checks?": "Highlight last move and checks?", + "Variant": "Variant", "Variants": "Variants", - "My games": "My games", - "Forum": "Forum", - "Contact": "Contact", - "About": "About", - "Language": "Language", - "Email": "Email", + "Live challenges": "Live challenges", + "Live games": "Live games", + "Login": "Login", + "Logout": "Logout", + "Modifications applied!": "Modifications applied!", + "Mutual agreement": "Mutual agreement", + "My games": "My games", + "Name": "Name", + "Name or Email": "Name or Email", + "New game": "New game", + "No subject. Send anyway?": "No subject. Send anyway?", + "None": "None", + "Notifications by email": "Notifications by email", + "Offer draw?": "Offer draw?", + "Play sounds?": "Play sounds?", + "Play with?": "Play with?", + "Please log in to accept corr challenges": "Please log in to accept corr challenges", + "Please log in to play corr games": "Please log in to play corr games", + "Please select a variant": "Please select a variant", + "Practice": "Practice", + "Processing... Please wait": "Processing... Please wait", + "participant(s):": "participant(s):", + "Register": "Register", + "Registration complete! Please check your emails": "Registration complete! Please check your emails", + "Resign": "Resign", + "Resign the game?": "Resign the game?", + "Rules": "Rules", + "Sample game": "Sample game", + "Send": "Send", + "Show possible moves?": "Show possible moves?", + "Send challenge": "Send challenge", + "Settings": "Settings", + "Stop game": "Stop game", "Subject": "Subject", - "Content": "Content", - "Email sent!": "Email sent!", + "Terminate game?": "Terminate game?", + "Three repetitions": "Three repetitions", + "Time": "Time", + "Time control": "Time control", + "To": "To", + "Type first letters...": "Type first letters...", + "Type here": "Type here", + "Unknown": "Unknown", + "Warning: target is not connected": "Warning: target is not connected", + "Warning: multi-tabs not supported": "Warning: multi-tabs not supported", + "White": "White", + "White to move": "White to move", + "White win": "White win", + "Who's there?": "Who's there?", // Variants boxes: + "Balanced sliders & leapers": "Balanced sliders & leapers", + "Big board": "Big board", + "Board upside down": "Board upside down", "Both sides of the mirror": "Both sides of the mirror", - "Keep antiking in check": "Keep antiking in check", - "Explosive captures": "Explosive captures", - "Shared pieces": "Shared pieces", - "Standard rules": "Standard rules", - "Captures reborn": "Captures reborn", "Capture all of a kind": "Capture all of a kind", - "Big board": "Big board", - "Lose all pieces": "Lose all pieces", - "Laws of attraction": "Laws of attraction", + "Captures reborn": "Captures reborn", "Exchange pieces positions": "Exchange pieces positions", "Exotic captures": "Exotic captures", - "Balanced sliders & leapers": "Balanced sliders & leapers", - "Reverse captures": "Reverse captures", - "Pawns move diagonally": "Pawns move diagonally", + "Explosive captures": "Explosive captures", "In the shadow": "In the shadow", + "Keep antiking in check": "Keep antiking in check", + "Lose all pieces": "Lose all pieces", + "Laws of attraction": "Laws of attraction", "Move twice": "Move twice", - "Board upside down": "Board upside down", - - // Variant page: - "New game": "New game", - "Waiting for opponent...": "Waiting for opponent...", - "Rules": "Rules", - "Play": "Play", - "White win": "White win", - "Black win": "Black win", - "Draw": "Draw", - "Unfinished": "Unknown", - "Settings": "Settings", - "Resign": "Resign", - "Undo": "Undo", - "Flip board": "Flip board", - "Ok": "Ok", - "Random": "Random", - "Preferences": "Preferences", - "My name is...": "My name is...", - "Show hints?": "Show hints?", - "Board colors": "Board colors", - "brown": "brown", - "green": "green", - "blue": "blue", - "Play sounds?": "Play sounds?", - "None": "None", - "All": "All", - "Type here": "Type here", - "Send": "Send", - "Download PGN": "Download PGN", - "Analyze": "Analyze", - "Cancel": "Cancel", - - // Game page: - + "Pawns move diagonally": "Pawns move diagonally", + "Reverse captures": "Reverse captures", + "Shared pieces": "Shared pieces", + "Standard rules": "Standard rules", }; diff --git a/client/src/translations/es.js b/client/src/translations/es.js index e3482187..e655aa25 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -1,5 +1,7 @@ export const translations = { + //jugada ou movimiento ? + //fin de la partida au lieu de final de partida ? "Language": "Idioma", // Index page: diff --git a/client/src/utils/gameStorage.js b/client/src/utils/gameStorage.js index 630d1c75..7fadbedd 100644 --- a/client/src/utils/gameStorage.js +++ b/client/src/utils/gameStorage.js @@ -17,6 +17,7 @@ // } import { ajax } from "@/utils/ajax"; +import { store } from "@/store"; function dbOperation(callback) { @@ -24,7 +25,7 @@ function dbOperation(callback) let DBOpenRequest = window.indexedDB.open("vchess", 4); DBOpenRequest.onerror = function(event) { - alert("Database error: " + event.target.errorCode); + alert(store.state.tr["Database error:"] + " " + event.target.errorCode); }; DBOpenRequest.onsuccess = function(event) { @@ -36,7 +37,7 @@ function dbOperation(callback) DBOpenRequest.onupgradeneeded = function(event) { let db = event.target.result; db.onerror = function(event) { - alert("Error while loading database: " + event.target.errorCode); + alert(store.state.tr["Error while loading database:"] + " " + event.target.errorCode); }; // Create objectStore for vchess->games let objectStore = db.createObjectStore("games", { keyPath: "id" }); @@ -58,7 +59,7 @@ export const GameStorage = callback({}); //everything's fine } transaction.onerror = function() { - callback({errmsg: "addGame failed: " + transaction.error}); + callback({errmsg: store.state.tr["Game retrieval failed:"] + " " + transaction.error}); }; } let objectStore = transaction.objectStore("games"); @@ -176,7 +177,7 @@ export const GameStorage = callback({}); //everything's fine } transaction.onerror = function() { - callback({errmsg: "removeGame failed: " + transaction.error}); + callback({errmsg: store.state.tr["Game removal failed:"] + " " + transaction.error}); }; } transaction.objectStore("games").delete(gameId); diff --git a/client/src/views/Analyze.vue b/client/src/views/Analyze.vue index 0c23a28b..af6bface 100644 --- a/client/src/views/Analyze.vue +++ b/client/src/views/Analyze.vue @@ -4,10 +4,8 @@ main .col-sm-12 #fenDiv input#fen(v-model="curFen" @input="adjustFenSize") - button(@click="gotoFen") Go - .row - .col-sm-12.col-md-10.col-md-offset-1 - BaseGame(:game="game" :vr="vr" ref="basegame") + button(@click="gotoFen") {{ st.tr["Go"] }} + BaseGame(:game="game" :vr="vr" ref="basegame") </template> <script> @@ -55,7 +53,7 @@ export default { this.initialize(this.loadGame); else { - alert("Please, analyze in Dark mode makes no sense ~_^"); + alert(this.st.tr["Analyze in Dark mode makes no sense!"]); history.back(); //or this.$router.go(-1) } }, diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 7d4369be..6ea6cdd9 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -1,12 +1,11 @@ <template lang="pug"> main input#modalChat.modal(type="checkbox" @click="resetChatColor") - div#chatWrap(role="dialog" data-checkbox="modalChat" - aria-labelledby="inputChat") + div#chatWrap(role="dialog" data-checkbox="modalChat" aria-labelledby="inputChat") #chat.card label.modal-close(for="modalChat") #participants - span {{ Object.keys(people).length }} participant(s): + span {{ Object.keys(people).length }} st.tr["participant(s):"] span(v-for="p in Object.values(people)" v-if="!!p.name") | {{ p.name }} span.anonymous(v-if="Object.values(people).some(p => !p.name)") @@ -17,9 +16,10 @@ main #aboveBoard.col-sm-12.col-md-9.col-md-offset-3.col-lg-10.col-lg-offset-2 button#chatBtn(onClick="doClick('modalChat')") Chat #actions(v-if="game.score=='*'") - button(@click="clickDraw" :class="{['draw-' + drawOffer]: true}") Draw - button(@click="abortGame") Abort - button(@click="resign") Resign + button(@click="clickDraw" :class="{['draw-' + drawOffer]: true}") + | {{ st.tr["Draw"] }} + button(@click="abortGame") {{ st.tr["Abort"] }} + button(@click="resign") {{ st.tr["Resign"] }} #playersInfo p span.name(:class="{connected: isConnected(0)}") @@ -94,7 +94,7 @@ export default { { clearInterval(clockUpdate); if (countdown < 0) - this.gameOver(this.vr.turn=="w" ? "0-1" : "1-0", "Time"); + this.gameOver(this.vr.turn=="w" ? "0-1" : "1-0", this.st.tr["Time"]); } else { @@ -159,7 +159,7 @@ export default { switch (data.code) { case "duplicate": - alert("Warning: duplicate 'offline' connection"); + alert(this.st.tr["Warning: multi-tabs not supported"]); break; // 0.2] Receive clients list (just socket IDs) case "pollclients": @@ -246,13 +246,13 @@ export default { break; } case "resign": - this.gameOver(data.side=="b" ? "1-0" : "0-1", "Resign"); + this.gameOver(data.side=="b" ? "1-0" : "0-1", this.st.tr["Resign"]); break; case "abort": - this.gameOver("?", "Abort"); + this.gameOver("?", this.st.tr["Abort"]); break; case "draw": - this.gameOver("1/2", data.message); + this.gameOver("1/2", this.st.tr[data.message]); break; case "drawoffer": // NOTE: observers don't know who offered draw @@ -304,7 +304,7 @@ export default { clickDraw: function() { if (["received","threerep"].includes(this.drawOffer)) { - if (!confirm("Accept draw?")) + if (!confirm(this.st.tr["Accept draw?"])) return; const message = (this.drawOffer == "received" ? "Mutual agreement" @@ -316,11 +316,11 @@ export default { message:message, target:sid})); } }); - this.gameOver("1/2", message); + this.gameOver("1/2", this.st.tr[message]); } else if (this.drawOffer == "") //no effect if drawOffer == "sent" { - if (!confirm("Offer draw?")) + if (!confirm(this.st.tr["Offer draw?"])) return; this.drawOffer = "sent"; Object.keys(this.people).forEach(sid => { @@ -333,7 +333,7 @@ export default { abortGame: function() { if (!confirm(this.st.tr["Terminate game?"])) return; - this.gameOver("?", "Abort"); + this.gameOver("?", this.st.tr["Abort"]); Object.keys(this.people).forEach(sid => { if (sid != this.st.user.sid) { @@ -345,7 +345,7 @@ export default { }); }, resign: function(e) { - if (!confirm("Resign the game?")) + if (!confirm(this.st.tr["Resign the game?"])) return; Object.keys(this.people).forEach(sid => { if (sid != this.st.user.sid) @@ -354,7 +354,7 @@ export default { side:this.game.mycolor, target:sid})); } }); - this.gameOver(this.game.mycolor=="w" ? "0-1" : "1-0", "Resign"); + this.gameOver(this.game.mycolor=="w" ? "0-1" : "1-0", this.st.tr["Resign"]); }, // 3 cases for loading a game: // - from indexedDB (running or completed live game I play) diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index 2180509c..48ad4d3f 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -1,24 +1,24 @@ <template lang="pug"> main input#modalInfo.modal(type="checkbox") - div(role="dialog" aria-labelledby="infoMessage") + div#infoDiv(role="dialog" data-checkbox="modalInfo" aria-labelledby="infoMessage") .card.smallpad.small-modal.text-center label.modal-close(for="modalInfo") h3#infoMessage.section p(v-html="infoMessage") input#modalNewgame.modal(type="checkbox") - div(role="dialog" data-checkbox="modalNewgame" + div#newgameDiv(role="dialog" data-checkbox="modalNewgame" aria-labelledby="titleFenedit") .card.smallpad(@keyup.enter="newChallenge") label#closeNewgame.modal-close(for="modalNewgame") fieldset - label(for="selectVariant") {{ st.tr["Variant"] }} + label(for="selectVariant") {{ st.tr["Variant"] }} * select#selectVariant(v-model="newchallenge.vid") option(v-for="v in st.variants" :value="v.id" :selected="newchallenge.vid==v.id") | {{ v.name }} fieldset - label(for="timeControl") {{ st.tr["Time control"] }} + label(for="timeControl") {{ st.tr["Time control"] }} * div#predefinedTimeControls button 3+2 button 5+3 @@ -26,29 +26,29 @@ main input#timeControl(type="text" v-model="newchallenge.timeControl" placeholder="5+0, 1h+30s, 7d+1d ...") fieldset(v-if="st.user.id > 0") - label(for="selectPlayers") {{ st.tr["Play with? (optional)"] }} + label(for="selectPlayers") {{ st.tr["Play with?"] }} input#selectPlayers(type="text" v-model="newchallenge.to") fieldset(v-if="st.user.id > 0 && newchallenge.to.length > 0") - label(for="inputFen") {{ st.tr["FEN (optional)"] }} + label(for="inputFen") {{ FEN }} input#inputFen(type="text" v-model="newchallenge.fen") button(@click="newChallenge") {{ st.tr["Send challenge"] }} .row .col-sm-12 - button#newGame(onClick="doClick('modalNewgame')") New game + button#newGame(onClick="doClick('modalNewgame')") {{ st.tr["New game"] }} .row .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 div .button-group button(@click="(e) => setDisplay('c','live',e)" class="active") - | Live Challenges + | {{ st.tr["Live challenges"] }} button(@click="(e) => setDisplay('c','corr',e)") - | Correspondance challenges + | {{ st.tr["Correspondance challenges"] }} ChallengeList(v-show="cdisplay=='live'" :challenges="filterChallenges('live')" @click-challenge="clickChallenge") ChallengeList(v-show="cdisplay=='corr'" :challenges="filterChallenges('corr')" @click-challenge="clickChallenge") #people - h3.text-center Who's there? + h3.text-center {{ st.tr["Who's there?"] }} #players p(v-for="p in Object.values(people)" v-if="!!p.name") span {{ p.name }} @@ -64,9 +64,9 @@ main div .button-group button(@click="(e) => setDisplay('g','live',e)" class="active") - | Live games + | {{ st.tr["Live games"] }} button(@click="(e) => setDisplay('g','corr',e)") - | Correspondance games + | {{ st.tr["Correspondance games"] }} GameList(v-show="gdisplay=='live'" :games="filterGames('live')" @show-game="showGame") GameList(v-show="gdisplay=='corr'" :games="filterGames('corr')" @@ -83,6 +83,8 @@ import Chat from "@/components/Chat.vue"; import GameList from "@/components/GameList.vue"; import ChallengeList from "@/components/ChallengeList.vue"; import { GameStorage } from "@/utils/gameStorage"; +import { processModalClick } from "@/utils/modalClick"; + export default { name: "my-hall", components: { @@ -208,6 +210,8 @@ export default { this.st.conn.onclose = socketCloseListener; }, mounted: function() { + [document.getElementById("infoDiv"),document.getElementById("newgameDiv")] + .forEach(elt => elt.addEventListener("click", processModalClick)); document.querySelectorAll("#predefinedTimeControls > button").forEach( (b) => { b.addEventListener("click", () => { this.newchallenge.timeControl = b.innerHTML; } @@ -271,7 +275,7 @@ export default { if (!targetSid) { if (!!warnDisconnected) - alert("Warning: " + to + " is not connected"); + alert(this.st.tr["Warning: target is not connected"]); return false; } else @@ -293,7 +297,7 @@ export default { switch (data.code) { case "duplicate": - alert("Warning: duplicate 'offline' connection"); + alert(this.st.tr["Warning: multi-tabs not supported"]); break; // 0.2] Receive clients list (just socket IDs) case "pollclients": @@ -413,7 +417,7 @@ export default { { ArrayFun.remove(this.challenges, c => c.id == data.cid); localStorage.removeItem("challenge"); - alert(this.people[data.from].name + " declined your challenge"); + alert(this.st.tr["Challenge declined"]); break; } case "deletechallenge": @@ -466,7 +470,7 @@ export default { }, newChallenge: async function() { if (this.newchallenge.vid == "") - return alert("Please select a variant"); + return alert(this.st.tr["Please select a variant"]); const vname = this.getVname(this.newchallenge.vid); const vModule = await import("@/variants/" + vname + ".js"); window.V = vModule.VariantRules; @@ -477,7 +481,7 @@ export default { return alert(error); const ctype = this.classifyObject(this.newchallenge); if (ctype == "corr" && this.st.user.id <= 0) - return alert("Please log in to play correspondance games"); + return alert(this.st.tr["Please log in to play correspondance games"]); // NOTE: "from" information is not required here let chall = Object.assign({}, this.newchallenge); const finishAddChallenge = (cid,warnDisconnected) => { @@ -545,7 +549,7 @@ export default { if (!myChallenge) { if (c.type == "corr" && this.st.user.id <= 0) - return alert("Please log in to accept corr challenges"); + return alert(this.st.tr["Please log in to accept corr challenges"]); c.accepted = true; if (!!c.to) //c.to == this.st.user.name (connected) { diff --git a/client/src/views/MyGames.vue b/client/src/views/MyGames.vue index 0973d32c..8183ff40 100644 --- a/client/src/views/MyGames.vue +++ b/client/src/views/MyGames.vue @@ -3,8 +3,8 @@ main .row .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 .button-group - button(@click="display='live'") Live games - button(@click="display='corr'") Correspondance games + button(@click="display='live'") {{ st.tr["Live games"] }} + button(@click="display='corr'") {{ st.tr["Correspondance games"] }} GameList(v-show="display=='live'" :games="filterGames('live')" @show-game="showGame") GameList(v-show="display=='corr'" :games="filterGames('corr')" diff --git a/client/src/views/Rules.vue b/client/src/views/Rules.vue index b0abd8de..8e883301 100644 --- a/client/src/views/Rules.vue +++ b/client/src/views/Rules.vue @@ -3,13 +3,13 @@ main .row .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 .button-group - button(@click="clickReadRules") Rules + button(@click="clickReadRules") {{ st.tr["Rules"] }} button(v-show="!gameInProgress" @click="() => startGame('auto')") - | Sample game + | {{ st.tr["Sample game"] }} button(v-show="!gameInProgress" @click="() => startGame('versus')") - | Practice + | {{ st.tr["Practice"] }} button(v-show="gameInProgress" @click="() => stopGame()") - | Stop game + | {{ st.tr["Stop game"] }} button(v-if="display=='rules' && gameInfo.vname!='Dark'" @click="gotoAnalyze") | {{ st.tr["Analyze"] }} diff --git a/client/src/views/Variants.vue b/client/src/views/Variants.vue index 69d4e69c..a2730393 100644 --- a/client/src/views/Variants.vue +++ b/client/src/views/Variants.vue @@ -2,7 +2,7 @@ main .row .nopadding.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 - label(for="prefixFilter") Type first letters... + label(for="prefixFilter") {{ st.tr["Type first letters..."] }} input#prefixFilter(v-model="curPrefix") .variant.col-sm-12.col-md-5.col-lg-4( v-for="(v,idx) in filteredVariants" diff --git a/server/db/populate.sql b/server/db/populate.sql index b770c575..33d5d2e0 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -16,6 +16,6 @@ insert or ignore into Variants (name,description) values ('Magnetic', 'Laws of attraction'), ('Marseille', 'Move twice'), ('Switching', 'Exchange pieces positions'), - ('Upsidedown', 'Head upside down'), + ('Upsidedown', 'Board upside down'), ('Wildebeest', 'Balanced sliders & leapers'), ('Zen', 'Reverse captures');