initial i18n implementation

This commit is contained in:
MDMCK10 2023-06-25 15:58:27 +02:00
parent 1f89ed75c1
commit 746b7fc018
5 changed files with 176 additions and 21 deletions

38
dist/index.html vendored
View File

@ -55,13 +55,13 @@
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a id="homeBtn" href="#" class="nav-link active" aria-current="page"><i class="fa-solid fa-house"></i> Home</a>
<a id="homeBtn" href="#" class="nav-link active" aria-current="page"><i class="fa-solid fa-house"></i><span id="homeText">Home</span></a>
</li>
<li class="nav-item">
<a href="https://computernewb.com/collab-vm/faq/" class="nav-link"><i class="fa-solid fa-circle-question"></i> FAQ</a>
<a href="https://computernewb.com/collab-vm/faq/" class="nav-link"><i class="fa-solid fa-circle-question"></i><span id="faqLink">FAQ</span></a>
</li>
<li class="nav-item">
<a href="https://computernewb.com/collab-vm/rules" class="nav-link"><i class="fa-solid fa-clipboard-check"></i> Rules</a>
<a href="https://computernewb.com/collab-vm/rules" class="nav-link"><i class="fa-solid fa-clipboard-check"></i><span id="rulesLink">Rules</span></a>
</li>
<li class="nav-item">
<a href="https://discord.gg/a4kqb4mGyX" class="nav-link"><i class="fa-brands fa-discord"></i> Discord</a>
@ -72,6 +72,18 @@
<li class="nav-item">
<a href="https://computernewb.com/collab-vm/user-vm" class="nav-link"><i class="fa-solid fa-user"></i> UserVM</a>
</li>
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle" role="button" href="#" data-bs-toggle="dropdown" id="navbarDropdown"><i class="fa-solid fa-globe"></i> Languages</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("sa")'><img src="//computernewb.com/vncresolver/flags/sa.png"> اللغة العربية (جزئية)</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("de")'><img src="//computernewb.com/vncresolver/flags/de.png"> Deutsch</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("en")'><img src="//computernewb.com/vncresolver/flags/gb.png"> English</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("es")'><img src="https://computernewb.com/vncresolver/flags/es.png"> Español</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("jp")'><img src="//computernewb.com/vncresolver/flags/jp.png"> 日本語</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("pl")'><img src="//computernewb.com/vncresolver/flags/pl.png"> Polski</a></li>
<li><a class="dropdown-item" href="#" onclick='window.i18n.change("ru")'><img src="//computernewb.com/vncresolver/flags/ru.png"> Русский</a></li>
</ul>
</li>
</ul>
</div>
</div>
@ -83,20 +95,20 @@
<canvas id="display" height="0" width="0" tabindex="-1"></canvas>
<p id="turnstatus" class="text-light"></p>
<div id="voteResetPanel" class="bg-dark text-light" style="display:none;">
Do you want to reset the vm?<br/>
<button class="btn btn-success" id="voteYesBtn"><i class="fa-solid fa-check"></i> Yes<span class="badge bg-secondary" id="voteYesLabel"></span></button> <button class="btn btn-danger" id="voteNoBtn"><i class="fa-solid fa-ban"></i> No<span class="badge bg-secondary" id="voteNoLabel"></span></button><br/>
<span id="voteResetText">Do you want to reset the vm?</span><br/>
<button class="btn btn-success" id="voteYesBtn"><i class="fa-solid fa-check"></i><span id="voteYesText">Yes</span><span class="badge bg-secondary" id="voteYesLabel"></span></button> <button class="btn btn-danger" id="voteNoBtn"><i class="fa-solid fa-ban"></i><span id="voteNoText">No</span><span class="badge bg-secondary" id="voteNoLabel"></span></button><br/>
Vote ends in <span id="votetime"></span> seconds<br/>
<div id="forceVotePanel">
<button class="btn btn-info" id="forceVoteYesBtn"><i class="fa-solid fa-check"></i> Pass Vote</button>
<button class="btn btn-info" id="forceVoteNoBtn"><i class="fa-solid fa-ban"></i> Cancel Vote</button>
<button class="btn btn-info" id="forceVoteYesBtn"><i class="fa-solid fa-check"></i><span id="passVoteButtonText">Pass Vote</span></button>
<button class="btn btn-info" id="forceVoteNoBtn"><i class="fa-solid fa-ban"></i><span id="cancelVoteButtonText">Cancel Vote</span></button>
</div>
</div>
<div id="btns">
<button class="btn btn-secondary" id="takeTurnBtn"><i class="fa-solid fa-computer-mouse"></i> Take Turn</button>
<button class="btn btn-secondary" id="changeUsernameBtn"><i class="fa-solid fa-signature"></i> Change Username</button>
<button class="btn btn-secondary" id="voteResetButton"><i class="fa-solid fa-rotate-left"></i> Vote for Reset</button>
<button class="btn btn-secondary" id="screenshotButton"><i class="fa-solid fa-camera"></i> Screenshot</button>
<button class="btn btn-secondary" id="ctrlAltDelBtn"><i class="fa-solid fa-gear"></i> Ctrl+Alt+Del</button>
<button class="btn btn-secondary" id="takeTurnBtn"><i class="fa-solid fa-computer-mouse"></i><span id="takeTurnButtonText">Take Turn</span></button>
<button class="btn btn-secondary" id="changeUsernameBtn"><i class="fa-solid fa-signature"></i><span id="changeUsernameButtonText">Change Username</span></button>
<button class="btn btn-secondary" id="voteResetButton"><i class="fa-solid fa-rotate-left"></i><span id="voteResetButtonText">Vote for Reset</span></button>
<button class="btn btn-secondary" id="screenshotButton"><i class="fa-solid fa-camera"></i><span id="screenshotButtonText">Screenshot</span></button>
<button class="btn btn-secondary" id="ctrlAltDelBtn"><i class="fa-solid fa-gear"></i>Ctrl+Alt+Del</button>
<div id="staffbtns">
<button class="btn btn-secondary" id="restoreBtn"><i class="fa-solid fa-rotate-left"></i> Restore</button>
<button class="btn btn-secondary" id="rebootBtn"><i class="fa-solid fa-power-off"></i> Reboot</button>
@ -111,7 +123,7 @@
<div class="table-responsive username-table">
<table class="table table-hover table-dark table-borderless">
<thead>
<th><i class="fa-solid fa-user"></i> Users Online (<span id="onlineusercount"></span>)</th>
<th><i class="fa-solid fa-user"></i><span id="onlineUserText">Users Online</span> (<span id="onlineusercount"></span>)</th>
</thead>
<tbody id="userlist"></tbody>
</table>

