diff --git a/client/public/vnc/error-handler.js b/client/public/vnc/error-handler.js
new file mode 100644
index 0000000..ef1cb64
--- /dev/null
+++ b/client/public/vnc/error-handler.js
@@ -0,0 +1,79 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2019 The noVNC authors
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+// Fallback for all uncaught errors
+function handleError(event, err) {
+ try {
+ const msg = document.getElementById('noVNC_fallback_errormsg');
+
+ // Work around Firefox bug:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1685038
+ if (event.message === "ResizeObserver loop completed with undelivered notifications.") {
+ return false;
+ }
+
+ // Only show the initial error
+ if (msg.hasChildNodes()) {
+ return false;
+ }
+
+ let div = document.createElement("div");
+ div.classList.add('noVNC_message');
+ div.appendChild(document.createTextNode(event.message));
+ msg.appendChild(div);
+
+ if (event.filename) {
+ div = document.createElement("div");
+ div.className = 'noVNC_location';
+ let text = event.filename;
+ if (event.lineno !== undefined) {
+ text += ":" + event.lineno;
+ if (event.colno !== undefined) {
+ text += ":" + event.colno;
+ }
+ }
+ div.appendChild(document.createTextNode(text));
+ msg.appendChild(div);
+ }
+
+ if (err && err.stack) {
+ div = document.createElement("div");
+ div.className = 'noVNC_stack';
+ div.appendChild(document.createTextNode(err.stack));
+ msg.appendChild(div);
+ }
+
+ document.getElementById('noVNC_fallback_error')
+ .classList.add("noVNC_open");
+
+ } catch (exc) {
+ document.write("noVNC encountered an error.");
+ }
+
+ // Try to disable keyboard interaction, best effort
+ try {
+ // Remove focus from the currently focused element in order to
+ // prevent keyboard interaction from continuing
+ if (document.activeElement) { document.activeElement.blur(); }
+
+ // Don't let any element be focusable when showing the error
+ let keyboardFocusable = 'a[href], button, input, textarea, select, details, [tabindex]';
+ document.querySelectorAll(keyboardFocusable).forEach((elem) => {
+ elem.setAttribute("tabindex", "-1");
+ });
+ } catch (exc) {
+ // Do nothing
+ }
+
+ // Don't return true since this would prevent the error
+ // from being printed to the browser console.
+ return false;
+}
+
+window.addEventListener('error', evt => handleError(evt, evt.error));
+window.addEventListener('unhandledrejection', evt => handleError(evt.reason, evt.reason));
diff --git a/client/public/vnc/images/alt.svg b/client/public/vnc/images/alt.svg
new file mode 100644
index 0000000..e5bb461
--- /dev/null
+++ b/client/public/vnc/images/alt.svg
@@ -0,0 +1,92 @@
+
+
+
+
diff --git a/client/public/vnc/images/clipboard.svg b/client/public/vnc/images/clipboard.svg
new file mode 100644
index 0000000..79af275
--- /dev/null
+++ b/client/public/vnc/images/clipboard.svg
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/client/public/vnc/images/connect.svg b/client/public/vnc/images/connect.svg
new file mode 100644
index 0000000..56cde41
--- /dev/null
+++ b/client/public/vnc/images/connect.svg
@@ -0,0 +1,96 @@
+
+
+
+
diff --git a/client/public/vnc/images/ctrl.svg b/client/public/vnc/images/ctrl.svg
new file mode 100644
index 0000000..856e939
--- /dev/null
+++ b/client/public/vnc/images/ctrl.svg
@@ -0,0 +1,96 @@
+
+
+
+
diff --git a/client/public/vnc/images/ctrlaltdel.svg b/client/public/vnc/images/ctrlaltdel.svg
new file mode 100644
index 0000000..d7744ea
--- /dev/null
+++ b/client/public/vnc/images/ctrlaltdel.svg
@@ -0,0 +1,100 @@
+
+
+
+
diff --git a/client/public/vnc/images/disconnect.svg b/client/public/vnc/images/disconnect.svg
new file mode 100644
index 0000000..6be7d18
--- /dev/null
+++ b/client/public/vnc/images/disconnect.svg
@@ -0,0 +1,94 @@
+
+
+
+
diff --git a/client/public/vnc/images/drag.svg b/client/public/vnc/images/drag.svg
new file mode 100644
index 0000000..139caf9
--- /dev/null
+++ b/client/public/vnc/images/drag.svg
@@ -0,0 +1,76 @@
+
+
+
+
diff --git a/client/public/vnc/images/error.svg b/client/public/vnc/images/error.svg
new file mode 100644
index 0000000..8356d3f
--- /dev/null
+++ b/client/public/vnc/images/error.svg
@@ -0,0 +1,81 @@
+
+
+
+
diff --git a/client/public/vnc/images/esc.svg b/client/public/vnc/images/esc.svg
new file mode 100644
index 0000000..830152b
--- /dev/null
+++ b/client/public/vnc/images/esc.svg
@@ -0,0 +1,92 @@
+
+
+
+
diff --git a/client/public/vnc/images/expander.svg b/client/public/vnc/images/expander.svg
new file mode 100644
index 0000000..e163535
--- /dev/null
+++ b/client/public/vnc/images/expander.svg
@@ -0,0 +1,69 @@
+
+
+
+
diff --git a/client/public/vnc/images/fullscreen.svg b/client/public/vnc/images/fullscreen.svg
new file mode 100644
index 0000000..29bd05d
--- /dev/null
+++ b/client/public/vnc/images/fullscreen.svg
@@ -0,0 +1,93 @@
+
+
+
+
diff --git a/client/public/vnc/images/handle.svg b/client/public/vnc/images/handle.svg
new file mode 100644
index 0000000..4a7a126
--- /dev/null
+++ b/client/public/vnc/images/handle.svg
@@ -0,0 +1,82 @@
+
+
+
+
diff --git a/client/public/vnc/images/handle_bg.svg b/client/public/vnc/images/handle_bg.svg
new file mode 100644
index 0000000..7579c42
--- /dev/null
+++ b/client/public/vnc/images/handle_bg.svg
@@ -0,0 +1,172 @@
+
+
+
+
diff --git a/client/public/vnc/images/icons/Makefile b/client/public/vnc/images/icons/Makefile
new file mode 100644
index 0000000..03eaed0
--- /dev/null
+++ b/client/public/vnc/images/icons/Makefile
@@ -0,0 +1,42 @@
+BROWSER_SIZES := 16 24 32 48 64
+#ANDROID_SIZES := 72 96 144 192
+# FIXME: The ICO is limited to 8 icons due to a Chrome bug:
+# https://bugs.chromium.org/p/chromium/issues/detail?id=1381393
+ANDROID_SIZES := 96 144 192
+WEB_ICON_SIZES := $(BROWSER_SIZES) $(ANDROID_SIZES)
+
+#IOS_1X_SIZES := 20 29 40 76 # No such devices exist anymore
+IOS_2X_SIZES := 40 58 80 120 152 167
+IOS_3X_SIZES := 60 87 120 180
+ALL_IOS_SIZES := $(IOS_1X_SIZES) $(IOS_2X_SIZES) $(IOS_3X_SIZES)
+
+ALL_ICONS := \
+ $(ALL_IOS_SIZES:%=novnc-ios-%.png) \
+ novnc.ico
+
+all: $(ALL_ICONS)
+
+# Our testing shows that the ICO file need to be sorted in largest to
+# smallest to get the apporpriate behviour
+WEB_ICON_SIZES_REVERSE := $(shell echo $(WEB_ICON_SIZES) | tr ' ' '\n' | sort -nr | tr '\n' ' ')
+WEB_BASE_ICONS := $(WEB_ICON_SIZES_REVERSE:%=novnc-%.png)
+.INTERMEDIATE: $(WEB_BASE_ICONS)
+
+novnc.ico: $(WEB_BASE_ICONS)
+ convert $(WEB_BASE_ICONS) "$@"
+
+# General conversion
+novnc-%.png: novnc-icon.svg
+ convert -depth 8 -background transparent \
+ -size $*x$* "$(lastword $^)" "$@"
+
+# iOS icons use their own SVG
+novnc-ios-%.png: novnc-ios-icon.svg
+ convert -depth 8 -background transparent \
+ -size $*x$* "$(lastword $^)" "$@"
+
+# The smallest sizes are generated using a different SVG
+novnc-16.png novnc-24.png novnc-32.png: novnc-icon-sm.svg
+
+clean:
+ rm -f *.png
diff --git a/client/public/vnc/images/icons/novnc-icon-35x21.svg b/client/public/vnc/images/icons/novnc-icon-35x21.svg
new file mode 100644
index 0000000..774c334
--- /dev/null
+++ b/client/public/vnc/images/icons/novnc-icon-35x21.svg
@@ -0,0 +1,98 @@
+
+
+
+
diff --git a/client/public/vnc/images/icons/novnc-icon-sm.svg b/client/public/vnc/images/icons/novnc-icon-sm.svg
new file mode 100644
index 0000000..aa1c6f1
--- /dev/null
+++ b/client/public/vnc/images/icons/novnc-icon-sm.svg
@@ -0,0 +1,163 @@
+
+
+
+
diff --git a/client/public/vnc/images/icons/novnc-icon.svg b/client/public/vnc/images/icons/novnc-icon.svg
new file mode 100644
index 0000000..1efff91
--- /dev/null
+++ b/client/public/vnc/images/icons/novnc-icon.svg
@@ -0,0 +1,163 @@
+
+
+
+
diff --git a/client/public/vnc/images/icons/novnc-ios-120.png b/client/public/vnc/images/icons/novnc-ios-120.png
new file mode 100644
index 0000000..8da7bab
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-120.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-152.png b/client/public/vnc/images/icons/novnc-ios-152.png
new file mode 100644
index 0000000..60b2bce
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-152.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-167.png b/client/public/vnc/images/icons/novnc-ios-167.png
new file mode 100644
index 0000000..98fade2
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-167.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-180.png b/client/public/vnc/images/icons/novnc-ios-180.png
new file mode 100644
index 0000000..5d24df7
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-180.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-40.png b/client/public/vnc/images/icons/novnc-ios-40.png
new file mode 100644
index 0000000..cf14894
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-40.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-58.png b/client/public/vnc/images/icons/novnc-ios-58.png
new file mode 100644
index 0000000..f6dfbeb
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-58.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-60.png b/client/public/vnc/images/icons/novnc-ios-60.png
new file mode 100644
index 0000000..8cda295
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-60.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-80.png b/client/public/vnc/images/icons/novnc-ios-80.png
new file mode 100644
index 0000000..6c417c4
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-80.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-87.png b/client/public/vnc/images/icons/novnc-ios-87.png
new file mode 100644
index 0000000..4377d87
Binary files /dev/null and b/client/public/vnc/images/icons/novnc-ios-87.png differ
diff --git a/client/public/vnc/images/icons/novnc-ios-icon.svg b/client/public/vnc/images/icons/novnc-ios-icon.svg
new file mode 100644
index 0000000..009452a
--- /dev/null
+++ b/client/public/vnc/images/icons/novnc-ios-icon.svg
@@ -0,0 +1,183 @@
+
+
+
+
diff --git a/client/public/vnc/images/icons/novnc.ico b/client/public/vnc/images/icons/novnc.ico
new file mode 100644
index 0000000..c3bc58e
Binary files /dev/null and b/client/public/vnc/images/icons/novnc.ico differ
diff --git a/client/public/vnc/images/info.svg b/client/public/vnc/images/info.svg
new file mode 100644
index 0000000..557b772
--- /dev/null
+++ b/client/public/vnc/images/info.svg
@@ -0,0 +1,81 @@
+
+
+
+
diff --git a/client/public/vnc/images/keyboard.svg b/client/public/vnc/images/keyboard.svg
new file mode 100644
index 0000000..137b350
--- /dev/null
+++ b/client/public/vnc/images/keyboard.svg
@@ -0,0 +1,88 @@
+
+
+
+
diff --git a/client/public/vnc/images/power.svg b/client/public/vnc/images/power.svg
new file mode 100644
index 0000000..4925d3e
--- /dev/null
+++ b/client/public/vnc/images/power.svg
@@ -0,0 +1,87 @@
+
+
+
+
diff --git a/client/public/vnc/images/settings.svg b/client/public/vnc/images/settings.svg
new file mode 100644
index 0000000..dbb2e80
--- /dev/null
+++ b/client/public/vnc/images/settings.svg
@@ -0,0 +1,76 @@
+
+
+
+
diff --git a/client/public/vnc/images/tab.svg b/client/public/vnc/images/tab.svg
new file mode 100644
index 0000000..1ccb322
--- /dev/null
+++ b/client/public/vnc/images/tab.svg
@@ -0,0 +1,86 @@
+
+
+
+
diff --git a/client/public/vnc/images/toggleextrakeys.svg b/client/public/vnc/images/toggleextrakeys.svg
new file mode 100644
index 0000000..b578c0d
--- /dev/null
+++ b/client/public/vnc/images/toggleextrakeys.svg
@@ -0,0 +1,90 @@
+
+
+
+
diff --git a/client/public/vnc/images/warning.svg b/client/public/vnc/images/warning.svg
new file mode 100644
index 0000000..7114f9b
--- /dev/null
+++ b/client/public/vnc/images/warning.svg
@@ -0,0 +1,81 @@
+
+
+
+
diff --git a/client/public/vnc/images/windows.svg b/client/public/vnc/images/windows.svg
new file mode 100644
index 0000000..ad5eec3
--- /dev/null
+++ b/client/public/vnc/images/windows.svg
@@ -0,0 +1,65 @@
+
+
+
+
\ No newline at end of file
diff --git a/client/public/vnc/locale/README b/client/public/vnc/locale/README
new file mode 100644
index 0000000..ca4f548
--- /dev/null
+++ b/client/public/vnc/locale/README
@@ -0,0 +1 @@
+DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES.
diff --git a/client/public/vnc/locale/cs.json b/client/public/vnc/locale/cs.json
new file mode 100644
index 0000000..dd31e6c
--- /dev/null
+++ b/client/public/vnc/locale/cs.json
@@ -0,0 +1,71 @@
+{
+ "Connecting...": "Připojení...",
+ "Disconnecting...": "Odpojení...",
+ "Reconnecting...": "Obnova připojení...",
+ "Internal error": "Vnitřní chyba",
+ "Must set host": "Hostitel musí být nastavení",
+ "Connected (encrypted) to ": "Připojení (šifrované) k ",
+ "Connected (unencrypted) to ": "Připojení (nešifrované) k ",
+ "Something went wrong, connection is closed": "Něco se pokazilo, odpojeno",
+ "Failed to connect to server": "Chyba připojení k serveru",
+ "Disconnected": "Odpojeno",
+ "New connection has been rejected with reason: ": "Nové připojení bylo odmítnuto s odůvodněním: ",
+ "New connection has been rejected": "Nové připojení bylo odmítnuto",
+ "Password is required": "Je vyžadováno heslo",
+ "noVNC encountered an error:": "noVNC narazilo na chybu:",
+ "Hide/Show the control bar": "Skrýt/zobrazit ovládací panel",
+ "Move/Drag viewport": "Přesunout/přetáhnout výřez",
+ "viewport drag": "přesun výřezu",
+ "Active Mouse Button": "Aktivní tlačítka myši",
+ "No mousebutton": "Žádné",
+ "Left mousebutton": "Levé tlačítko myši",
+ "Middle mousebutton": "Prostřední tlačítko myši",
+ "Right mousebutton": "Pravé tlačítko myši",
+ "Keyboard": "Klávesnice",
+ "Show keyboard": "Zobrazit klávesnici",
+ "Extra keys": "Extra klávesy",
+ "Show extra keys": "Zobrazit extra klávesy",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Přepnout Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Přepnout Alt",
+ "Send Tab": "Odeslat tabulátor",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Odeslat Esc",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Poslat Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Vypnutí/Restart",
+ "Shutdown/Reboot...": "Vypnutí/Restart...",
+ "Power": "Napájení",
+ "Shutdown": "Vypnout",
+ "Reboot": "Restart",
+ "Reset": "Reset",
+ "Clipboard": "Schránka",
+ "Clear": "Vymazat",
+ "Fullscreen": "Celá obrazovka",
+ "Settings": "Nastavení",
+ "Shared mode": "Sdílený režim",
+ "View only": "Pouze prohlížení",
+ "Clip to window": "Přizpůsobit oknu",
+ "Scaling mode:": "Přizpůsobení velikosti",
+ "None": "Žádné",
+ "Local scaling": "Místní",
+ "Remote resizing": "Vzdálené",
+ "Advanced": "Pokročilé",
+ "Repeater ID:": "ID opakovače",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Šifrování:",
+ "Host:": "Hostitel:",
+ "Port:": "Port:",
+ "Path:": "Cesta",
+ "Automatic reconnect": "Automatická obnova připojení",
+ "Reconnect delay (ms):": "Zpoždění připojení (ms)",
+ "Show dot when no cursor": "Tečka místo chybějícího kurzoru myši",
+ "Logging:": "Logování:",
+ "Disconnect": "Odpojit",
+ "Connect": "Připojit",
+ "Password:": "Heslo",
+ "Send Password": "Odeslat heslo",
+ "Cancel": "Zrušit"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/de.json b/client/public/vnc/locale/de.json
new file mode 100644
index 0000000..fa15463
--- /dev/null
+++ b/client/public/vnc/locale/de.json
@@ -0,0 +1,74 @@
+{
+ "Connecting...": "Verbinden...",
+ "Disconnecting...": "Verbindung trennen...",
+ "Reconnecting...": "Verbindung wiederherstellen...",
+ "Internal error": "Interner Fehler",
+ "Must set host": "Richten Sie den Server ein",
+ "Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ",
+ "Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ",
+ "Something went wrong, connection is closed": "Etwas lief schief, Verbindung wurde getrennt",
+ "Disconnected": "Verbindung zum Server getrennt",
+ "New connection has been rejected with reason: ": "Verbindung wurde aus folgendem Grund abgelehnt: ",
+ "New connection has been rejected": "Verbindung wurde abgelehnt",
+ "Password is required": "Passwort ist erforderlich",
+ "noVNC encountered an error:": "Ein Fehler ist aufgetreten:",
+ "Hide/Show the control bar": "Kontrollleiste verstecken/anzeigen",
+ "Move/Drag viewport": "Ansichtsfenster verschieben/ziehen",
+ "viewport drag": "Ansichtsfenster ziehen",
+ "Active Mouse Button": "Aktive Maustaste",
+ "No mousebutton": "Keine Maustaste",
+ "Left mousebutton": "Linke Maustaste",
+ "Middle mousebutton": "Mittlere Maustaste",
+ "Right mousebutton": "Rechte Maustaste",
+ "Keyboard": "Tastatur",
+ "Show keyboard": "Tastatur anzeigen",
+ "Extra keys": "Zusatztasten",
+ "Show extra keys": "Zusatztasten anzeigen",
+ "Ctrl": "Strg",
+ "Toggle Ctrl": "Strg umschalten",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt umschalten",
+ "Send Tab": "Tab senden",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Escape senden",
+ "Ctrl+Alt+Del": "Strg+Alt+Entf",
+ "Send Ctrl-Alt-Del": "Strg+Alt+Entf senden",
+ "Shutdown/Reboot": "Herunterfahren/Neustarten",
+ "Shutdown/Reboot...": "Herunterfahren/Neustarten...",
+ "Power": "Energie",
+ "Shutdown": "Herunterfahren",
+ "Reboot": "Neustarten",
+ "Reset": "Zurücksetzen",
+ "Clipboard": "Zwischenablage",
+ "Clear": "Löschen",
+ "Fullscreen": "Vollbild",
+ "Settings": "Einstellungen",
+ "Shared mode": "Geteilter Modus",
+ "View only": "Nur betrachten",
+ "Clip to window": "Auf Fenster begrenzen",
+ "Scaling mode:": "Skalierungsmodus:",
+ "None": "Keiner",
+ "Local scaling": "Lokales skalieren",
+ "Remote resizing": "Serverseitiges skalieren",
+ "Advanced": "Erweitert",
+ "Repeater ID:": "Repeater ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Verschlüsselt",
+ "Host:": "Server:",
+ "Port:": "Port:",
+ "Path:": "Pfad:",
+ "Automatic reconnect": "Automatisch wiederverbinden",
+ "Reconnect delay (ms):": "Wiederverbindungsverzögerung (ms):",
+ "Logging:": "Protokollierung:",
+ "Disconnect": "Verbindung trennen",
+ "Connect": "Verbinden",
+ "Password:": "Passwort:",
+ "Cancel": "Abbrechen",
+ "Canvas not supported.": "Canvas nicht unterstützt.",
+ "Disconnect timeout": "Zeitüberschreitung beim Trennen",
+ "Local Downscaling": "Lokales herunterskalieren",
+ "Local Cursor": "Lokaler Mauszeiger",
+ "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "'Clipping-Modus' aktiviert, Scrollbalken in 'IE-Vollbildmodus' werden nicht unterstützt",
+ "True Color": "True Color"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/el.json b/client/public/vnc/locale/el.json
new file mode 100644
index 0000000..57d6731
--- /dev/null
+++ b/client/public/vnc/locale/el.json
@@ -0,0 +1,100 @@
+{
+ "HTTPS is required for full functionality": "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα",
+ "Connecting...": "Συνδέεται...",
+ "Disconnecting...": "Aποσυνδέεται...",
+ "Reconnecting...": "Επανασυνδέεται...",
+ "Internal error": "Εσωτερικό σφάλμα",
+ "Must set host": "Πρέπει να οριστεί ο διακομιστής",
+ "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ",
+ "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ",
+ "Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε",
+ "Failed to connect to server": "Αποτυχία στη σύνδεση με το διακομιστή",
+ "Disconnected": "Αποσυνδέθηκε",
+ "New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ",
+ "New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ",
+ "Credentials are required": "Απαιτούνται διαπιστευτήρια",
+ "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:",
+ "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου",
+ "Drag": "Σύρσιμο",
+ "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου",
+ "Keyboard": "Πληκτρολόγιο",
+ "Show Keyboard": "Εμφάνιση Πληκτρολογίου",
+ "Extra keys": "Επιπλέον πλήκτρα",
+ "Show Extra Keys": "Εμφάνιση Επιπλέον Πλήκτρων",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Εναλλαγή Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Εναλλαγή Alt",
+ "Toggle Windows": "Εναλλαγή Παράθυρων",
+ "Windows": "Παράθυρα",
+ "Send Tab": "Αποστολή Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Αποστολή Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Αποστολή Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Κλείσιμο/Επανεκκίνηση",
+ "Shutdown/Reboot...": "Κλείσιμο/Επανεκκίνηση...",
+ "Power": "Απενεργοποίηση",
+ "Shutdown": "Κλείσιμο",
+ "Reboot": "Επανεκκίνηση",
+ "Reset": "Επαναφορά",
+ "Clipboard": "Πρόχειρο",
+ "Edit clipboard content in the textarea below.": "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω.",
+ "Full Screen": "Πλήρης Οθόνη",
+ "Settings": "Ρυθμίσεις",
+ "Shared Mode": "Κοινόχρηστη Λειτουργία",
+ "View Only": "Μόνο Θέαση",
+ "Clip to Window": "Αποκοπή στο όριο του Παράθυρου",
+ "Scaling Mode:": "Λειτουργία Κλιμάκωσης:",
+ "None": "Καμία",
+ "Local Scaling": "Τοπική Κλιμάκωση",
+ "Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους",
+ "Advanced": "Για προχωρημένους",
+ "Quality:": "Ποιότητα:",
+ "Compression level:": "Επίπεδο συμπίεσης:",
+ "Repeater ID:": "Repeater ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Κρυπτογράφηση",
+ "Host:": "Όνομα διακομιστή:",
+ "Port:": "Πόρτα διακομιστή:",
+ "Path:": "Διαδρομή:",
+ "Automatic Reconnect": "Αυτόματη επανασύνδεση",
+ "Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):",
+ "Show Dot when No Cursor": "Εμφάνιση Τελείας όταν δεν υπάρχει Δρομέας",
+ "Logging:": "Καταγραφή:",
+ "Version:": "Έκδοση:",
+ "Disconnect": "Αποσύνδεση",
+ "Connect": "Σύνδεση",
+ "Server identity": "Ταυτότητα Διακομιστή",
+ "The server has provided the following identifying information:": "Ο διακομιστής παρείχε την ακόλουθη πληροφορία ταυτοποίησης:",
+ "Fingerprint:": "Δακτυλικό αποτύπωμα:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Παρακαλώ επαληθεύσετε ότι η πληροφορία είναι σωστή και πιέστε \"Αποδοχή\". Αλλιώς πιέστε \"Απόρριψη\".",
+ "Approve": "Αποδοχή",
+ "Reject": "Απόρριψη",
+ "Credentials": "Διαπιστευτήρια",
+ "Username:": "Κωδικός Χρήστη:",
+ "Password:": "Κωδικός Πρόσβασης:",
+ "Send Credentials": "Αποστολή Διαπιστευτηρίων",
+ "Cancel": "Ακύρωση",
+ "Password is required": "Απαιτείται ο κωδικός πρόσβασης",
+ "viewport drag": "σύρσιμο θεατού πεδίου",
+ "Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού",
+ "No mousebutton": "Χωρίς Πλήκτρο Ποντικιού",
+ "Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού",
+ "Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού",
+ "Right mousebutton": "Δεξί Πλήκτρο Ποντικιού",
+ "Clear": "Καθάρισμα",
+ "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas",
+ "Disconnect timeout": "Παρέλευση χρονικού ορίου αποσύνδεσης",
+ "Local Downscaling": "Τοπική Συρρίκνωση",
+ "Local Cursor": "Τοπικός Δρομέας",
+ "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "Εφαρμογή λειτουργίας αποκοπής αφού δεν υποστηρίζονται οι λωρίδες κύλισης σε πλήρη οθόνη στον IE",
+ "True Color": "Πραγματικά Χρώματα",
+ "Style:": "Στυλ:",
+ "default": "προεπιλεγμένο",
+ "Apply": "Εφαρμογή",
+ "Connection": "Σύνδεση",
+ "Token:": "Διακριτικό:",
+ "Send Password": "Αποστολή Κωδικού Πρόσβασης"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/es.json b/client/public/vnc/locale/es.json
new file mode 100644
index 0000000..bb08824
--- /dev/null
+++ b/client/public/vnc/locale/es.json
@@ -0,0 +1,68 @@
+{
+ "Connecting...": "Conectando...",
+ "Connected (encrypted) to ": "Conectado (con encriptación) a",
+ "Connected (unencrypted) to ": "Conectado (sin encriptación) a",
+ "Disconnecting...": "Desconectando...",
+ "Disconnected": "Desconectado",
+ "Must set host": "Se debe configurar el host",
+ "Reconnecting...": "Reconectando...",
+ "Password is required": "La contraseña es obligatoria",
+ "Disconnect timeout": "Tiempo de desconexión agotado",
+ "noVNC encountered an error:": "noVNC ha encontrado un error:",
+ "Hide/Show the control bar": "Ocultar/Mostrar la barra de control",
+ "Move/Drag viewport": "Mover/Arrastrar la ventana",
+ "viewport drag": "Arrastrar la ventana",
+ "Active Mouse Button": "Botón activo del ratón",
+ "No mousebutton": "Ningún botón del ratón",
+ "Left mousebutton": "Botón izquierdo del ratón",
+ "Middle mousebutton": "Botón central del ratón",
+ "Right mousebutton": "Botón derecho del ratón",
+ "Keyboard": "Teclado",
+ "Show keyboard": "Mostrar teclado",
+ "Extra keys": "Teclas adicionales",
+ "Show Extra Keys": "Mostrar Teclas Adicionales",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Pulsar/Soltar Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Pulsar/Soltar Alt",
+ "Send Tab": "Enviar Tabulación",
+ "Tab": "Tabulación",
+ "Esc": "Esc",
+ "Send Escape": "Enviar Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Enviar Ctrl+Alt+Del",
+ "Shutdown/Reboot": "Apagar/Reiniciar",
+ "Shutdown/Reboot...": "Apagar/Reiniciar...",
+ "Power": "Encender",
+ "Shutdown": "Apagar",
+ "Reboot": "Reiniciar",
+ "Reset": "Restablecer",
+ "Clipboard": "Portapapeles",
+ "Clear": "Vaciar",
+ "Fullscreen": "Pantalla Completa",
+ "Settings": "Configuraciones",
+ "Encrypt": "Encriptar",
+ "Shared Mode": "Modo Compartido",
+ "View only": "Solo visualización",
+ "Clip to window": "Recortar al tamaño de la ventana",
+ "Scaling mode:": "Modo de escalado:",
+ "None": "Ninguno",
+ "Local Scaling": "Escalado Local",
+ "Local Downscaling": "Reducción de escala local",
+ "Remote resizing": "Cambio de tamaño remoto",
+ "Advanced": "Avanzado",
+ "Local Cursor": "Cursor Local",
+ "Repeater ID:": "ID del Repetidor:",
+ "WebSocket": "WebSocket",
+ "Host:": "Host:",
+ "Port:": "Puerto:",
+ "Path:": "Ruta:",
+ "Automatic reconnect": "Reconexión automática",
+ "Reconnect delay (ms):": "Retraso en la reconexión (ms):",
+ "Logging:": "Registrando:",
+ "Disconnect": "Desconectar",
+ "Connect": "Conectar",
+ "Password:": "Contraseña:",
+ "Cancel": "Cancelar",
+ "Canvas not supported.": "Canvas no soportado."
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/fr.json b/client/public/vnc/locale/fr.json
new file mode 100644
index 0000000..c8607ce
--- /dev/null
+++ b/client/public/vnc/locale/fr.json
@@ -0,0 +1,82 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "Lancer sans HTTPS n'est pas recommandé, crashs ou autres problèmes en vue.",
+ "Connecting...": "En cours de connexion...",
+ "Disconnecting...": "Déconnexion en cours...",
+ "Reconnecting...": "Reconnexion en cours...",
+ "Internal error": "Erreur interne",
+ "Failed to connect to server: ": "Échec de connexion au serveur ",
+ "Connected (encrypted) to ": "Connecté (chiffré) à ",
+ "Connected (unencrypted) to ": "Connecté (non chiffré) à ",
+ "Something went wrong, connection is closed": "Quelque chose s'est mal passé, la connexion a été fermée",
+ "Failed to connect to server": "Échec de connexion au serveur",
+ "Disconnected": "Déconnecté",
+ "New connection has been rejected with reason: ": "Une nouvelle connexion a été rejetée avec motif : ",
+ "New connection has been rejected": "Une nouvelle connexion a été rejetée",
+ "Credentials are required": "Les identifiants sont requis",
+ "noVNC encountered an error:": "noVNC a rencontré une erreur :",
+ "Hide/Show the control bar": "Masquer/Afficher la barre de contrôle",
+ "Drag": "Faire glisser",
+ "Move/Drag viewport": "Déplacer la fenêtre de visualisation",
+ "Keyboard": "Clavier",
+ "Show keyboard": "Afficher le clavier",
+ "Extra keys": "Touches supplémentaires",
+ "Show extra keys": "Afficher les touches supplémentaires",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Basculer Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Basculer Alt",
+ "Toggle Windows": "Basculer Windows",
+ "Windows": "Fenêtre",
+ "Send Tab": "Envoyer Tab",
+ "Tab": "Tabulation",
+ "Esc": "Esc",
+ "Send Escape": "Envoyer Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Envoyer Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Arrêter/Redémarrer",
+ "Shutdown/Reboot...": "Arrêter/Redémarrer...",
+ "Power": "Alimentation",
+ "Shutdown": "Arrêter",
+ "Reboot": "Redémarrer",
+ "Reset": "Réinitialiser",
+ "Clipboard": "Presse-papiers",
+ "Edit clipboard content in the textarea below.": "Editer le contenu du presse-papier dans la zone ci-dessous.",
+ "Full screen": "Plein écran",
+ "Settings": "Paramètres",
+ "Shared mode": "Mode partagé",
+ "View only": "Afficher uniquement",
+ "Clip to window": "Ajuster à la fenêtre",
+ "Scaling mode:": "Mode mise à l'échelle :",
+ "None": "Aucun",
+ "Local scaling": "Mise à l'échelle locale",
+ "Remote resizing": "Redimensionnement à distance",
+ "Advanced": "Avancé",
+ "Quality:": "Qualité :",
+ "Compression level:": "Niveau de compression :",
+ "Repeater ID:": "ID Répéteur :",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Chiffrer",
+ "Host:": "Hôte :",
+ "Port:": "Port :",
+ "Path:": "Chemin :",
+ "Automatic reconnect": "Reconnecter automatiquement",
+ "Reconnect delay (ms):": "Délai de reconnexion (ms) :",
+ "Show dot when no cursor": "Afficher le point lorsqu'il n'y a pas de curseur",
+ "Logging:": "Se connecter :",
+ "Version:": "Version :",
+ "Disconnect": "Déconnecter",
+ "Connect": "Connecter",
+ "Server identity": "Identité du serveur",
+ "The server has provided the following identifying information:": "Le serveur a fourni l'identification suivante :",
+ "Fingerprint:": "Empreinte digitale :",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "SVP, verifiez que l'information est correcte et pressez \"Accepter\". Sinon pressez \"Refuser\".",
+ "Approve": "Accepter",
+ "Reject": "Refuser",
+ "Credentials": "Envoyer les identifiants",
+ "Username:": "Nom d'utilisateur :",
+ "Password:": "Mot de passe :",
+ "Send credentials": "Envoyer les identifiants",
+ "Cancel": "Annuler",
+ "Must set host": "Doit définir l'hôte",
+ "Clear": "Effacer"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/hu.json b/client/public/vnc/locale/hu.json
new file mode 100644
index 0000000..ba700b5
--- /dev/null
+++ b/client/public/vnc/locale/hu.json
@@ -0,0 +1,80 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "HTTPS nélkül futtatni nem ajánlott, összeomlások vagy más problémák várhatók.",
+ "Connecting...": "Kapcsolódás...",
+ "Disconnecting...": "Kapcsolat bontása...",
+ "Reconnecting...": "Újrakapcsolódás...",
+ "Internal error": "Belső hiba",
+ "Failed to connect to server: ": "Nem sikerült csatlakozni a szerverhez: ",
+ "Connected (encrypted) to ": "Kapcsolódva (titkosítva) ehhez: ",
+ "Connected (unencrypted) to ": "Kapcsolódva (titkosítatlanul) ehhez: ",
+ "Something went wrong, connection is closed": "Valami hiba történt, a kapcsolat lezárult",
+ "Failed to connect to server": "Nem sikerült csatlakozni a szerverhez",
+ "Disconnected": "Kapcsolat bontva",
+ "New connection has been rejected with reason: ": "Az új kapcsolat elutasítva, indok: ",
+ "New connection has been rejected": "Az új kapcsolat elutasítva",
+ "Credentials are required": "Hitelesítő adatok szükségesek",
+ "noVNC encountered an error:": "A noVNC hibát észlelt:",
+ "Hide/Show the control bar": "Vezérlősáv elrejtése/megjelenítése",
+ "Drag": "Húzás",
+ "Move/Drag viewport": "Nézet mozgatása/húzása",
+ "Keyboard": "Billentyűzet",
+ "Show keyboard": "Billentyűzet megjelenítése",
+ "Extra keys": "Extra billentyűk",
+ "Show extra keys": "Extra billentyűk megjelenítése",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Ctrl lenyomása/felengedése",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt lenyomása/felengedése",
+ "Toggle Windows": "Windows lenyomása/felengedése",
+ "Windows": "Windows",
+ "Send Tab": "Tab küldése",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Escape küldése",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Ctrl-Alt-Del küldése",
+ "Shutdown/Reboot": "Leállítás/Újraindítás",
+ "Shutdown/Reboot...": "Leállítás/Újraindítás...",
+ "Power": "Bekapcsolás",
+ "Shutdown": "Leállítás",
+ "Reboot": "Újraindítás",
+ "Reset": "Reset",
+ "Clipboard": "Vágólap",
+ "Edit clipboard content in the textarea below.": "Itt tudod módosítani a vágólap tartalmát.",
+ "Full screen": "Teljes képernyő",
+ "Settings": "Beállítások",
+ "Shared mode": "Megosztott mód",
+ "View only": "Csak megtekintés",
+ "Clip to window": "Ablakhoz igazítás",
+ "Scaling mode:": "Méretezési mód:",
+ "None": "Nincs",
+ "Local scaling": "Helyi méretezés",
+ "Remote resizing": "Távoli átméretezés",
+ "Advanced": "Speciális",
+ "Quality:": "Minőség:",
+ "Compression level:": "Tömörítési szint:",
+ "Repeater ID:": "Ismétlő azonosító:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Titkosítás",
+ "Host:": "Hoszt:",
+ "Port:": "Port:",
+ "Path:": "Útvonal:",
+ "Automatic reconnect": "Automatikus újracsatlakozás",
+ "Reconnect delay (ms):": "Újracsatlakozás késleltetése (ms):",
+ "Show dot when no cursor": "Kurzor hiányában pont mutatása",
+ "Logging:": "Naplózás:",
+ "Version:": "Verzió:",
+ "Disconnect": "Kapcsolat bontása",
+ "Connect": "Csatlakozás",
+ "Server identity": "Szerver azonosító",
+ "The server has provided the following identifying information:": "A szerver a következő azonosító információt adta meg:",
+ "Fingerprint:": "Ujjlenyomat:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Ellenőrizze, hogy az információ helyes-e és nyomja meg a \"Jóváhagyás\" gombot. Ellenkező esetben nyomja meg az \"Elutasítás\" gombot.",
+ "Approve": "Jóváhagyás",
+ "Reject": "Elutasítás",
+ "Credentials": "Hitelesítő adatok",
+ "Username:": "Felhasználónév:",
+ "Password:": "Jelszó:",
+ "Send credentials": "Hitelesítő adatok küldése",
+ "Cancel": "Mégse"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/it.json b/client/public/vnc/locale/it.json
new file mode 100644
index 0000000..28e6f72
--- /dev/null
+++ b/client/public/vnc/locale/it.json
@@ -0,0 +1,68 @@
+{
+ "Connecting...": "Connessione in corso...",
+ "Disconnecting...": "Disconnessione...",
+ "Reconnecting...": "Riconnessione...",
+ "Internal error": "Errore interno",
+ "Must set host": "Devi impostare l'host",
+ "Connected (encrypted) to ": "Connesso (crittografato) a ",
+ "Connected (unencrypted) to ": "Connesso (non crittografato) a",
+ "Something went wrong, connection is closed": "Qualcosa è andato storto, la connessione è stata chiusa",
+ "Failed to connect to server": "Impossibile connettersi al server",
+ "Disconnected": "Disconnesso",
+ "New connection has been rejected with reason: ": "La nuova connessione è stata rifiutata con motivo: ",
+ "New connection has been rejected": "La nuova connessione è stata rifiutata",
+ "Credentials are required": "Le credenziali sono obbligatorie",
+ "noVNC encountered an error:": "noVNC ha riscontrato un errore:",
+ "Hide/Show the control bar": "Nascondi/Mostra la barra di controllo",
+ "Keyboard": "Tastiera",
+ "Show keyboard": "Mostra tastiera",
+ "Extra keys": "Tasti Aggiuntivi",
+ "Show Extra Keys": "Mostra Tasti Aggiuntivi",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Tieni premuto Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Tieni premuto Alt",
+ "Toggle Windows": "Tieni premuto Windows",
+ "Windows": "Windows",
+ "Send Tab": "Invia Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Invia Esc",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Canc",
+ "Send Ctrl-Alt-Del": "Invia Ctrl-Alt-Canc",
+ "Shutdown/Reboot": "Spegnimento/Riavvio",
+ "Shutdown/Reboot...": "Spegnimento/Riavvio...",
+ "Power": "Alimentazione",
+ "Shutdown": "Spegnimento",
+ "Reboot": "Riavvio",
+ "Reset": "Reset",
+ "Clipboard": "Clipboard",
+ "Clear": "Pulisci",
+ "Fullscreen": "Schermo intero",
+ "Settings": "Impostazioni",
+ "Shared mode": "Modalità condivisa",
+ "View Only": "Sola Visualizzazione",
+ "Scaling mode:": "Modalità di ridimensionamento:",
+ "None": "Nessuna",
+ "Local Scaling": "Ridimensionamento Locale",
+ "Remote Resizing": "Ridimensionamento Remoto",
+ "Advanced": "Avanzate",
+ "Quality:": "Qualità:",
+ "Compression level:": "Livello Compressione:",
+ "Repeater ID:": "ID Ripetitore:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Crittografa",
+ "Host:": "Host:",
+ "Port:": "Porta:",
+ "Path:": "Percorso:",
+ "Automatic Reconnect": "Riconnessione Automatica",
+ "Reconnect Delay (ms):": "Ritardo Riconnessione (ms):",
+ "Show Dot when No Cursor": "Mostra Punto quando Nessun Cursore",
+ "Version:": "Versione:",
+ "Disconnect": "Disconnetti",
+ "Connect": "Connetti",
+ "Username:": "Utente:",
+ "Password:": "Password:",
+ "Send Credentials": "Invia Credenziale",
+ "Cancel": "Annulla"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/ja.json b/client/public/vnc/locale/ja.json
new file mode 100644
index 0000000..4fc9b8a
--- /dev/null
+++ b/client/public/vnc/locale/ja.json
@@ -0,0 +1,81 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "HTTPS接続なしで実行することは推奨されません。クラッシュしたりその他の問題が発生したりする可能性があります。",
+ "Connecting...": "接続しています...",
+ "Disconnecting...": "切断しています...",
+ "Reconnecting...": "再接続しています...",
+ "Internal error": "内部エラー",
+ "Must set host": "ホストを設定する必要があります",
+ "Failed to connect to server: ": "サーバーへの接続に失敗しました: ",
+ "Connected (encrypted) to ": "接続しました (暗号化済み): ",
+ "Connected (unencrypted) to ": "接続しました (暗号化されていません): ",
+ "Something went wrong, connection is closed": "問題が発生したため、接続が閉じられました",
+ "Failed to connect to server": "サーバーへの接続に失敗しました",
+ "Disconnected": "切断しました",
+ "New connection has been rejected with reason: ": "新規接続は次の理由で拒否されました: ",
+ "New connection has been rejected": "新規接続は拒否されました",
+ "Credentials are required": "資格情報が必要です",
+ "noVNC encountered an error:": "noVNC でエラーが発生しました:",
+ "Hide/Show the control bar": "コントロールバーを隠す/表示する",
+ "Drag": "ドラッグ",
+ "Move/Drag viewport": "ビューポートを移動/ドラッグ",
+ "Keyboard": "キーボード",
+ "Show keyboard": "キーボードを表示",
+ "Extra keys": "追加キー",
+ "Show extra keys": "追加キーを表示",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Ctrl キーをトグル",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt キーをトグル",
+ "Toggle Windows": "Windows キーをトグル",
+ "Windows": "Windows",
+ "Send Tab": "Tab キーを送信",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Escape キーを送信",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Ctrl-Alt-Del を送信",
+ "Shutdown/Reboot": "シャットダウン/再起動",
+ "Shutdown/Reboot...": "シャットダウン/再起動...",
+ "Power": "電源",
+ "Shutdown": "シャットダウン",
+ "Reboot": "再起動",
+ "Reset": "リセット",
+ "Clipboard": "クリップボード",
+ "Edit clipboard content in the textarea below.": "以下の入力欄からクリップボードの内容を編集できます。",
+ "Full screen": "全画面表示",
+ "Settings": "設定",
+ "Shared mode": "共有モード",
+ "View only": "表示専用",
+ "Clip to window": "ウィンドウにクリップ",
+ "Scaling mode:": "スケーリングモード:",
+ "None": "なし",
+ "Local scaling": "ローカルでスケーリング",
+ "Remote resizing": "リモートでリサイズ",
+ "Advanced": "高度",
+ "Quality:": "品質:",
+ "Compression level:": "圧縮レベル:",
+ "Repeater ID:": "リピーター ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "暗号化",
+ "Host:": "ホスト:",
+ "Port:": "ポート:",
+ "Path:": "パス:",
+ "Automatic reconnect": "自動再接続",
+ "Reconnect delay (ms):": "再接続する遅延 (ミリ秒):",
+ "Show dot when no cursor": "カーソルがないときにドットを表示する",
+ "Logging:": "ロギング:",
+ "Version:": "バージョン:",
+ "Disconnect": "切断",
+ "Connect": "接続",
+ "Server identity": "サーバーの識別情報",
+ "The server has provided the following identifying information:": "サーバーは以下の識別情報を提供しています:",
+ "Fingerprint:": "フィンガープリント:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "この情報が正しい場合は「承認」を、そうでない場合は「拒否」を押してください。",
+ "Approve": "承認",
+ "Reject": "拒否",
+ "Credentials": "資格情報",
+ "Username:": "ユーザー名:",
+ "Password:": "パスワード:",
+ "Send credentials": "資格情報を送信",
+ "Cancel": "キャンセル"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/ko.json b/client/public/vnc/locale/ko.json
new file mode 100644
index 0000000..47b0805
--- /dev/null
+++ b/client/public/vnc/locale/ko.json
@@ -0,0 +1,70 @@
+{
+ "Connecting...": "연결중...",
+ "Disconnecting...": "연결 해제중...",
+ "Reconnecting...": "재연결중...",
+ "Internal error": "내부 오류",
+ "Must set host": "호스트는 설정되어야 합니다.",
+ "Connected (encrypted) to ": "다음과 (암호화되어) 연결되었습니다:",
+ "Connected (unencrypted) to ": "다음과 (암호화 없이) 연결되었습니다:",
+ "Something went wrong, connection is closed": "무언가 잘못되었습니다, 연결이 닫혔습니다.",
+ "Failed to connect to server": "서버에 연결하지 못했습니다.",
+ "Disconnected": "연결이 해제되었습니다.",
+ "New connection has been rejected with reason: ": "새 연결이 다음 이유로 거부되었습니다:",
+ "New connection has been rejected": "새 연결이 거부되었습니다.",
+ "Password is required": "비밀번호가 필요합니다.",
+ "noVNC encountered an error:": "noVNC에 오류가 발생했습니다:",
+ "Hide/Show the control bar": "컨트롤 바 숨기기/보이기",
+ "Move/Drag viewport": "움직이기/드래그 뷰포트",
+ "viewport drag": "뷰포트 드래그",
+ "Active Mouse Button": "마우스 버튼 활성화",
+ "No mousebutton": "마우스 버튼 없음",
+ "Left mousebutton": "왼쪽 마우스 버튼",
+ "Middle mousebutton": "중간 마우스 버튼",
+ "Right mousebutton": "오른쪽 마우스 버튼",
+ "Keyboard": "키보드",
+ "Show keyboard": "키보드 보이기",
+ "Extra keys": "기타 키들",
+ "Show extra keys": "기타 키들 보이기",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Ctrl 켜기/끄기",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt 켜기/끄기",
+ "Send Tab": "Tab 보내기",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Esc 보내기",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Ctrl+Alt+Del 보내기",
+ "Shutdown/Reboot": "셧다운/리붓",
+ "Shutdown/Reboot...": "셧다운/리붓...",
+ "Power": "전원",
+ "Shutdown": "셧다운",
+ "Reboot": "리붓",
+ "Reset": "리셋",
+ "Clipboard": "클립보드",
+ "Clear": "지우기",
+ "Fullscreen": "전체화면",
+ "Settings": "설정",
+ "Shared mode": "공유 모드",
+ "View only": "보기 전용",
+ "Clip to window": "창에 클립",
+ "Scaling mode:": "스케일링 모드:",
+ "None": "없음",
+ "Local scaling": "로컬 스케일링",
+ "Remote resizing": "원격 크기 조절",
+ "Advanced": "고급",
+ "Repeater ID:": "중계 ID",
+ "WebSocket": "웹소켓",
+ "Encrypt": "암호화",
+ "Host:": "호스트:",
+ "Port:": "포트:",
+ "Path:": "위치:",
+ "Automatic reconnect": "자동 재연결",
+ "Reconnect delay (ms):": "재연결 지연 시간 (ms)",
+ "Logging:": "로깅",
+ "Disconnect": "연결 해제",
+ "Connect": "연결",
+ "Password:": "비밀번호:",
+ "Send Password": "비밀번호 전송",
+ "Cancel": "취소"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/nl.json b/client/public/vnc/locale/nl.json
new file mode 100644
index 0000000..61f2df3
--- /dev/null
+++ b/client/public/vnc/locale/nl.json
@@ -0,0 +1,95 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "Het is niet aan te raden om zonder HTTPS te werken, crashes of andere problemen zijn dan waarschijnlijk.",
+ "Connecting...": "Aan het verbinden…",
+ "Disconnecting...": "Bezig om verbinding te verbreken...",
+ "Reconnecting...": "Opnieuw verbinding maken...",
+ "Internal error": "Interne fout",
+ "Failed to connect to server: ": "Verbinding maken met server is mislukt",
+ "Connected (encrypted) to ": "Verbonden (versleuteld) met ",
+ "Connected (unencrypted) to ": "Verbonden (onversleuteld) met ",
+ "Something went wrong, connection is closed": "Er iets fout gelopen, verbinding werd verbroken",
+ "Failed to connect to server": "Verbinding maken met server is mislukt",
+ "Disconnected": "Verbinding verbroken",
+ "New connection has been rejected with reason: ": "Nieuwe verbinding is geweigerd met de volgende reden: ",
+ "New connection has been rejected": "Nieuwe verbinding is geweigerd",
+ "Credentials are required": "Inloggegevens zijn nodig",
+ "noVNC encountered an error:": "noVNC heeft een fout bemerkt:",
+ "Hide/Show the control bar": "Verberg/Toon de bedieningsbalk",
+ "Drag": "Sleep",
+ "Move/Drag viewport": "Verplaats/Versleep Kijkvenster",
+ "Keyboard": "Toetsenbord",
+ "Show keyboard": "Toon Toetsenbord",
+ "Extra keys": "Extra toetsen",
+ "Show extra keys": "Toon Extra Toetsen",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Ctrl omschakelen",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt omschakelen",
+ "Toggle Windows": "Vensters omschakelen",
+ "Windows": "Vensters",
+ "Send Tab": "Tab Sturen",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Escape Sturen",
+ "Ctrl+Alt+Del": "Ctrl-Alt-Del",
+ "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Sturen",
+ "Shutdown/Reboot": "Uitschakelen/Herstarten",
+ "Shutdown/Reboot...": "Uitschakelen/Herstarten...",
+ "Power": "Systeem",
+ "Shutdown": "Uitschakelen",
+ "Reboot": "Herstarten",
+ "Reset": "Resetten",
+ "Clipboard": "Klembord",
+ "Edit clipboard content in the textarea below.": "Edit de inhoud van het klembord in het tekstveld hieronder",
+ "Full screen": "Volledig Scherm",
+ "Settings": "Instellingen",
+ "Shared mode": "Gedeelde Modus",
+ "View only": "Alleen Kijken",
+ "Clip to window": "Randen buiten venster afsnijden",
+ "Scaling mode:": "Schaalmodus:",
+ "None": "Geen",
+ "Local scaling": "Lokaal Schalen",
+ "Remote resizing": "Op Afstand Formaat Wijzigen",
+ "Advanced": "Geavanceerd",
+ "Quality:": "Kwaliteit:",
+ "Compression level:": "Compressieniveau:",
+ "Repeater ID:": "Repeater ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Versleutelen",
+ "Host:": "Host:",
+ "Port:": "Poort:",
+ "Path:": "Pad:",
+ "Automatic reconnect": "Automatisch Opnieuw Verbinden",
+ "Reconnect delay (ms):": "Vertraging voor Opnieuw Verbinden (ms):",
+ "Show dot when no cursor": "Geef stip weer indien geen cursor",
+ "Logging:": "Logmeldingen:",
+ "Version:": "Versie:",
+ "Disconnect": "Verbinding verbreken",
+ "Connect": "Verbinden",
+ "Server identity": "Serveridentiteit",
+ "The server has provided the following identifying information:": "De server geeft de volgende identificerende informatie:",
+ "Fingerprint:": "Vingerafdruk:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Verifieer dat de informatie is correct en druk “OK”. Druk anders op “Afwijzen”.",
+ "Approve": "OK",
+ "Reject": "Afwijzen",
+ "Credentials": "Inloggegevens",
+ "Username:": "Gebruikersnaam:",
+ "Password:": "Wachtwoord:",
+ "Send credentials": "Stuur inloggegevens",
+ "Cancel": "Annuleren",
+ "Must set host": "Host moeten worden ingesteld",
+ "Password is required": "Wachtwoord is vereist",
+ "viewport drag": "kijkvenster slepen",
+ "Active Mouse Button": "Actieve Muisknop",
+ "No mousebutton": "Geen muisknop",
+ "Left mousebutton": "Linker muisknop",
+ "Middle mousebutton": "Middelste muisknop",
+ "Right mousebutton": "Rechter muisknop",
+ "Clear": "Wissen",
+ "Send Password": "Verzend Wachtwoord:",
+ "Disconnect timeout": "Timeout tijdens verbreken van verbinding",
+ "Local Downscaling": "Lokaal Neerschalen",
+ "Local Cursor": "Lokale Cursor",
+ "Canvas not supported.": "Canvas wordt niet ondersteund.",
+ "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "''Clipping mode' ingeschakeld, omdat schuifbalken in volledige-scherm-modus in IE niet worden ondersteund"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/pl.json b/client/public/vnc/locale/pl.json
new file mode 100644
index 0000000..87c1690
--- /dev/null
+++ b/client/public/vnc/locale/pl.json
@@ -0,0 +1,80 @@
+{
+ "Connecting...": "Łączenie...",
+ "Disconnecting...": "Rozłączanie...",
+ "Reconnecting...": "Łączenie...",
+ "Internal error": "Błąd wewnętrzny",
+ "Must set host": "Host i port są wymagane",
+ "Connected (encrypted) to ": "Połączenie (szyfrowane) z ",
+ "Connected (unencrypted) to ": "Połączenie (nieszyfrowane) z ",
+ "Something went wrong, connection is closed": "Coś poszło źle, połączenie zostało zamknięte",
+ "Disconnected": "Rozłączony",
+ "New connection has been rejected with reason: ": "Nowe połączenie zostało odrzucone z powodu: ",
+ "New connection has been rejected": "Nowe połączenie zostało odrzucone",
+ "Password is required": "Hasło jest wymagane",
+ "noVNC encountered an error:": "noVNC napotkało błąd:",
+ "Hide/Show the control bar": "Pokaż/Ukryj pasek ustawień",
+ "Move/Drag Viewport": "Ruszaj/Przeciągaj Viewport",
+ "viewport drag": "przeciągnij viewport",
+ "Active Mouse Button": "Aktywny Przycisk Myszy",
+ "No mousebutton": "Brak przycisku myszy",
+ "Left mousebutton": "Lewy przycisk myszy",
+ "Middle mousebutton": "Środkowy przycisk myszy",
+ "Right mousebutton": "Prawy przycisk myszy",
+ "Keyboard": "Klawiatura",
+ "Show keyboard": "Pokaż klawiaturę",
+ "Extra keys": "Przyciski dodatkowe",
+ "Show extra keys": "Pokaż przyciski dodatkowe",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Przełącz Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Przełącz Alt",
+ "Send Tab": "Wyślij Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Wyślij Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Wyślij Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Wyłącz/Uruchom ponownie",
+ "Shutdown/Reboot...": "Wyłącz/Uruchom ponownie...",
+ "Power": "Włączony",
+ "Shutdown": "Wyłącz",
+ "Reboot": "Uruchom ponownie",
+ "Reset": "Resetuj",
+ "Clipboard": "Schowek",
+ "Clear": "Wyczyść",
+ "Fullscreen": "Pełny ekran",
+ "Settings": "Ustawienia",
+ "Shared Mode": "Tryb Współdzielenia",
+ "View Only": "Tylko Podgląd",
+ "Clip to Window": "Przytnij do Okna",
+ "Scaling Mode:": "Tryb Skalowania:",
+ "None": "Brak",
+ "Local scaling": "Skalowanie lokalne",
+ "Remote resizing": "Skalowanie zdalne",
+ "Advanced": "Zaawansowane",
+ "Repeater ID:": "ID Repeatera:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Szyfrowanie",
+ "Host:": "Host:",
+ "Port:": "Port:",
+ "Path:": "Ścieżka:",
+ "Automatic reconnect": "Automatycznie wznawiaj połączenie",
+ "Reconnect delay (ms):": "Opóźnienie wznawiania (ms):",
+ "Logging:": "Poziom logowania:",
+ "Disconnect": "Rozłącz",
+ "Connect": "Połącz",
+ "Password:": "Hasło:",
+ "Cancel": "Anuluj",
+ "Canvas not supported.": "Element Canvas nie jest wspierany.",
+ "Disconnect timeout": "Timeout rozłączenia",
+ "Local Downscaling": "Downscaling lokalny",
+ "Local Cursor": "Lokalny kursor",
+ "Forcing clipping mode since scrollbars aren't supported by IE in fullscreen": "Wymuszam clipping mode ponieważ paski przewijania nie są wspierane przez IE w trybie pełnoekranowym",
+ "True Color": "True Color",
+ "Style:": "Styl:",
+ "default": "domyślny",
+ "Apply": "Zapisz",
+ "Connection": "Połączenie",
+ "Token:": "Token:",
+ "Send Password": "Wyślij Hasło"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/pt_BR.json b/client/public/vnc/locale/pt_BR.json
new file mode 100644
index 0000000..9c2f7ce
--- /dev/null
+++ b/client/public/vnc/locale/pt_BR.json
@@ -0,0 +1,72 @@
+{
+ "Connecting...": "Conectando...",
+ "Disconnecting...": "Desconectando...",
+ "Reconnecting...": "Reconectando...",
+ "Internal error": "Erro interno",
+ "Must set host": "É necessário definir o host",
+ "Connected (encrypted) to ": "Conectado (com criptografia) a ",
+ "Connected (unencrypted) to ": "Conectado (sem criptografia) a ",
+ "Something went wrong, connection is closed": "Algo deu errado. A conexão foi encerrada.",
+ "Failed to connect to server": "Falha ao conectar-se ao servidor",
+ "Disconnected": "Desconectado",
+ "New connection has been rejected with reason: ": "A nova conexão foi rejeitada pelo motivo: ",
+ "New connection has been rejected": "A nova conexão foi rejeitada",
+ "Credentials are required": "Credenciais são obrigatórias",
+ "noVNC encountered an error:": "O noVNC encontrou um erro:",
+ "Hide/Show the control bar": "Esconder/mostrar a barra de controles",
+ "Drag": "Arrastar",
+ "Move/Drag viewport": "Mover/arrastar a janela",
+ "Keyboard": "Teclado",
+ "Show keyboard": "Mostrar teclado",
+ "Extra keys": "Teclas adicionais",
+ "Show extra keys": "Mostrar teclas adicionais",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Pressionar/soltar Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Pressionar/soltar Alt",
+ "Toggle Windows": "Pressionar/soltar Windows",
+ "Windows": "Windows",
+ "Send Tab": "Enviar Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Enviar Esc",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Enviar Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Desligar/reiniciar",
+ "Shutdown/Reboot...": "Desligar/reiniciar...",
+ "Power": "Ligar",
+ "Shutdown": "Desligar",
+ "Reboot": "Reiniciar",
+ "Reset": "Reiniciar (forçado)",
+ "Clipboard": "Área de transferência",
+ "Clear": "Limpar",
+ "Fullscreen": "Tela cheia",
+ "Settings": "Configurações",
+ "Shared mode": "Modo compartilhado",
+ "View only": "Apenas visualizar",
+ "Clip to window": "Recortar à janela",
+ "Scaling mode:": "Modo de dimensionamento:",
+ "None": "Nenhum",
+ "Local scaling": "Local",
+ "Remote resizing": "Remoto",
+ "Advanced": "Avançado",
+ "Quality:": "Qualidade:",
+ "Compression level:": "Nível de compressão:",
+ "Repeater ID:": "ID do repetidor:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Criptografar",
+ "Host:": "Host:",
+ "Port:": "Porta:",
+ "Path:": "Caminho:",
+ "Automatic reconnect": "Reconexão automática",
+ "Reconnect delay (ms):": "Atraso da reconexão (ms)",
+ "Show dot when no cursor": "Mostrar ponto quando não há cursor",
+ "Logging:": "Registros:",
+ "Version:": "Versão:",
+ "Disconnect": "Desconectar",
+ "Connect": "Conectar",
+ "Username:": "Nome de usuário:",
+ "Password:": "Senha:",
+ "Send credentials": "Enviar credenciais",
+ "Cancel": "Cancelar"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/ru.json b/client/public/vnc/locale/ru.json
new file mode 100644
index 0000000..bd1bb53
--- /dev/null
+++ b/client/public/vnc/locale/ru.json
@@ -0,0 +1,72 @@
+{
+ "Connecting...": "Подключение...",
+ "Disconnecting...": "Отключение...",
+ "Reconnecting...": "Переподключение...",
+ "Internal error": "Внутренняя ошибка",
+ "Must set host": "Задайте имя сервера или IP",
+ "Connected (encrypted) to ": "Подключено (с шифрованием) к ",
+ "Connected (unencrypted) to ": "Подключено (без шифрования) к ",
+ "Something went wrong, connection is closed": "Что-то пошло не так, подключение разорвано",
+ "Failed to connect to server": "Ошибка подключения к серверу",
+ "Disconnected": "Отключено",
+ "New connection has been rejected with reason: ": "Новое соединение отклонено по причине: ",
+ "New connection has been rejected": "Новое соединение отклонено",
+ "Credentials are required": "Требуются учетные данные",
+ "noVNC encountered an error:": "Ошибка noVNC: ",
+ "Hide/Show the control bar": "Скрыть/Показать контрольную панель",
+ "Drag": "Переместить",
+ "Move/Drag viewport": "Переместить окно",
+ "Keyboard": "Клавиатура",
+ "Show keyboard": "Показать клавиатуру",
+ "Extra keys": "Дополнительные Кнопки",
+ "Show Extra Keys": "Показать Дополнительные Кнопки",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Зажать Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Зажать Alt",
+ "Toggle Windows": "Зажать Windows",
+ "Windows": "Вкладка",
+ "Send Tab": "Передать нажатие Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Передать нажатие Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Передать нажатие Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Выключить/Перезагрузить",
+ "Shutdown/Reboot...": "Выключить/Перезагрузить...",
+ "Power": "Питание",
+ "Shutdown": "Выключить",
+ "Reboot": "Перезагрузить",
+ "Reset": "Сброс",
+ "Clipboard": "Буфер обмена",
+ "Clear": "Очистить",
+ "Fullscreen": "Во весь экран",
+ "Settings": "Настройки",
+ "Shared mode": "Общий режим",
+ "View Only": "Только Просмотр",
+ "Clip to window": "В окно",
+ "Scaling mode:": "Масштаб:",
+ "None": "Нет",
+ "Local scaling": "Локальный масштаб",
+ "Remote resizing": "Удаленная перенастройка размера",
+ "Advanced": "Дополнительно",
+ "Quality:": "Качество",
+ "Compression level:": "Уровень Сжатия",
+ "Repeater ID:": "Идентификатор ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Шифрование",
+ "Host:": "Сервер:",
+ "Port:": "Порт:",
+ "Path:": "Путь:",
+ "Automatic reconnect": "Автоматическое переподключение",
+ "Reconnect delay (ms):": "Задержка переподключения (мс):",
+ "Show dot when no cursor": "Показать точку вместо курсора",
+ "Logging:": "Лог:",
+ "Version:": "Версия",
+ "Disconnect": "Отключение",
+ "Connect": "Подключение",
+ "Username:": "Имя Пользователя",
+ "Password:": "Пароль:",
+ "Send Credentials": "Передача Учетных Данных",
+ "Cancel": "Выход"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/sv.json b/client/public/vnc/locale/sv.json
new file mode 100644
index 0000000..67f6675
--- /dev/null
+++ b/client/public/vnc/locale/sv.json
@@ -0,0 +1,83 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "Det är ej rekommenderat att köra utan HTTPS, krascher och andra problem är troliga.",
+ "Connecting...": "Ansluter...",
+ "Disconnecting...": "Kopplar ner...",
+ "Reconnecting...": "Återansluter...",
+ "Internal error": "Internt fel",
+ "Failed to connect to server: ": "Misslyckades att ansluta till servern: ",
+ "Connected (encrypted) to ": "Ansluten (krypterat) till ",
+ "Connected (unencrypted) to ": "Ansluten (okrypterat) till ",
+ "Something went wrong, connection is closed": "Något gick fel, anslutningen avslutades",
+ "Failed to connect to server": "Misslyckades att ansluta till servern",
+ "Disconnected": "Frånkopplad",
+ "New connection has been rejected with reason: ": "Ny anslutning har blivit nekad med följande skäl: ",
+ "New connection has been rejected": "Ny anslutning har blivit nekad",
+ "Credentials are required": "Användaruppgifter krävs",
+ "noVNC encountered an error:": "noVNC stötte på ett problem:",
+ "Hide/Show the control bar": "Göm/Visa kontrollbaren",
+ "Drag": "Dra",
+ "Move/Drag viewport": "Flytta/Dra vyn",
+ "Keyboard": "Tangentbord",
+ "Show keyboard": "Visa tangentbord",
+ "Extra keys": "Extraknappar",
+ "Show extra keys": "Visa extraknappar",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Växla Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Växla Alt",
+ "Toggle Windows": "Växla Windows",
+ "Windows": "Windows",
+ "Send Tab": "Skicka Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Skicka Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Skicka Ctrl-Alt-Del",
+ "Shutdown/Reboot": "Stäng av/Boota om",
+ "Shutdown/Reboot...": "Stäng av/Boota om...",
+ "Power": "Ström",
+ "Shutdown": "Stäng av",
+ "Reboot": "Boota om",
+ "Reset": "Återställ",
+ "Clipboard": "Urklipp",
+ "Edit clipboard content in the textarea below.": "Redigera urklippets innehåll i fältet nedan.",
+ "Full screen": "Fullskärm",
+ "Settings": "Inställningar",
+ "Shared mode": "Delat läge",
+ "View only": "Endast visning",
+ "Clip to window": "Begränsa till fönster",
+ "Scaling mode:": "Skalningsläge:",
+ "None": "Ingen",
+ "Local scaling": "Lokal skalning",
+ "Remote resizing": "Ändra storlek",
+ "Advanced": "Avancerat",
+ "Quality:": "Kvalitet:",
+ "Compression level:": "Kompressionsnivå:",
+ "Repeater ID:": "Repeater-ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Kryptera",
+ "Host:": "Värd:",
+ "Port:": "Port:",
+ "Path:": "Sökväg:",
+ "Automatic reconnect": "Automatisk återanslutning",
+ "Reconnect delay (ms):": "Fördröjning (ms):",
+ "Show dot when no cursor": "Visa prick när ingen muspekare finns",
+ "Logging:": "Loggning:",
+ "Version:": "Version:",
+ "Disconnect": "Koppla från",
+ "Connect": "Anslut",
+ "Server identity": "Server-identitet",
+ "The server has provided the following identifying information:": "Servern har gett följande identifierande information:",
+ "Fingerprint:": "Fingeravtryck:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Kontrollera att informationen är korrekt och tryck sedan \"Godkänn\". Tryck annars \"Neka\".",
+ "Approve": "Godkänn",
+ "Reject": "Neka",
+ "Credentials": "Användaruppgifter",
+ "Username:": "Användarnamn:",
+ "Password:": "Lösenord:",
+ "Send credentials": "Skicka användaruppgifter",
+ "Cancel": "Avbryt",
+ "Must set host": "Du måste specifiera en värd",
+ "HTTPS is required for full functionality": "HTTPS krävs för full funktionalitet",
+ "Clear": "Rensa"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/tr.json b/client/public/vnc/locale/tr.json
new file mode 100644
index 0000000..90f8162
--- /dev/null
+++ b/client/public/vnc/locale/tr.json
@@ -0,0 +1,69 @@
+{
+ "Connecting...": "Bağlanıyor...",
+ "Disconnecting...": "Bağlantı kesiliyor...",
+ "Reconnecting...": "Yeniden bağlantı kuruluyor...",
+ "Internal error": "İç hata",
+ "Must set host": "Sunucuyu kur",
+ "Connected (encrypted) to ": "Bağlı (şifrelenmiş)",
+ "Connected (unencrypted) to ": "Bağlandı (şifrelenmemiş)",
+ "Something went wrong, connection is closed": "Bir şeyler ters gitti, bağlantı kesildi",
+ "Disconnected": "Bağlantı kesildi",
+ "New connection has been rejected with reason: ": "Bağlantı aşağıdaki nedenlerden dolayı reddedildi: ",
+ "New connection has been rejected": "Bağlantı reddedildi",
+ "Password is required": "Şifre gerekli",
+ "noVNC encountered an error:": "Bir hata oluştu:",
+ "Hide/Show the control bar": "Denetim masasını Gizle/Göster",
+ "Move/Drag Viewport": "Görünümü Taşı/Sürükle",
+ "viewport drag": "Görüntü penceresini sürükle",
+ "Active Mouse Button": "Aktif Fare Düğmesi",
+ "No mousebutton": "Fare düğmesi yok",
+ "Left mousebutton": "Farenin sol düğmesi",
+ "Middle mousebutton": "Farenin orta düğmesi",
+ "Right mousebutton": "Farenin sağ düğmesi",
+ "Keyboard": "Klavye",
+ "Show Keyboard": "Klavye Düzenini Göster",
+ "Extra keys": "Ekstra tuşlar",
+ "Show extra keys": "Ekstra tuşları göster",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Ctrl Değiştir ",
+ "Alt": "Alt",
+ "Toggle Alt": "Alt Değiştir",
+ "Send Tab": "Sekme Gönder",
+ "Tab": "Sekme",
+ "Esc": "Esc",
+ "Send Escape": "Boşluk Gönder",
+ "Ctrl+Alt+Del": "Ctrl + Alt + Del",
+ "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Gönder",
+ "Shutdown/Reboot": "Kapat/Yeniden Başlat",
+ "Shutdown/Reboot...": "Kapat/Yeniden Başlat...",
+ "Power": "Güç",
+ "Shutdown": "Kapat",
+ "Reboot": "Yeniden Başlat",
+ "Reset": "Sıfırla",
+ "Clipboard": "Pano",
+ "Clear": "Temizle",
+ "Fullscreen": "Tam Ekran",
+ "Settings": "Ayarlar",
+ "Shared Mode": "Paylaşım Modu",
+ "View Only": "Sadece Görüntüle",
+ "Clip to Window": "Pencereye Tıkla",
+ "Scaling Mode:": "Ölçekleme Modu:",
+ "None": "Bilinmeyen",
+ "Local Scaling": "Yerel Ölçeklendirme",
+ "Remote Resizing": "Uzaktan Yeniden Boyutlandırma",
+ "Advanced": "Gelişmiş",
+ "Repeater ID:": "Tekralayıcı ID:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Şifrele",
+ "Host:": "Ana makine:",
+ "Port:": "Port:",
+ "Path:": "Yol:",
+ "Automatic Reconnect": "Otomatik Yeniden Bağlan",
+ "Reconnect Delay (ms):": "Yeniden Bağlanma Süreci (ms):",
+ "Logging:": "Giriş yapılıyor:",
+ "Disconnect": "Bağlantıyı Kes",
+ "Connect": "Bağlan",
+ "Password:": "Parola:",
+ "Cancel": "Vazgeç",
+ "Canvas not supported.": "Tuval desteklenmiyor."
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/uk.json b/client/public/vnc/locale/uk.json
new file mode 100644
index 0000000..513ed65
--- /dev/null
+++ b/client/public/vnc/locale/uk.json
@@ -0,0 +1,81 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "Робота без HTTPS не рекомендується, ймовірні збої чи інші проблеми.",
+ "Connecting...": "З'єднання...",
+ "Disconnecting...": "Від'єднання...",
+ "Reconnecting...": "Перез'єднання...",
+ "Internal error": "Внутрішня помилка",
+ "Failed to connect to server: ": "Не вдалося з'єднатися з сервером: ",
+ "Connected (encrypted) to ": "З'єднано (з шифруванням) з ",
+ "Connected (unencrypted) to ": "З'єднано (без шифрування) з ",
+ "Something went wrong, connection is closed": "Щось пішло не так, з'єднання закрито",
+ "Failed to connect to server": "Не вдалося з'єднатися з сервером",
+ "Disconnected": "Від'єднано",
+ "New connection has been rejected with reason: ": "Нове з'єднання відхилено. Причина: ",
+ "New connection has been rejected": "Нове з'єднання відхилено",
+ "Are you sure you want to disconnect the session?": "Точно від'єднати сеанс?",
+ "Credentials are required": "Треба особові дані",
+ "noVNC encountered an error:": "Помилка noVNC:",
+ "Hide/Show the control bar": "Сховати/показати панель керування",
+ "Drag": "Посунути",
+ "Move/Drag viewport": "Змістити область огляду",
+ "Keyboard": "Клавіатура",
+ "Show keyboard": "Показати клавіатуру",
+ "Extra keys": "Додаткові клавіші",
+ "Show extra keys": "Показати додаткові клавіші",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "Затиснути Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "Затиснути Alt",
+ "Toggle Windows": "Затиснути Windows",
+ "Windows": "Windows",
+ "Send Tab": "Натиснути Tab",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "Натиснути Escape",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "Натиснути Ctrl+Alt+Del",
+ "Shutdown/Reboot": "Вимкнути/перезавантажити",
+ "Shutdown/Reboot...": "Вимкнути/перезавантажити...",
+ "Power": "Живлення",
+ "Shutdown": "Вимкнути",
+ "Reboot": "Перезавантажити",
+ "Reset": "Скинути",
+ "Clipboard": "Буфер обміну",
+ "Edit clipboard content in the textarea below.": "Редагуйте вміст буфера обміну в текстовій зоні внизу.",
+ "Full screen": "Повний екран",
+ "Settings": "Параметри",
+ "Shared mode": "Спільний режим",
+ "View only": "Лише перегляд",
+ "Clip to window": "До розмірів вікна",
+ "Scaling mode:": "Режим масштабування:",
+ "None": "Вимкнено",
+ "Local scaling": "Локальне масштабування",
+ "Remote resizing": "Віддалене масштабування",
+ "Advanced": "Додатково",
+ "Quality:": "Якість:",
+ "Compression level:": "Рівень стиснення:",
+ "Repeater ID:": "Ідентифікатор репітера:",
+ "WebSocket": "WebSocket",
+ "Encrypt": "Шифрування",
+ "Host:": "Сервер:",
+ "Port:": "Порт:",
+ "Path:": "Шлях:",
+ "Automatic reconnect": "Автоматичне перез'єднання",
+ "Reconnect delay (ms):": "Затримка перез'єднання (мс):",
+ "Show dot when no cursor": "Показувати крапку, коли нема курсора",
+ "Logging:": "Журнал:",
+ "Version:": "Версія:",
+ "Disconnect": "Від'єднати",
+ "Connect": "З'єднати",
+ "Server identity": "Ідентифікація сервера",
+ "The server has provided the following identifying information:": "Сервер надає такі ідентифікаційні дані:",
+ "Fingerprint:": "Відбиток:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Перевірте, чи дані коректні, й натисніть «Схвалити». Інакше натисніть «Відхилити».",
+ "Approve": "Схвалити",
+ "Reject": "Відхилити",
+ "Credentials": "Особові дані",
+ "Username:": "Користувацьке ім'я:",
+ "Password:": "Пароль:",
+ "Send credentials": "Надіслати особові дані",
+ "Cancel": "Скасувати"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/zh_CN.json b/client/public/vnc/locale/zh_CN.json
new file mode 100644
index 0000000..2898d2c
--- /dev/null
+++ b/client/public/vnc/locale/zh_CN.json
@@ -0,0 +1,93 @@
+{
+ "Running without HTTPS is not recommended, crashes or other issues are likely.": "不建议在没有 HTTPS 的情况下运行,可能会出现崩溃或出现其他问题。",
+ "Connecting...": "连接中...",
+ "Disconnecting...": "正在断开连接...",
+ "Reconnecting...": "重新连接中...",
+ "Internal error": "内部错误",
+ "Must set host": "必须设置主机",
+ "Failed to connect to server: ": "无法连接到服务器:",
+ "Connected (encrypted) to ": "已连接(已加密)到",
+ "Connected (unencrypted) to ": "已连接(未加密)到",
+ "Something went wrong, connection is closed": "出了点问题,连接已关闭",
+ "Failed to connect to server": "无法连接到服务器",
+ "Disconnected": "已断开连接",
+ "New connection has been rejected with reason: ": "新连接被拒绝,原因如下:",
+ "New connection has been rejected": "新连接已被拒绝",
+ "Credentials are required": "需要凭证",
+ "noVNC encountered an error:": "noVNC 遇到一个错误:",
+ "Hide/Show the control bar": "显示/隐藏控制栏",
+ "Drag": "拖动",
+ "Move/Drag viewport": "移动/拖动窗口",
+ "Keyboard": "键盘",
+ "Show keyboard": "显示键盘",
+ "Extra keys": "额外按键",
+ "Show extra keys": "显示额外按键",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "切换 Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "切换 Alt",
+ "Toggle Windows": "切换窗口",
+ "Windows": "窗口",
+ "Send Tab": "发送 Tab 键",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "发送 Escape 键",
+ "Ctrl+Alt+Del": "Ctrl+Alt+Del",
+ "Send Ctrl-Alt-Del": "发送 Ctrl+Alt+Del 键",
+ "Shutdown/Reboot": "关机/重启",
+ "Shutdown/Reboot...": "关机/重启...",
+ "Power": "电源",
+ "Shutdown": "关机",
+ "Reboot": "重启",
+ "Reset": "重置",
+ "Clipboard": "剪贴板",
+ "Edit clipboard content in the textarea below.": "在下面的文本区域中编辑剪贴板内容。",
+ "Full screen": "全屏",
+ "Settings": "设置",
+ "Shared mode": "分享模式",
+ "View only": "仅查看",
+ "Clip to window": "限制/裁切窗口大小",
+ "Scaling mode:": "缩放模式:",
+ "None": "无",
+ "Local scaling": "本地缩放",
+ "Remote resizing": "远程调整大小",
+ "Advanced": "高级",
+ "Quality:": "品质:",
+ "Compression level:": "压缩级别:",
+ "Repeater ID:": "中继站 ID",
+ "WebSocket": "WebSocket",
+ "Encrypt": "加密",
+ "Host:": "主机:",
+ "Port:": "端口:",
+ "Path:": "路径:",
+ "Automatic reconnect": "自动重新连接",
+ "Reconnect delay (ms):": "重新连接间隔 (ms):",
+ "Show dot when no cursor": "无光标时显示点",
+ "Logging:": "日志级别:",
+ "Version:": "版本:",
+ "Disconnect": "断开连接",
+ "Connect": "连接",
+ "Server identity": "服务器身份",
+ "The server has provided the following identifying information:": "服务器提供了以下识别信息:",
+ "Fingerprint:": "指纹:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "请核实信息是否正确,并按 “同意”,否则按 “拒绝”。",
+ "Approve": "同意",
+ "Reject": "拒绝",
+ "Credentials": "凭证",
+ "Username:": "用户名:",
+ "Password:": "密码:",
+ "Send credentials": "发送凭证",
+ "Cancel": "取消",
+ "Password is required": "请提供密码",
+ "Disconnect timeout": "超时断开",
+ "viewport drag": "窗口拖动",
+ "Active Mouse Button": "启动鼠标按键",
+ "No mousebutton": "禁用鼠标按键",
+ "Left mousebutton": "鼠标左键",
+ "Middle mousebutton": "鼠标中键",
+ "Right mousebutton": "鼠标右键",
+ "Clear": "清除",
+ "Local Downscaling": "降低本地尺寸",
+ "Local Cursor": "本地光标",
+ "Canvas not supported.": "不支持 Canvas。"
+}
\ No newline at end of file
diff --git a/client/public/vnc/locale/zh_TW.json b/client/public/vnc/locale/zh_TW.json
new file mode 100644
index 0000000..9d292a3
--- /dev/null
+++ b/client/public/vnc/locale/zh_TW.json
@@ -0,0 +1,69 @@
+{
+ "Connecting...": "連線中...",
+ "Disconnecting...": "正在中斷連線...",
+ "Reconnecting...": "重新連線中...",
+ "Internal error": "內部錯誤",
+ "Must set host": "請提供主機資訊",
+ "Connected (encrypted) to ": "已加密連線到",
+ "Connected (unencrypted) to ": "未加密連線到",
+ "Something went wrong, connection is closed": "發生錯誤,連線已關閉",
+ "Failed to connect to server": "無法連線到伺服器",
+ "Disconnected": "連線已中斷",
+ "New connection has been rejected with reason: ": "連線被拒絕,原因:",
+ "New connection has been rejected": "連線被拒絕",
+ "Password is required": "請提供密碼",
+ "noVNC encountered an error:": "noVNC 遇到一個錯誤:",
+ "Hide/Show the control bar": "顯示/隱藏控制列",
+ "Move/Drag viewport": "拖放顯示範圍",
+ "viewport drag": "顯示範圍拖放",
+ "Active Mouse Button": "啟用滑鼠按鍵",
+ "No mousebutton": "無滑鼠按鍵",
+ "Left mousebutton": "滑鼠左鍵",
+ "Middle mousebutton": "滑鼠中鍵",
+ "Right mousebutton": "滑鼠右鍵",
+ "Keyboard": "鍵盤",
+ "Show keyboard": "顯示鍵盤",
+ "Extra keys": "額外按鍵",
+ "Show extra keys": "顯示額外按鍵",
+ "Ctrl": "Ctrl",
+ "Toggle Ctrl": "切換 Ctrl",
+ "Alt": "Alt",
+ "Toggle Alt": "切換 Alt",
+ "Send Tab": "送出 Tab 鍵",
+ "Tab": "Tab",
+ "Esc": "Esc",
+ "Send Escape": "送出 Escape 鍵",
+ "Ctrl+Alt+Del": "Ctrl-Alt-Del",
+ "Send Ctrl-Alt-Del": "送出 Ctrl-Alt-Del 快捷鍵",
+ "Shutdown/Reboot": "關機/重新啟動",
+ "Shutdown/Reboot...": "關機/重新啟動...",
+ "Power": "電源",
+ "Shutdown": "關機",
+ "Reboot": "重新啟動",
+ "Reset": "重設",
+ "Clipboard": "剪貼簿",
+ "Clear": "清除",
+ "Fullscreen": "全螢幕",
+ "Settings": "設定",
+ "Shared mode": "分享模式",
+ "View only": "僅檢視",
+ "Clip to window": "限制/裁切視窗大小",
+ "Scaling mode:": "縮放模式:",
+ "None": "無",
+ "Local scaling": "本機縮放",
+ "Remote resizing": "遠端調整大小",
+ "Advanced": "進階",
+ "Repeater ID:": "中繼站 ID",
+ "WebSocket": "WebSocket",
+ "Encrypt": "加密",
+ "Host:": "主機:",
+ "Port:": "連接埠:",
+ "Path:": "路徑:",
+ "Automatic reconnect": "自動重新連線",
+ "Reconnect delay (ms):": "重新連線間隔 (ms):",
+ "Logging:": "日誌級別:",
+ "Disconnect": "中斷連線",
+ "Connect": "連線",
+ "Password:": "密碼:",
+ "Cancel": "取消"
+}
\ No newline at end of file
diff --git a/client/public/vnc/localization.js b/client/public/vnc/localization.js
new file mode 100644
index 0000000..c8257fd
--- /dev/null
+++ b/client/public/vnc/localization.js
@@ -0,0 +1,206 @@
+/*
+ * noVNC: HTML5 VNC client
+ * Copyright (C) 2018 The noVNC authors
+ * Licensed under MPL 2.0 (see LICENSE.txt)
+ *
+ * See README.md for usage and integration instructions.
+ */
+
+/*
+ * Localization utilities
+ */
+
+export class Localizer {
+ constructor() {
+ // Currently configured language
+ this.language = 'en';
+
+ // Current dictionary of translations
+ this._dictionary = undefined;
+ }
+
+ // Configure suitable language based on user preferences
+ async setup(supportedLanguages, baseURL) {
+ this.language = 'en'; // Default: US English
+ this._dictionary = undefined;
+
+ this._setupLanguage(supportedLanguages);
+ await this._setupDictionary(baseURL);
+ }
+
+ _setupLanguage(supportedLanguages) {
+ /*
+ * Navigator.languages only available in Chrome (32+) and FireFox (32+)
+ * Fall back to navigator.language for other browsers
+ */
+ let userLanguages;
+ if (typeof window.navigator.languages == 'object') {
+ userLanguages = window.navigator.languages;
+ } else {
+ userLanguages = [navigator.language || navigator.userLanguage];
+ }
+
+ for (let i = 0;i < userLanguages.length;i++) {
+ const userLang = userLanguages[i]
+ .toLowerCase()
+ .replace("_", "-")
+ .split("-");
+
+ // First pass: perfect match
+ for (let j = 0; j < supportedLanguages.length; j++) {
+ const supLang = supportedLanguages[j]
+ .toLowerCase()
+ .replace("_", "-")
+ .split("-");
+
+ if (userLang[0] !== supLang[0]) {
+ continue;
+ }
+ if (userLang[1] !== supLang[1]) {
+ continue;
+ }
+
+ this.language = supportedLanguages[j];
+ return;
+ }
+
+ // Second pass: English fallback
+ if (userLang[0] === 'en') {
+ return;
+ }
+
+ // Third pass pass: other fallback
+ for (let j = 0;j < supportedLanguages.length;j++) {
+ const supLang = supportedLanguages[j]
+ .toLowerCase()
+ .replace("_", "-")
+ .split("-");
+
+ if (userLang[0] !== supLang[0]) {
+ continue;
+ }
+ if (supLang[1] !== undefined) {
+ continue;
+ }
+
+ this.language = supportedLanguages[j];
+ return;
+ }
+ }
+ }
+
+ async _setupDictionary(baseURL) {
+ if (baseURL) {
+ if (!baseURL.endsWith("/")) {
+ baseURL = baseURL + "/";
+ }
+ } else {
+ baseURL = "";
+ }
+
+ if (this.language === "en") {
+ return;
+ }
+
+ let response = await fetch(baseURL + this.language + ".json");
+ if (!response.ok) {
+ throw Error("" + response.status + " " + response.statusText);
+ }
+
+ this._dictionary = await response.json();
+ }
+
+ // Retrieve localised text
+ get(id) {
+ if (typeof this._dictionary !== 'undefined' &&
+ this._dictionary[id]) {
+ return this._dictionary[id];
+ } else {
+ return id;
+ }
+ }
+
+ // Traverses the DOM and translates relevant fields
+ // See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
+ translateDOM() {
+ const self = this;
+
+ function process(elem, enabled) {
+ function isAnyOf(searchElement, items) {
+ return items.indexOf(searchElement) !== -1;
+ }
+
+ function translateString(str) {
+ // We assume surrounding whitespace, and whitespace around line
+ // breaks is just for source formatting
+ str = str.split("\n").map(s => s.trim()).join(" ").trim();
+ return self.get(str);
+ }
+
+ function translateAttribute(elem, attr) {
+ const str = translateString(elem.getAttribute(attr));
+ elem.setAttribute(attr, str);
+ }
+
+ function translateTextNode(node) {
+ const str = translateString(node.data);
+ node.data = str;
+ }
+
+ if (elem.hasAttribute("translate")) {
+ if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) {
+ enabled = true;
+ } else if (isAnyOf(elem.getAttribute("translate"), ["no"])) {
+ enabled = false;
+ }
+ }
+
+ if (enabled) {
+ if (elem.hasAttribute("abbr") &&
+ elem.tagName === "TH") {
+ translateAttribute(elem, "abbr");
+ }
+ if (elem.hasAttribute("alt") &&
+ isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) {
+ translateAttribute(elem, "alt");
+ }
+ if (elem.hasAttribute("download") &&
+ isAnyOf(elem.tagName, ["A", "AREA"])) {
+ translateAttribute(elem, "download");
+ }
+ if (elem.hasAttribute("label") &&
+ isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP",
+ "OPTION", "TRACK"])) {
+ translateAttribute(elem, "label");
+ }
+ // FIXME: Should update "lang"
+ if (elem.hasAttribute("placeholder") &&
+ isAnyOf(elem.tagName, ["INPUT", "TEXTAREA"])) {
+ translateAttribute(elem, "placeholder");
+ }
+ if (elem.hasAttribute("title")) {
+ translateAttribute(elem, "title");
+ }
+ if (elem.hasAttribute("value") &&
+ elem.tagName === "INPUT" &&
+ isAnyOf(elem.getAttribute("type"), ["reset", "button", "submit"])) {
+ translateAttribute(elem, "value");
+ }
+ }
+
+ for (let i = 0; i < elem.childNodes.length; i++) {
+ const node = elem.childNodes[i];
+ if (node.nodeType === node.ELEMENT_NODE) {
+ process(node, enabled);
+ } else if (node.nodeType === node.TEXT_NODE && enabled) {
+ translateTextNode(node);
+ }
+ }
+ }
+
+ process(document.body, true);
+ }
+}
+
+export const l10n = new Localizer();
+export default l10n.get.bind(l10n);
diff --git a/client/public/vnc/sounds/CREDITS b/client/public/vnc/sounds/CREDITS
new file mode 100644
index 0000000..ec1fb55
--- /dev/null
+++ b/client/public/vnc/sounds/CREDITS
@@ -0,0 +1,4 @@
+bell
+ Copyright: Dr. Richard Boulanger et al
+ URL: http://www.archive.org/details/Berklee44v12
+ License: CC-BY Attribution 3.0 Unported
diff --git a/client/public/vnc/sounds/bell.mp3 b/client/public/vnc/sounds/bell.mp3
new file mode 100644
index 0000000..fdbf149
Binary files /dev/null and b/client/public/vnc/sounds/bell.mp3 differ
diff --git a/client/public/vnc/sounds/bell.oga b/client/public/vnc/sounds/bell.oga
new file mode 100644
index 0000000..144d2b3
Binary files /dev/null and b/client/public/vnc/sounds/bell.oga differ
diff --git a/client/public/vnc/styles/Orbitron700.ttf b/client/public/vnc/styles/Orbitron700.ttf
new file mode 100644
index 0000000..e28729d
Binary files /dev/null and b/client/public/vnc/styles/Orbitron700.ttf differ
diff --git a/client/public/vnc/styles/Orbitron700.woff b/client/public/vnc/styles/Orbitron700.woff
new file mode 100644
index 0000000..61db630
Binary files /dev/null and b/client/public/vnc/styles/Orbitron700.woff differ
diff --git a/client/public/vnc/styles/base.css b/client/public/vnc/styles/base.css
new file mode 100644
index 0000000..5e71ae7
--- /dev/null
+++ b/client/public/vnc/styles/base.css
@@ -0,0 +1,1106 @@
+/*
+ * noVNC base CSS
+ * Copyright (C) 2019 The noVNC authors
+ * noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
+ * This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
+ */
+
+/*
+ * Z index layers:
+ *
+ * 0: Main screen
+ * 10: Control bar
+ * 50: Transition blocker
+ * 60: Connection popups
+ * 100: Status bar
+ * ...
+ * 1000: Javascript crash
+ * ...
+ * 10000: Max (used for polyfills)
+ */
+
+/*
+ * State variables (set on :root):
+ *
+ * noVNC_loading: Page is still loading
+ * noVNC_connecting: Connecting to server
+ * noVNC_reconnecting: Re-establishing a connection
+ * noVNC_connected: Connected to server (most common state)
+ * noVNC_disconnecting: Disconnecting from server
+ */
+
+:root {
+ font-family: sans-serif;
+ line-height: 1.6;
+}
+
+body {
+ margin:0;
+ padding:0;
+ /*Background image with light grey curve.*/
+ background-color:#494949;
+ background-repeat:no-repeat;
+ background-position:right bottom;
+ height:100%;
+ touch-action: none;
+}
+
+html {
+ height:100%;
+}
+
+.noVNC_only_touch.noVNC_hidden {
+ display: none;
+}
+
+.noVNC_disabled {
+ color: var(--novnc-grey);
+}
+
+/* ----------------------------------------
+ * Spinner
+ * ----------------------------------------
+ */
+
+.noVNC_spinner {
+ position: relative;
+}
+.noVNC_spinner, .noVNC_spinner::before, .noVNC_spinner::after {
+ width: 10px;
+ height: 10px;
+ border-radius: 2px;
+ box-shadow: -60px 10px 0 rgba(255, 255, 255, 0);
+ animation: noVNC_spinner 1.0s linear infinite;
+}
+.noVNC_spinner::before {
+ content: "";
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ animation-delay: -0.1s;
+}
+.noVNC_spinner::after {
+ content: "";
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ animation-delay: 0.1s;
+}
+@keyframes noVNC_spinner {
+ 0% { box-shadow: -60px 10px 0 rgba(255, 255, 255, 0); width: 20px; }
+ 25% { box-shadow: 20px 10px 0 rgba(255, 255, 255, 1); width: 10px; }
+ 50% { box-shadow: 60px 10px 0 rgba(255, 255, 255, 0); width: 10px; }
+}
+
+/* ----------------------------------------
+ * WebKit centering hacks
+ * ----------------------------------------
+ */
+
+.noVNC_center {
+ /*
+ * This is a workaround because webkit misrenders transforms and
+ * uses non-integer coordinates, resulting in blurry content.
+ * Ideally we'd use "top: 50%; transform: translateY(-50%);" on
+ * the objects instead.
+ */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+}
+.noVNC_center > * {
+ pointer-events: auto;
+}
+
+.noVNC_crosscenter {
+ display: flex !important;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ margin: 0 !important;
+ padding: 0 !important;
+ pointer-events: none;
+}
+.noVNC_crosscenter > * {
+ pointer-events: auto;
+}
+.noVNC_right .noVNC_crosscenter {
+ left: auto;
+ right: 0;
+}
+.noVNC_top.noVNC_crosscenter,
+.noVNC_top .noVNC_crosscenter {
+ flex-direction: row;
+ width: 100%;
+ height: auto;
+}
+.noVNC_bottom.noVNC_crosscenter,
+.noVNC_bottom .noVNC_crosscenter {
+ flex-direction: row;
+ width: 100%;
+ height: auto;
+}
+.noVNC_bottom .noVNC_crosscenter {
+ top: auto;
+ bottom: 0;
+}
+
+/* ----------------------------------------
+ * Layering
+ * ----------------------------------------
+ */
+
+.noVNC_connect_layer {
+ z-index: 60;
+}
+
+/* ----------------------------------------
+ * Fallback error
+ * ----------------------------------------
+ */
+
+#noVNC_fallback_error {
+ z-index: 1000;
+ visibility: hidden;
+ /* Put a dark background in front of everything but the error,
+ and don't let mouse events pass through */
+ background: rgba(0, 0, 0, 0.8);
+ pointer-events: all;
+}
+#noVNC_fallback_error.noVNC_open {
+ visibility: visible;
+}
+
+#noVNC_fallback_error > div {
+ max-width: calc(100vw - 30px - 30px);
+ max-height: calc(100vh - 30px - 30px);
+ overflow: auto;
+
+ padding: 15px;
+
+ transition: 0.5s ease-in-out;
+
+ transform: translateY(-50px);
+ opacity: 0;
+
+ text-align: center;
+ font-weight: bold;
+ color: #fff;
+
+ border-radius: 12px;
+ box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
+ background: rgba(200,55,55,0.8);
+}
+#noVNC_fallback_error.noVNC_open > div {
+ transform: translateY(0);
+ opacity: 1;
+}
+
+#noVNC_fallback_errormsg {
+ font-weight: normal;
+}
+
+#noVNC_fallback_errormsg .noVNC_message {
+ display: inline-block;
+ text-align: left;
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+
+#noVNC_fallback_error .noVNC_location {
+ font-style: italic;
+ font-size: 0.8em;
+ color: rgba(255, 255, 255, 0.8);
+}
+
+#noVNC_fallback_error .noVNC_stack {
+ padding: 10px;
+ margin: 10px;
+ font-size: 0.8em;
+ text-align: left;
+ font-family: monospace;
+ white-space: pre;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ background: rgba(0, 0, 0, 0.2);
+ overflow: auto;
+}
+
+/* ----------------------------------------
+ * Control bar
+ * ----------------------------------------
+ */
+
+#noVNC_control_bar_anchor {
+ /* The anchor is needed to get z-stacking to work */
+ position: fixed;
+ z-index: 10;
+
+ transition: 0.5s ease-in-out;
+
+ /* Edge misrenders animations wihthout this */
+ transform: translateX(0);
+}
+:root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle {
+ opacity: 0.8;
+}
+#noVNC_control_bar_anchor:is(.noVNC_top, .noVNC_bottom) {
+ /* Edge misrenders animations wihthout this */
+ transform: translateY(0);
+}
+#noVNC_control_bar_anchor.noVNC_right {
+ left: auto;
+ right: 0;
+}
+#noVNC_control_bar_anchor.noVNC_bottom {
+ top: auto;
+ bottom: 0;
+}
+
+#noVNC_control_bar {
+ position: relative;
+ left: -100%;
+
+ transition: 0.5s ease-in-out;
+
+ background-color: var(--novnc-blue);
+ border-radius: 0 12px 12px 0;
+
+ user-select: none;
+ -webkit-user-select: none;
+ -webkit-touch-callout: none; /* Disable iOS image long-press popup */
+}
+.noVNC_right #noVNC_control_bar {
+ left: 100%;
+ border-radius: 12px 0 0 12px;
+}
+.noVNC_top #noVNC_control_bar {
+ left: auto;
+ /* FIXME: We want to mirror the left and right modes here and use a
+ relative top offset (-100%), but it doesn't resolve
+ correctly against the anchor height reference */
+ top: -55px;
+ border-radius: 0 0 12px 12px;
+}
+.noVNC_bottom #noVNC_control_bar {
+ left: auto;
+ /* FIXME: We want to mirror the left and right modes here and use a
+ relative top offset (100%), but it doesn't resolve
+ correctly against the anchor height reference */
+ top: 55px;
+ border-radius: 12px 12px 0 0;
+}
+#noVNC_control_bar.noVNC_open {
+ box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
+ left: 0;
+}
+:is(.noVNC_top, .noVNC_bottom) #noVNC_control_bar.noVNC_open {
+ left: auto;
+ top: 0;
+}
+#noVNC_control_bar::before {
+ /* This extra element is to get a proper shadow */
+ content: "";
+ position: absolute;
+ z-index: -1;
+ height: 100%;
+ width: 30px;
+ left: -30px;
+ transition: box-shadow 0.5s ease-in-out;
+}
+.noVNC_right #noVNC_control_bar::before {
+ visibility: hidden;
+}
+.noVNC_top #noVNC_control_bar::before {
+ height: 30px;
+ width: 100%;
+ top: -30px;
+ bottom: auto;
+}
+.noVNC_bottom #noVNC_control_bar::before {
+ visibility: hidden;
+}
+
+#noVNC_control_bar.noVNC_open::before {
+ box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
+}
+
+#noVNC_control_bar_handle {
+ position: absolute;
+ left: -15px;
+ top: 0;
+ transform: translateY(35px);
+ width: calc(100% + 30px);
+ height: 50px;
+ z-index: -1;
+ cursor: pointer;
+ border-radius: 6px;
+ background-color: var(--novnc-darkblue);
+ box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5);
+}
+:root:not(.noVNC_connected) #noVNC_control_bar_handle {
+ display: none;
+}
+:is(.noVNC_top, .noVNC_bottom) #noVNC_control_bar_handle {
+ transform: translateX(35px);
+ top: -15px;
+ left: 0;
+ width: 50px;
+ height: calc(100% + 30px);
+}
+
+#noVNC_control_bar_handle::before {
+ content: "";
+ background: url("../images/handle_bg.svg");
+ background-repeat: no-repeat;
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 15px;
+ height: 50px;
+}
+.noVNC_right #noVNC_control_bar_handle::before {
+ left: 0;
+ right: auto;
+}
+.noVNC_top #noVNC_control_bar_handle::before {
+ left: 0;
+ right: auto;
+ transform-origin: bottom left;
+ transform: rotate(90deg) translateX(20px);
+}
+.noVNC_bottom #noVNC_control_bar_handle::before {
+ left: 0;
+ right: auto;
+ transform-origin: bottom left;
+ transform: rotate(90deg) translateX(-50px);
+}
+
+#noVNC_control_bar_handle:after {
+ content: "";
+ transition: transform 0.5s ease-in-out;
+ background: url("../images/handle.svg") no-repeat center;
+ background-size: 5px 6px;
+ position: absolute;
+ top: 20px; /* (50px-10px)/2 */
+ right: 3px;
+ transform: none;
+ width: 10px;
+ height: 10px;
+ transform-origin: center;
+}
+.noVNC_right #noVNC_control_bar_handle:after {
+ left: 3px;
+ right: auto;
+ transform: rotate(180deg);
+}
+.noVNC_top #noVNC_control_bar_handle:after {
+ left: 20px;
+ right: auto;
+ top: auto;
+ bottom: 3px;
+ transform: rotate(90deg);
+}
+.noVNC_bottom #noVNC_control_bar_handle:after {
+ left: 20px;
+ right: auto;
+ top: 3px;
+ bottom: auto;
+ transform: rotate(-90deg);
+}
+
+#noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
+ transform: translateX(1px) rotate(180deg);
+}
+.noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
+ transform: translateX(-1px);
+}
+.noVNC_top #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
+ transform: translateY(1px) rotate(-90deg);
+}
+.noVNC_bottom #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
+ transform: translateY(-1px) rotate(90deg);
+}
+
+/* Larger touch area for the handle, used when a touch screen is available */
+#noVNC_control_bar_handle div {
+ position: absolute;
+ left: auto;
+ right: -35px;
+ top: 0;
+ width: 50px;
+ height: 100%;
+ display: none;
+}
+@media (any-pointer: coarse) {
+ #noVNC_control_bar_handle div {
+ display: initial;
+ }
+}
+.noVNC_right #noVNC_control_bar_handle div {
+ left: -35px;
+ right: auto;
+}
+.noVNC_top #noVNC_control_bar_handle div {
+ left: 0;
+ right: auto;
+ top: auto;
+ bottom: -35px;
+ width: 100%;
+ height: 50px;
+}
+.noVNC_bottom #noVNC_control_bar_handle div {
+ left: 0;
+ right: auto;
+ top: -35px;
+ bottom: auto;
+ width: 100%;
+ height: 50px;
+}
+
+#noVNC_control_bar > .noVNC_scroll {
+ max-height: 100vh; /* Chrome is buggy with 100% */
+ overflow-x: hidden;
+ overflow-y: auto;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 10px 0;
+}
+:is(.noVNC_top, .noVNC_bottom) > #noVNC_control_bar > .noVNC_scroll {
+ max-width: 100vw; /* Chrome is buggy with 100% */
+ overflow-x: auto;
+ overflow-y: hidden;
+ flex-direction: row;
+ gap: 0 10px;
+}
+
+/* Control bar hint */
+.noVNC_hint_anchor {
+ position: fixed;
+ left: -50px;
+}
+.noVNC_hint_anchor.noVNC_right {
+ left: auto;
+ right: -50px;
+}
+.noVNC_hint_anchor.noVNC_top {
+ left: auto;
+ top: -50px;
+}
+.noVNC_hint_anchor.noVNC_bottom {
+ left: auto;
+ top: auto;
+ bottom: -50px;
+}
+.noVNC_control_bar_hint {
+ width: 100px;
+ height: 50%;
+ max-height: 600px;
+ position: relative;
+ transform: scale(0);
+
+ visibility: hidden;
+ opacity: 0;
+ transition: 0.2s ease-in-out;
+ background: transparent;
+ box-shadow: 0 0 10px black, inset 0 0 10px 10px var(--novnc-darkblue);
+ border-radius: 12px;
+ transition-delay: 0s;
+}
+:is(.noVNC_top, .noVNC_bottom) .noVNC_control_bar_hint {
+ width: 50%;
+ height: 100px;
+ max-width: 600px;
+ max-height: none;
+}
+.noVNC_control_bar_hint.noVNC_active {
+ visibility: visible;
+ opacity: 1;
+ transition-delay: 0.2s;
+ transform: scale(1);
+}
+.noVNC_control_bar_hint.noVNC_notransition {
+ transition: none !important;
+}
+
+/* Control bar buttons */
+#noVNC_control_bar .noVNC_button {
+ min-width: unset;
+ padding: 4px 4px;
+ border:1px solid rgba(255, 255, 255, 0.2);
+ border-radius: 6px;
+ background-color: transparent;
+}
+#noVNC_control_bar .noVNC_button.noVNC_selected {
+ border-color: rgba(0, 0, 0, 0.8);
+ background-color: rgba(0, 0, 0, 0.5);
+}
+#noVNC_control_bar .noVNC_button.noVNC_hidden {
+ display: none !important;
+}
+
+/* Panels */
+.noVNC_panel {
+ transform: translateX(25px);
+
+ transition: 0.5s ease-in-out;
+
+ box-sizing: border-box; /* so max-width don't have to care about padding */
+ max-width: calc(100vw - 75px - 25px); /* minus left and right margins */
+ max-height: calc(100vh - 75px - 25px); /* minus top and bottom margins */
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ visibility: hidden;
+ opacity: 0;
+
+ padding: 15px;
+
+ background: #fff;
+ border-radius: 12px;
+ color: #000;
+ border: 2px solid #E0E0E0;
+ box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
+}
+.noVNC_panel.noVNC_open {
+ visibility: visible;
+ opacity: 1;
+ transform: translateX(75px);
+}
+.noVNC_right .noVNC_panel {
+ transform: translateX(-25px);
+}
+.noVNC_right .noVNC_panel.noVNC_open {
+ transform: translateX(-75px);
+}
+.noVNC_top .noVNC_panel {
+ transform: translateY(25px);
+}
+.noVNC_top .noVNC_panel.noVNC_open {
+ transform: translateY(75px);
+}
+.noVNC_bottom .noVNC_panel {
+ transform: translateY(-25px);
+}
+.noVNC_bottom .noVNC_panel.noVNC_open {
+ transform: translateY(-75px);
+}
+
+.noVNC_panel > * {
+ display: block;
+ margin: 10px auto;
+}
+.noVNC_panel > *:first-child {
+ margin-top: 0 !important;
+}
+.noVNC_panel > *:last-child {
+ margin-bottom: 0 !important;
+}
+
+.noVNC_panel hr {
+ border: none;
+ border-top: 1px solid var(--novnc-lightgrey);
+ width: 100%; /*
inside a flexbox will otherwise be 0px wide */
+}
+
+.noVNC_panel label {
+ display: block;
+ white-space: nowrap;
+ margin: 5px;
+}
+@media (max-width: 540px) {
+ /* Allow wrapping on small screens */
+ .noVNC_panel label {
+ white-space: unset;
+ }
+}
+
+.noVNC_panel li {
+ margin: 5px;
+}
+
+.noVNC_panel .noVNC_heading {
+ background-color: var(--novnc-blue);
+ border-radius: 6px;
+ padding: 5px 8px;
+ /* Compensate for padding in image */
+ padding-right: 11px;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ color: white;
+ font-size: 20px;
+ font-weight: bold;
+ white-space: nowrap;
+}
+.noVNC_panel .noVNC_heading img {
+ vertical-align: bottom;
+}
+
+.noVNC_panel form {
+ display: flex;
+ flex-direction: column;
+ gap: 12px
+}
+
+.noVNC_panel .button_row {
+ margin-top: 10px;
+ display: flex;
+ gap: 10px;
+ justify-content: space-between;
+}
+.noVNC_panel .button_row *:only-child {
+ margin-left: auto; /* Align single buttons to the right */
+}
+
+/* Expanders */
+.noVNC_expander {
+ cursor: pointer;
+}
+.noVNC_expander::before {
+ content: url("../images/expander.svg");
+ display: inline-block;
+ margin-right: 5px;
+ transition: 0.2s ease-in-out;
+}
+.noVNC_expander.noVNC_open::before {
+ transform: rotateZ(90deg);
+}
+.noVNC_expander ~ * {
+ margin: 5px;
+ margin-left: 10px;
+ padding: 5px;
+ background: rgba(0, 0, 0, 0.04);
+ border-radius: 6px;
+}
+.noVNC_expander:not(.noVNC_open) ~ * {
+ display: none;
+}
+
+/* Control bar content */
+
+#noVNC_control_bar .noVNC_logo {
+ display: block;
+ max-width: 35px;
+ max-height: 35px;
+ object-fit: contain;
+}
+
+.noVNC_logo + hr {
+ /* Remove all but top border */
+ border: none;
+ border-top: 1px solid rgba(255, 255, 255, 0.2);
+ width: 35px;
+ height: 1px;
+ margin: 0;
+}
+:is(.noVNC_top, .noVNC_bottom) .noVNC_logo + hr {
+ /* Remove all but left border */
+ border-left: 1px solid rgba(255, 255, 255, 0.2);
+ border-top: none;
+ width: 1px;
+ height: 35px;
+}
+
+:root:not(.noVNC_connected) #noVNC_view_drag_button {
+ display: none;
+}
+
+/* noVNC Touch Device only buttons */
+:root:not(.noVNC_connected) #noVNC_keyboard_button {
+ display: none;
+}
+@media not all and (any-pointer: coarse) {
+ /* FIXME: It is bad to assume that no touch devices have physical
+ keyboards available. Hopefully we can get a media query
+ for this:
+ https://github.com/w3c/csswg-drafts/issues/3871 */
+ :root.noVNC_connected #noVNC_keyboard_button {
+ display: none;
+ }
+}
+
+/* Extra manual keys */
+:root:not(.noVNC_connected) #noVNC_toggle_extra_keys_button {
+ display: none;
+}
+
+#noVNC_modifiers {
+ background-color: var(--novnc-darkgrey);
+ border: none;
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 10px 0;
+}
+#noVNC_modifiers > * {
+ margin: 0;
+}
+:is(.noVNC_top, .noVNC_bottom) #noVNC_modifiers {
+ flex-direction: row;
+ gap: 0 10px;
+}
+
+/* Shutdown/Reboot */
+:root:not(.noVNC_connected) #noVNC_power_button {
+ display: none;
+}
+#noVNC_power {
+}
+#noVNC_power_buttons {
+ display: none;
+}
+
+#noVNC_power input[type=button] {
+ width: 100%;
+}
+
+/* Clipboard */
+:root:not(.noVNC_connected) #noVNC_clipboard_button {
+ display: none;
+}
+#noVNC_clipboard_text {
+ width: 360px;
+ min-width: 150px;
+ height: 160px;
+ min-height: 70px;
+
+ box-sizing: border-box;
+ max-width: 100%;
+ /* minus approximate height of title, height of subtitle, and margin */
+ max-height: calc(100vh - 10em - 25px);
+}
+
+/* Settings */
+#noVNC_settings {
+}
+#noVNC_settings ul {
+ list-style: none;
+ padding: 0px;
+}
+#noVNC_settings button,
+#noVNC_settings select,
+#noVNC_settings textarea,
+#noVNC_settings input:not([type=checkbox]):not([type=radio]) {
+ margin-left: 6px;
+ /* Prevent inputs in settings from being too wide */
+ max-width: calc(100% - 6px - var(--input-xpadding) * 2);
+}
+
+#noVNC_setting_port {
+ width: 80px;
+}
+#noVNC_setting_path {
+ width: 100px;
+}
+
+/* Version */
+
+.noVNC_version_wrapper {
+ font-size: small;
+}
+
+.noVNC_version {
+ margin-left: 1rem;
+}
+
+/* Connection controls */
+:root:not(.noVNC_connected) #noVNC_disconnect_button {
+ display: none;
+}
+
+/* ----------------------------------------
+ * Status dialog
+ * ----------------------------------------
+ */
+
+#noVNC_status {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ z-index: 100;
+ transform: translateY(-100%);
+
+ cursor: pointer;
+
+ transition: 0.5s ease-in-out;
+
+ visibility: hidden;
+ opacity: 0;
+
+ padding: 5px;
+
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-content: center;
+
+ line-height: 1.6;
+ word-wrap: break-word;
+ color: #fff;
+
+ border-bottom: 1px solid rgba(0, 0, 0, 0.9);
+}
+#noVNC_status.noVNC_open {
+ transform: translateY(0);
+ visibility: visible;
+ opacity: 1;
+}
+
+#noVNC_status::before {
+ content: "";
+ display: inline-block;
+ width: 25px;
+ height: 25px;
+ margin-right: 5px;
+}
+
+#noVNC_status.noVNC_status_normal {
+ background: rgba(128,128,128,0.9);
+}
+#noVNC_status.noVNC_status_normal::before {
+ content: url("../images/info.svg") " ";
+}
+#noVNC_status.noVNC_status_error {
+ background: rgba(200,55,55,0.9);
+}
+#noVNC_status.noVNC_status_error::before {
+ content: url("../images/error.svg") " ";
+}
+#noVNC_status.noVNC_status_warn {
+ background: rgba(180,180,30,0.9);
+}
+#noVNC_status.noVNC_status_warn::before {
+ content: url("../images/warning.svg") " ";
+}
+
+/* ----------------------------------------
+ * Connect dialog
+ * ----------------------------------------
+ */
+
+#noVNC_connect_dlg {
+ transition: 0.5s ease-in-out;
+
+ transform: scale(0, 0);
+ visibility: hidden;
+ opacity: 0;
+}
+#noVNC_connect_dlg.noVNC_open {
+ transform: scale(1, 1);
+ visibility: visible;
+ opacity: 1;
+}
+#noVNC_connect_dlg .noVNC_logo {
+ transition: 0.5s ease-in-out;
+ padding: 10px;
+ margin-bottom: 10px;
+
+ font-size: 80px;
+ text-align: center;
+
+ border-radius: 6px;
+}
+@media (max-width: 440px) {
+ #noVNC_connect_dlg {
+ max-width: calc(100vw - 100px);
+ }
+ #noVNC_connect_dlg .noVNC_logo {
+ font-size: calc(25vw - 30px);
+ }
+}
+#noVNC_connect_dlg div {
+ padding: 18px;
+
+ background-color: var(--novnc-darkgrey);
+ border-radius: 12px;
+ text-align: center;
+ font-size: 20px;
+
+ box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
+}
+#noVNC_connect_button {
+ width: 100%;
+ padding: 6px 30px;
+ cursor: pointer;
+ border-color: transparent;
+ border-radius: 12px;
+ background-color: var(--novnc-blue);
+ color: white;
+
+ display: flex;
+ justify-content: center;
+ place-items: center;
+ gap: 4px;
+}
+
+#noVNC_connect_button img {
+ vertical-align: bottom;
+ height: 1.3em;
+}
+
+/* ----------------------------------------
+ * Server verification dialog
+ * ----------------------------------------
+ */
+
+#noVNC_verify_server_dlg {
+ position: relative;
+
+ transform: translateY(-50px);
+}
+#noVNC_verify_server_dlg.noVNC_open {
+ transform: translateY(0);
+}
+#noVNC_fingerprint_block {
+ margin: 10px;
+}
+
+/* ----------------------------------------
+ * Password dialog
+ * ----------------------------------------
+ */
+
+#noVNC_credentials_dlg {
+ position: relative;
+
+ transform: translateY(-50px);
+}
+#noVNC_credentials_dlg.noVNC_open {
+ transform: translateY(0);
+}
+#noVNC_username_block.noVNC_hidden,
+#noVNC_password_block.noVNC_hidden {
+ display: none;
+}
+
+
+/* ----------------------------------------
+ * Main area
+ * ----------------------------------------
+ */
+
+/* Transition screen */
+#noVNC_transition {
+ transition: 0.5s ease-in-out;
+
+ display: flex;
+ opacity: 0;
+ visibility: hidden;
+
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+
+ color: white;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 50;
+
+ /*display: flex;*/
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+}
+:root.noVNC_loading #noVNC_transition,
+:root.noVNC_connecting #noVNC_transition,
+:root.noVNC_disconnecting #noVNC_transition,
+:root.noVNC_reconnecting #noVNC_transition {
+ opacity: 1;
+ visibility: visible;
+}
+:root:not(.noVNC_reconnecting) #noVNC_cancel_reconnect_button {
+ display: none;
+}
+#noVNC_transition_text {
+ font-size: 1.5em;
+}
+
+/* Main container */
+#noVNC_container {
+ width: 100%;
+ height: 100%;
+ background-color: #313131;
+ border-bottom-right-radius: 800px 600px;
+ /*border-top-left-radius: 800px 600px;*/
+
+ /* If selection isn't disabled, long-pressing stuff in the sidebar
+ can accidentally select the container or the canvas. This can
+ happen when attempting to move the handle. */
+ user-select: none;
+ -webkit-user-select: none;
+}
+
+#noVNC_keyboardinput {
+ width: 1px;
+ height: 1px;
+ background-color: #fff;
+ color: #fff;
+ border: 0;
+ position: absolute;
+ left: -40px;
+ z-index: -1;
+ ime-mode: disabled;
+}
+
+/*Default noVNC logo.*/
+/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */
+@font-face {
+ font-family: 'Orbitron';
+ font-style: normal;
+ font-weight: 700;
+ src: local('?'), url('Orbitron700.woff') format('woff'),
+ url('Orbitron700.ttf') format('truetype');
+}
+
+.noVNC_logo {
+ color: var(--novnc-yellow);
+ font-family: 'Orbitron', 'OrbitronTTF', sans-serif;
+ line-height: 0.9;
+ text-shadow: 0.1em 0.1em 0 black;
+}
+.noVNC_logo span{
+ color: var(--novnc-green);
+}
+
+#noVNC_bell {
+ display: none;
+}
+
+/* ----------------------------------------
+ * Media sizing
+ * ----------------------------------------
+ */
+
+@media screen and (max-width: 640px){
+ #noVNC_logo {
+ font-size: 150px;
+ }
+}
+
+@media screen and (min-width: 321px) and (max-width: 480px) {
+ #noVNC_logo {
+ font-size: 110px;
+ }
+}
+
+@media screen and (max-width: 320px) {
+ #noVNC_logo {
+ font-size: 90px;
+ }
+}
diff --git a/client/public/vnc/styles/constants.css b/client/public/vnc/styles/constants.css
new file mode 100644
index 0000000..1123a3e
--- /dev/null
+++ b/client/public/vnc/styles/constants.css
@@ -0,0 +1,30 @@
+/*
+ * noVNC general CSS constant variables
+ * Copyright (C) 2025 The noVNC authors
+ * noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
+ * This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
+ */
+
+/* ---------- COLORS ----------- */
+
+:root {
+ --novnc-grey: rgb(128, 128, 128);
+ --novnc-lightgrey: rgb(192, 192, 192);
+ --novnc-darkgrey: rgb(92, 92, 92);
+
+ /* Transparent to make button colors adapt to the background */
+ --novnc-buttongrey: rgba(192, 192, 192, 0.5);
+
+ --novnc-blue: rgb(110, 132, 163);
+ --novnc-lightblue: rgb(74, 144, 217);
+ --novnc-darkblue: rgb(83, 99, 122);
+
+ --novnc-green: rgb(0, 128, 0);
+ --novnc-yellow: rgb(255, 255, 0);
+}
+
+/* ------ MISC PROPERTIES ------ */
+
+:root {
+ --input-xpadding: 1em;
+}
diff --git a/client/public/vnc/styles/input.css b/client/public/vnc/styles/input.css
new file mode 100644
index 0000000..8273d70
--- /dev/null
+++ b/client/public/vnc/styles/input.css
@@ -0,0 +1,628 @@
+/*
+ * noVNC general input element CSS
+ * Copyright (C) 2025 The noVNC authors
+ * noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
+ * This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
+ */
+
+/* ------- SHARED BETWEEN INPUT ELEMENTS -------- */
+
+input,
+textarea,
+button,
+select,
+input::file-selector-button {
+ padding: 0.5em var(--input-xpadding);
+ border-radius: 6px;
+ appearance: none;
+ text-overflow: ellipsis;
+
+ /* Respect standard font settings */
+ font: inherit;
+ line-height: 1.6;
+}
+input:disabled,
+textarea:disabled,
+button:disabled,
+select:disabled,
+label[disabled] {
+ opacity: 0.4;
+}
+
+input:focus-visible,
+textarea:focus-visible,
+button:focus-visible,
+select:focus-visible,
+input:focus-visible::file-selector-button {
+ outline: 2px solid var(--novnc-lightblue);
+ outline-offset: 1px;
+}
+
+/* ------- TEXT INPUT -------- */
+
+input:not([type]),
+input[type=date],
+input[type=datetime-local],
+input[type=email],
+input[type=month],
+input[type=number],
+input[type=password],
+input[type=search],
+input[type=tel],
+input[type=text],
+input[type=time],
+input[type=url],
+input[type=week],
+textarea {
+ border: 1px solid var(--novnc-lightgrey);
+ /* Account for borders on text inputs, buttons dont have borders */
+ padding: calc(0.5em - 1px) var(--input-xpadding);
+}
+input:not([type]):focus-visible,
+input[type=date]:focus-visible,
+input[type=datetime-local]:focus-visible,
+input[type=email]:focus-visible,
+input[type=month]:focus-visible,
+input[type=number]:focus-visible,
+input[type=password]:focus-visible,
+input[type=search]:focus-visible,
+input[type=tel]:focus-visible,
+input[type=text]:focus-visible,
+input[type=time]:focus-visible,
+input[type=url]:focus-visible,
+input[type=week]:focus-visible,
+textarea:focus-visible {
+ outline-offset: -1px;
+}
+
+textarea {
+ margin: unset; /* Remove Firefox's built in margin */
+ /* Prevent layout from shifting when scrollbars show */
+ scrollbar-gutter: stable;
+ /* Make textareas show at minimum one line. This does not work when
+ using box-sizing border-box, in which case, vertical padding and
+ border width needs to be taken into account. */
+ min-height: 1lh;
+ vertical-align: baseline; /* Firefox gives "text-bottom" by default */
+}
+
+/* ------- NUMBER PICKERS ------- */
+
+/* We can't style the number spinner buttons:
+ https://github.com/w3c/csswg-drafts/issues/8777 */
+input[type=number]::-webkit-inner-spin-button,
+input[type=number]::-webkit-outer-spin-button {
+ /* Get rid of increase/decrease buttons in WebKit */
+ appearance: none;
+}
+input[type=number] {
+ /* Get rid of increase/decrease buttons in Firefox */
+ appearance: textfield;
+}
+
+/* ------- BUTTON ACTIVATIONS -------- */
+
+/* A color overlay that depends on the activation level. The level can then be
+ set for different states on an element, for example hover and click on a
+