From 38ae0c7796a58596f376d5c011563d7f43de62d4 Mon Sep 17 00:00:00 2001 From: MaciejkaG Date: Sat, 6 Apr 2024 01:48:49 +0200 Subject: [PATCH] Major changes - Multiple translation improvements - Added language switch in settings - Minor fixes and improvements - Still need to fix error messages (they are hardcoded in polish) --- index.js | 43 ++++++++++++++++++++++++++++++++++++++ lang/en.json | 3 +++ lang/pl.json | 8 ++++--- nodemon.json | 3 ++- public/assets/css/main.css | 18 ++++++++++++++-- public/assets/js/socket.js | 33 ++++++++++++++++++++++++++++- utils/auth.js | 28 ++++++++++++------------- utils/localisation.js | 7 +++++++ views/index.handlebars | 10 +++++++-- 9 files changed, 130 insertions(+), 23 deletions(-) diff --git a/index.js b/index.js index 2e79496..90b041b 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ import { Lang } from './utils/localisation.js'; import { rateLimit } from 'express-rate-limit'; import { RedisStore as LimiterRedisStore } from 'rate-limit-redis'; import SessionRedisStore from 'connect-redis'; +import mysql from 'mysql'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -24,6 +25,8 @@ const app = express(); const flags = process.env.flags ? process.env.flags.split(",") : null; +const langs = [{ id: "en", name: "English" }, { id: "pl", name: "Polish" }]; + app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -93,6 +96,9 @@ app.get('/', async (req, res) => { } else if (req.session.nickname == null) { auth.getLanguage(req.session.userId).then(language => { var locale; + + req.session.autoLang = language == null ? true : false; + if (language) { locale = new Lang([language]); req.session.langs = [language]; @@ -351,10 +357,47 @@ io.on('connection', async (socket) => { socket.on('my profile', (callback) => { auth.getProfile(session.userId).then((profile) => { + profile.uid = session.userId; callback(profile); }); }); + socket.on('locale options', (callback) => { + const locale = new Lang(session.langs); + + let userLanguage = langs.find((element) => element.id == locale.lang); + let userLangs = langs.filter((element) => element.id != locale.lang); + + if (session.autoLang) { + userLangs.unshift(userLanguage); + userLangs.unshift({ id: "null", name: "Auto" }); + } else { + userLangs.unshift({ id: "null", name: "Auto" }); + userLangs.unshift(userLanguage); + } + + callback(userLangs); + }); + + socket.on('change locale', (locale, callback) => { + if (locale === "null" || langs.find((element) => element.id == locale)) { + locale = locale === "null" ? null : locale; + const conn = mysql.createConnection({ host: process.env.db_host, user: process.env.db_user, password: process.env.db_pass, database: 'statki' }); + conn.query(`UPDATE accounts SET language = ${conn.escape(locale)} WHERE user_id = ${conn.escape(session.userId)}`, (err) => { + if (err) { callback({ status: 'dbErr' }); return; } + else callback({ status: 'ok' }); + + req.session.reload((err) => { + if (err) return socket.disconnect(); + + req.session.autoLang = locale ? false : true; + req.session.save(); + }); + }); + conn.end(); + } + }); + socket.on('create lobby', (callback) => { if (socket.rooms.size === 1) { let id = genID(); diff --git a/lang/en.json b/lang/en.json index 3201458..b7f7a2f 100644 --- a/lang/en.json +++ b/lang/en.json @@ -57,6 +57,9 @@ "winrate": "winrate", "No matches played": "No matches played" }, + "Settings": { + "General": "General" + }, "General": { "Unknown error occured": "Unknown error occured", "Status:": "Status:" diff --git a/lang/pl.json b/lang/pl.json index b327e8c..4d46cb3 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -43,7 +43,7 @@ "PvP/Loading": { "PvP / Loading": "PvP / Wczytywanie", "Wait": "Czekaj...", - "You will be redirected soon": "Wkrótce zostaniesz przekierowany(-a)", + "You will be redirected soon": "Wkrótce nastąpi przekierowanie", "Opponent:": "Przeciwnik" }, "Profile": { @@ -56,9 +56,11 @@ "total matches played": "meczy zagranych łącznie", "winrate": "winrate", - "No matches played": "Nie zagrano meczy" + "No matches played": "Nie zagrano żadnych meczy" + }, + "Settings": { + "General": "Ogólne" }, - "General": { "Unknown error occured": "Wystąpił nieznany błąd", "Status:": "Status:" diff --git a/nodemon.json b/nodemon.json index fa31724..82b69fc 100644 --- a/nodemon.json +++ b/nodemon.json @@ -2,6 +2,7 @@ "ignore": [ "public/*", "views/*", - "utils/mail/*" + "utils/mail/*", + "lang/*" ] } \ No newline at end of file diff --git a/public/assets/css/main.css b/public/assets/css/main.css index 5e7b385..127a3b1 100644 --- a/public/assets/css/main.css +++ b/public/assets/css/main.css @@ -246,8 +246,6 @@ nav span:hover { flex-direction: column; gap: 2rem; flex: 2; - - overflow-y: scroll; } #profileView .matchList::-webkit-scrollbar { @@ -323,4 +321,20 @@ nav span:hover { .tippyTemplate { display: none; +} + +#settingsView label { + font-size: 1.2rem; +} + +#settingsView select { + padding: 0.5rem 1rem; + padding: 0.5rem 2rem; + font-size: 1rem; + background-color: black; + border: solid 1px white; + color: white; + border-radius: 15px; + outline: none; + margin-left: 2rem; } \ No newline at end of file diff --git a/public/assets/js/socket.js b/public/assets/js/socket.js index 6603ce7..e5c0f13 100644 --- a/public/assets/js/socket.js +++ b/public/assets/js/socket.js @@ -29,7 +29,38 @@ socket.on("gameReady", (gameId) => { var nickname; +socket.emit('locale options', (langs) => { + console.log("Fetching available locale options"); + let menu = ""; + langs.forEach(lang => { + menu += ``; + }); + + $("#languages").html(menu); + console.log("Locale options fetched"); +}); + +$("#languages").on("change", function() { + lockUI(true); + console.log("Switching language to", $(this).val()); + socket.emit("change locale", $(this).val(), (response) => { + switch (response.status) { + case "ok": + console.log("Switched languages, refreshing"); + window.location.reload(); + break; + + default: + alert(`${window.locale["Unknown error occured"]}\n${window.locale["Status:"]} ${response.status}`); + lockUI(false); + break; + } + }); +}); + socket.emit("my profile", (profile) => { + console.log("Received user data. UID:", profile.uid); + // General profile data let options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; $("#playerSince").html(new Date(profile.profile.account_creation).toLocaleDateString(undefined, options)); @@ -59,7 +90,7 @@ socket.emit("my profile", (profile) => { matchHistoryDOM += `

${match.won === 1 ? window.locale["Victory"] : window.locale["Defeat"]}

vs. ${match.match_type === "pvp" ? match.opponent : "AI"}

${window.locale["Click to view match statistics"]}

${date}
${duration}
`; } - if (matchHistoryDOM === "") { + if (!matchHistoryDOM) { matchHistoryDOM = `

${window.locale["No matches played"]}

`; } diff --git a/utils/auth.js b/utils/auth.js index 7d94af0..a71534d 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -84,9 +84,9 @@ export class MailAuth { const row = response[0]; resolve({ status: 1, uid: row.user_id }); - - conn.end(); }); + + conn.end(); }); } @@ -101,9 +101,9 @@ export class MailAuth { } else { resolve(null); } - - conn.end(); }); + + conn.end(); }); } @@ -191,9 +191,9 @@ export class MailAuth { resolve({ status: 1, uid: row.user_id }); - - conn.end(); }); + + conn.end(); }); } @@ -205,10 +205,10 @@ export class MailAuth { else conn.query(`INSERT INTO statistics(match_id, user_id, board, won) VALUES (${conn.escape(matchId)}, ${conn.escape(hostId)}, ${conn.escape(JSON.stringify(boards[0]))}, ${conn.escape(!winnerIdx ? 1 : 0)}), (${conn.escape(matchId)}, ${conn.escape(guestId)}, ${conn.escape(JSON.stringify(boards[1]))}, ${conn.escape(winnerIdx ? 1 : 0)})`, async (error, response) => { if (error) reject(error); else resolve(); - - conn.end(); }); }); + + conn.end(); }); } @@ -227,9 +227,9 @@ export class MailAuth { resolve({ profile, stats, matchHistory }); } - - conn.end(); }); + + conn.end(); }); } @@ -251,9 +251,9 @@ export class MailAuth { conn.query(`UPDATE accounts SET nickname = ${conn.escape(nickname)} WHERE user_id = ${conn.escape(uid)}`, (error) => { if (error) reject(error); resolve(); - - conn.end(); }); + + conn.end(); }); } @@ -263,9 +263,9 @@ export class MailAuth { conn.query(`SELECT nickname FROM accounts WHERE user_id = ${conn.escape(uid)}`, (error, response) => { if (error) reject(error); resolve(response[0].nickname); - - conn.end(); }); + + conn.end(); }); } } diff --git a/utils/localisation.js b/utils/localisation.js index bb866ae..3371bb1 100644 --- a/utils/localisation.js +++ b/utils/localisation.js @@ -8,18 +8,23 @@ const __dirname = path.dirname(__filename); export class Lang { constructor(langs) { const languagesPath = path.join(__dirname, '../lang'); + this.allText = null; for (let i = 0; i < langs.length; i++) { const lang = langs[i]; if (fs.readdirSync(languagesPath).includes(`${lang}.json`)) { try { this.allText = JSON.parse(fs.readFileSync(path.join(languagesPath, `${lang}.json`), 'utf8')); + this.lang = lang; return; } catch (e) { console.log(e); } } } + + this.allText = JSON.parse(fs.readFileSync(path.join(languagesPath, 'en.json'), 'utf8')); + this.lang = 'en'; } t(key) { @@ -37,5 +42,7 @@ export class Lang { } } } + + } diff --git a/views/index.handlebars b/views/index.handlebars index 3cdcd71..f275418 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -93,9 +93,14 @@ -
+
- +

{{ t 'menu.Settings.Settings' }}

+

{{ t 'menu.Settings.General' }}

+ +
@@ -106,6 +111,7 @@ "Victory": "{{ t 'menu.Profile.Victory' }}", "Defeat": "{{ t 'menu.Profile.Defeat' }}", "Click to view match statistics": "{{ t 'menu.Profile.Click to view match statistics' }}", + "No matches played": "{{ t 'menu.Profile.No matches played' }}", "Reconnecting": "{{ t 'errors.Reconnecting' }}", "Reconnected": "{{ t 'errors.Reconnected' }}",