22
dist/translations/de.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"Control Collaborative Virtual Machines!": "Steuern Sie kollaborative virtuelle Maschinen!",
"Home": "Hauptseite",
"FAQ": "FAQ",
"Rules": "Regeln",
"Do you want to reset the vm?": "Möchten Sie die VM zurücksetzen?",
"Yes": "Ja",
"No": "Nein",
"Vote ends in # seconds": "Abstimmung endet in # Sekunden",
"Pass Vote": "Abstimmung bestehen",
"Cancel Vote": "Abstimmung abbrechen",
"Take Turn": "In Reihe stellen.",
"Change Username": "Nutzername ändern",
"Vote for Reset": "Für Zurücksetzung abstimmen",
"Screenshot": "Screenshot",
"Users Online": "Nutzer online",
"End Turn": "Aus der Reihe kommen",
"Turn expires in # seconds.": "Ihre Zeit läuft in # Sekunden aus.",
"Waiting for turn in # seconds.": "In der Reihe warten für # Sekunden.",
"Please wait # seconds before starting another vote.": "Bitte warten Sie # Sekunden bevor Sie noch eine Abstimmung starten.",
"Enter new username": "Geben Sie Ihren neuen Nutzername ein."
}

22
dist/translations/en.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"Control Collaborative Virtual Machines!": "Control Collaborative Virtual Machines!",
"Home": "Home",
"FAQ": "FAQ",
"Rules": "Rules",
"Do you want to reset the vm?": "Do you want to reset the vm?",
"Yes": "Yes",
"No": "No",
"Vote ends in # seconds": "Vote ends in # seconds",
"Pass Vote": "Pass Vote",
"Cancel Vote": "Cancel Vote",
"Take Turn": "Take Turn",
"Change Username": "Change Username",
"Vote for Reset": "Vote for Reset",
"Screenshot": "Screenshot",
"Users Online": "Users Online",
"End Turn": "End Turn",
"Turn expires in # seconds.": "Turn expires in # seconds.",
"Waiting for turn in # seconds.": "Waiting for turn in # seconds.",
"Please wait # seconds before starting another vote.": "Please wait # seconds before starting another vote.",
"Enter new username": "Enter new username"
}

91
src/i18n.js Normal file
View File

@ -0,0 +1,91 @@
export default class i18n {
lang;
data;
error;
constructor(lang) {
this.lang = lang;
}
async init() {
return new Promise(async (resolve, reject) => {
this.load(this.lang).then(res => {
this.error = false;
this.data = res;
return resolve();
}).catch(() => {
this.error = true;
alert(`i18n error: Failed to load language file for ${lang}. Alert a site administrator!`);
return reject();
});
});
}
load(lang) {
return new Promise(async (res, rej) => {
await fetch(`translations/${lang}.json`).then(response => {
if (!response.ok) { return rej(); }
return res(response.json());
});
});
}
get(key) {
// If we failed to load the translations earlier, return the original input.
if (this.error) {
return key;
}
const value = this.data[key];
// If the translation does not exist in the currently loaded language, return the original input.
if (!value) {
return key;
}
return value;
}
change(lang) {
if (this.lang == lang) return;
this.load(lang).then(res => {
this.lang = lang;
this.data = res;
this.replaceAllInDOM();
}).catch((e) => {
console.log(e);
return alert(`i18n error: Failed to load language file for ${lang}. Alert a site administrator!`);
});
}
replaceAllInDOM() {
document.title = this.get("Control Collaborative Virtual Machines!");
var elements = [
{ id: "homeText", key: "Home" },
{ id: "faqLink", key: "FAQ" },
{ id: "rulesLink", key: "Rules" },
{ id: "onlineUserText", key: "Users Online" },
{ id: "voteResetText", key: "Do you want to reset the vm?" },
{ id: "voteYesText", key: "Yes" },
{ id: "voteNoText", key: "No" },
{ id: "passVoteButtonText", key: "Pass Vote" },
{ id: "cancelVoteButtonText", key: "Cancel Vote" },
{ id: "takeTurnButtonText", key: "Take Turn" },
{ id: "changeUsernameButtonText", key: "Change Username" },
{ id: "voteResetButtonText", key: "Vote for Reset" },
{ id: "screenshotButtonText", key: "Screenshot" }
];
elements.forEach(el => {
var element = document.getElementById(el.id);
if (element != null) {
element.innerText = ` ${this.get(el.key)}`;
} else {
console.warn(`${el.id} was null (would have assigned ${this.get(el.key)})`)
}
});
}
}

View File

@ -4,6 +4,14 @@ import { GetKeysym } from "./keyboard";
import { createNanoEvents } from "nanoevents";
import { makeperms } from "./permissions";
import doCaptcha from "./captcha";
import i18n from "./i18n";
// i18n
window.i18n = new i18n(navigator.language.split("-")[0]);
window.i18n.init().then(() => {
window.i18n.replaceAllInDOM();
});
// None = -1
// Has turn = 0
// In queue = <queue position>
@ -275,7 +283,7 @@ class CollabVMClient {
curr.turn = -1;
curr.element.classList = "";
});
buttons.takeTurn.innerHTML = "<i class=\"fa-solid fa-computer-mouse\"></i> Take Turn";
buttons.takeTurn.innerHTML = `<i class=\"fa-solid fa-computer-mouse\"></i><span id="takeTurnButtonText"> ${window.i18n.get("Take Turn")}</span>`;
turn = -1;
if (!msgArr.includes(username))
turnstatus.innerText = "";
@ -296,7 +304,7 @@ class CollabVMClient {
secs--;
if (secs === 0)
clearInterval(turninterval);
turnstatus.innerText = `Turn expires in ${secs} seconds.`;
turnstatus.innerText = `${window.i18n.get("Turn expires in # seconds.").replace("#", secs)}`;
}
turnUpdate();
turninterval = setInterval(turnUpdate, 1000);
@ -312,7 +320,7 @@ class CollabVMClient {
secs--;
if (secs === 0)
clearInterval(turninterval);
turnstatus.innerText = `Waiting for turn in ${secs} seconds.`;
turnstatus.innerText = `${window.i18n.get("Waiting for turn in # seconds.").replace("#", secs)}`;
}
turninterval = setInterval(turnUpdate, 1000);
turnUpdate();
@ -324,9 +332,9 @@ class CollabVMClient {
}
}
if (turn === -1) {
buttons.takeTurn.innerHTML = "<i class=\"fa-solid fa-computer-mouse\"></i> Take Turn";
buttons.takeTurn.innerHTML = `<i class=\"fa-solid fa-computer-mouse\"></i><span id="takeTurnButtonText"> ${window.i18n.get("Take Turn")}</span>`;
} else {
buttons.takeTurn.innerHTML = "<i class=\"fa-solid fa-computer-mouse\"></i> End Turn";
buttons.takeTurn.innerHTML = `<i class=\"fa-solid fa-computer-mouse\"></i><span id="takeTurnButtonText"> ${window.i18n.get("End Turn")}</span>`;
}
this.reloadUsers();
break;
@ -356,8 +364,8 @@ class CollabVMClient {
voteresetpanel.style.display = "none";
break;
case "3":
// too soon dumbass
window.alert(`Please wait ${msgArr[2]} seconds before starting another vote.`);
// Vote is on cooldown
window.alert(`${window.i18n.get("Please wait # seconds before starting another vote.").replace("#", msgArr[2])}`);
break;
}
break;
@ -820,7 +828,7 @@ function sendChat() {
chatinput.value = "";
}
buttons.changeUsername.addEventListener('click', () => {
var newuser = window.prompt("Enter new username", window.username);
var newuser = window.prompt(window.i18n.get("Enter new username"), window.username);
if (newuser == null) return;
vm.rename(newuser);
});