diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index d38162800..000000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -**/xtscancodes.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 900a7186e..000000000 --- a/.eslintrc +++ /dev/null @@ -1,48 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true - }, - "parserOptions": { - "sourceType": "module" - }, - "extends": "eslint:recommended", - "rules": { - // Unsafe or confusing stuff that we forbid - - "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], - "no-constant-condition": ["error", { "checkLoops": false }], - "no-var": "error", - "no-useless-constructor": "error", - "object-shorthand": ["error", "methods", { "avoidQuotes": true }], - "prefer-arrow-callback": "error", - "arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ], - "arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }], - "arrow-spacing": ["error"], - "no-confusing-arrow": ["error", { "allowParens": true }], - - // Enforced coding style - - "brace-style": ["error", "1tbs", { "allowSingleLine": true }], - "indent": ["error", 4, { "SwitchCase": 1, - "CallExpression": { "arguments": "first" }, - "ArrayExpression": "first", - "ObjectExpression": "first", - "ignoreComments": true }], - "comma-spacing": ["error"], - "comma-style": ["error"], - "curly": ["error", "multi-line"], - "func-call-spacing": ["error"], - "func-names": ["error"], - "func-style": ["error", "declaration", { "allowArrowFunctions": true }], - "key-spacing": ["error"], - "keyword-spacing": ["error"], - "no-trailing-spaces": ["error"], - "semi": ["error"], - "space-before-blocks": ["error"], - "space-before-function-paren": ["error", { "anonymous": "always", - "named": "never", - "asyncArrow": "always" }], - "switch-colon-spacing": ["error"], - } -} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 94ac6f8dc..1b377d569 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -7,7 +7,7 @@ about: Create a report to help us improve **Describe the bug** A clear and concise description of what the bug is. -**To Reproduce** +**To reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..cbd35aa75 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Question or discussion + url: https://groups.google.com/forum/?fromgroups#!forum/novnc + about: Ask a question or start a discussion diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..1a18e936d --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,97 @@ +name: Publish + +on: + push: + pull_request: + release: + types: [published] + +jobs: + npm: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v4 + - run: | + GITREV=$(git rev-parse --short HEAD) + echo $GITREV + sed -i "s/^\(.*\"version\".*\)\"\([^\"]\+\)\"\(.*\)\$/\1\"\2-g$GITREV\"\3/" package.json + if: github.event_name != 'release' + - uses: actions/setup-node@v4 + with: + # Node 24 is needed to get npm > 11.5.1, which is a requirement for + # OIDC auth. + node-version: 24 + # Needs to be explicitly specified for auth to work + registry-url: 'https://registry.npmjs.org' + - run: npm install + - uses: actions/upload-artifact@v4 + with: + name: npm + path: lib + - run: npm publish --access public + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'release' && + !github.event.release.prerelease + - run: npm publish --access public --tag beta + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'release' && + github.event.release.prerelease + - run: npm publish --access public --tag dev + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'push' && + github.event.ref == 'refs/heads/master' + snap: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + GITREV=$(git rev-parse --short HEAD) + echo $GITREV + sed -i "s/^\(.*\"version\".*\)\"\([^\"]\+\)\"\(.*\)\$/\1\"\2-g$GITREV\"\3/" package.json + if: github.event_name != 'release' + - run: | + VERSION=$(grep '"version"' package.json | cut -d '"' -f 4) + echo $VERSION + sed -i "s/^version:.*/version: '$VERSION'/" snap/snapcraft.yaml + - uses: snapcore/action-build@v1 + id: snapcraft + - uses: actions/upload-artifact@v4 + with: + name: snap + path: ${{ steps.snapcraft.outputs.snap }} + - uses: snapcore/action-publish@v1 + with: + snap: ${{ steps.snapcraft.outputs.snap }} + release: stable + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }} + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'release' && + !github.event.release.prerelease + - uses: snapcore/action-publish@v1 + with: + snap: ${{ steps.snapcraft.outputs.snap }} + release: beta + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }} + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'release' && + github.event.release.prerelease + - uses: snapcore/action-publish@v1 + with: + snap: ${{ steps.snapcraft.outputs.snap }} + release: edge + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }} + if: | + github.repository == 'novnc/noVNC' && + github.event_name == 'push' && + github.event.ref == 'refs/heads/master' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..540bb9907 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,19 @@ +name: Lint + +on: [push, pull_request] + +jobs: + eslint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm update + - run: npm run lint + html: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm update + - run: git ls-tree --name-only -r HEAD | grep -E "[.](html|css)$" | xargs ./utils/validate diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..b72195b52 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,28 @@ +name: Test + +on: [push, pull_request] + +jobs: + test: + strategy: + matrix: + os: + - ubuntu-latest + - windows-latest + browser: + - ChromeHeadless + - FirefoxHeadless + include: + - os: macos-latest + browser: Safari + - os: windows-latest + browser: EdgeHeadless + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm update + - run: npm run test + env: + TEST_BROWSER_NAME: ${{ matrix.browser }} diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml new file mode 100644 index 000000000..a4da9cbfa --- /dev/null +++ b/.github/workflows/translate.yml @@ -0,0 +1,15 @@ +name: Translate + +on: [push, pull_request] + +jobs: + translate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm update + - run: sudo apt-get install gettext + - run: make -C po update-pot + - run: make -C po update-po + - run: make -C po update-js diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 763bb5bf0..000000000 --- a/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: node_js -sudo: false -cache: - directories: - - node_modules -node_js: - - 6 -env: - matrix: - - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Windows 10' -# FIXME Skip tests in Linux since Sauce Labs browser versions are ancient. -# - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='Linux' - - TEST_BROWSER_NAME=chrome TEST_BROWSER_OS='OS X 10.11' - - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Windows 10' -# - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='Linux' - - TEST_BROWSER_NAME=firefox TEST_BROWSER_OS='OS X 10.11' - - TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 10' - - TEST_BROWSER_NAME='internet explorer' TEST_BROWSER_OS='Windows 7' - - TEST_BROWSER_NAME=microsoftedge TEST_BROWSER_OS='Windows 10' - - TEST_BROWSER_NAME=safari TEST_BROWSER_OS='OS X 10.13' -before_script: npm install -g karma-cli -addons: - sauce_connect: - username: "directxman12" - jwt: - secure: "d3ekMYslpn6R4f0ajtRMt9SUFmNGDiItHpqaXC5T4KI0KMEsxgvEOfJot5PiFFJWg1DSpJZH6oaW2UxGZ3duJLZrXIEd/JePY8a6NtT35BNgiDPgcp+eu2Bu3rhrSNg7/HEsD1ma+JeUTnv18Ai5oMFfCCQJx2J6osIxyl/ZVxA=" -stages: -- lint -- test -- name: deploy - if: tag is PRESENT -jobs: - include: - - stage: lint - env: - addons: - before_script: - script: npm run lint - - - env: - addons: - before_script: - script: git ls-tree --name-only -r HEAD | grep -E "[.](html|css)$" | xargs ./utils/validate - - stage: deploy - env: - addons: - script: skip - before_script: skip - deploy: - provider: npm - skip_cleanup: true - email: ossman@cendio.se - api_key: - secure: "Qq2Mi9xQawO2zlAigzshzMu2QMHvu1IaN9l0ZIivE99wHJj7eS5f4miJ9wB+/mWRRgb3E8uj9ZRV24+Oc36drlBTU9sz+lHhH0uFMfAIseceK64wZV9sLAZm472fmPp2xdUeTCCqPaRy7g1XBqiJ0LyZvEFLsRijqcLjPBF+b8w=" - on: - tags: true - repo: novnc/noVNC - - diff --git a/AUTHORS b/AUTHORS index dec0e8932..e8fb12404 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,9 +1,9 @@ maintainers: -- Joel Martin (@kanaka) -- Solly Ross (@directxman12) - Samuel Mannehed for Cendio AB (@samhed) - Pierre Ossman for Cendio AB (@CendioOssman) maintainersEmeritus: +- Joel Martin (@kanaka) +- Solly Ross (@directxman12) - @astrand contributors: # There are a bunch of people that should be here. diff --git a/LICENSE.txt b/LICENSE.txt index 20f3eb025..0581c11ed 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -noVNC is Copyright (C) 2018 The noVNC Authors +noVNC is Copyright (C) 2022 The noVNC authors (./AUTHORS) The noVNC core library files are licensed under the MPL 2.0 (Mozilla @@ -42,12 +42,6 @@ licenses (all MPL 2.0 compatible): vendor/pako/ : MIT - vendor/browser-es-module-loader/src/ : MIT - - vendor/browser-es-module-loader/dist/ : Various BSD style licenses - - vendor/promise.js : MIT - Any other files not mentioned above are typically marked with a copyright/license header at the top of the file. The default noVNC license is MPL-2.0. diff --git a/README.md b/README.md index 566b8e4f5..3c831be6f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -## noVNC: HTML VNC Client Library and Application +## noVNC: HTML VNC client library and application -[![Build Status](https://travis-ci.org/novnc/noVNC.svg?branch=master)](https://travis-ci.org/novnc/noVNC) +[![Test Status](https://github.com/novnc/noVNC/workflows/Test/badge.svg)](https://github.com/novnc/noVNC/actions?query=workflow%3ATest) +[![Lint Status](https://github.com/novnc/noVNC/workflows/Lint/badge.svg)](https://github.com/novnc/noVNC/actions?query=workflow%3ALint) ### Description @@ -13,25 +14,24 @@ Many companies, projects and products have integrated noVNC including [OpenNebula](http://opennebula.org/), [LibVNCServer](http://libvncserver.sourceforge.net), and [ThinLinc](https://cendio.com/thinlinc). See -[the Projects and Companies wiki page](https://github.com/novnc/noVNC/wiki/Projects-and-companies-using-noVNC) +[the Projects and companies wiki page](https://github.com/novnc/noVNC/wiki/Projects-and-companies-using-noVNC) for a more complete list with additional info and links. -### Table of Contents +### Table of contents - [News/help/contact](#newshelpcontact) - [Features](#features) - [Screenshots](#screenshots) -- [Browser Requirements](#browser-requirements) -- [Server Requirements](#server-requirements) -- [Quick Start](#quick-start) -- [Integration and Deployment](#integration-and-deployment) +- [Browser requirements](#browser-requirements) +- [Server requirements](#server-requirements) +- [Quick start](#quick-start) +- [Installation from snap package](#installation-from-snap-package) +- [Integration and deployment](#integration-and-deployment) - [Authors/Contributors](#authorscontributors) ### News/help/contact The project website is found at [novnc.com](http://novnc.com). -Notable commits, announcements and news are posted to -[@noVNC](http://www.twitter.com/noVNC). If you are a noVNC developer/integrator/user (or want to be) please join the [noVNC discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc). @@ -57,17 +57,22 @@ profits such as: [Electronic Frontier Foundation](https://www.eff.org/), [Against Malaria Foundation](http://www.againstmalaria.com/), [Nothing But Nets](http://www.nothingbutnets.net/), etc. -Please tweet [@noVNC](http://www.twitter.com/noVNC) if you do. ### Features * Supports all modern browsers including mobile (iOS, Android) -* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG +* Supported authentication methods: none, classical VNC, RealVNC's + RSA-AES, Tight, VeNCrypt Plain, XVP, Apple's Diffie-Hellman, + UltraVNC's MSLogonII +* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG, + ZRLE, JPEG, Zlib, H.264 * Supports scaling, clipping and resizing the desktop +* Supports back & forward mouse buttons * Local cursor rendering -* Clipboard copy/paste +* Clipboard copy/paste with full Unicode support * Translations +* Touch gestures for emulating common mouse actions * Licensed mainly under the [MPL 2.0](http://www.mozilla.org/MPL/2.0/), see [the license document](LICENSE.txt) for details @@ -82,16 +87,16 @@ See more screenshots [here](http://novnc.com/screenshots.html). -### Browser Requirements +### Browser requirements noVNC uses many modern web technologies so a formal requirement list is not available. However these are the minimum versions we are currently aware of: -* Chrome 49, Firefox 44, Safari 10, Opera 36, IE 11, Edge 12 +* Chrome 89, Firefox 89, Safari 15, Opera 75, Edge 89 -### Server Requirements +### Server requirements noVNC follows the standard VNC protocol, but unlike other VNC clients it does require WebSockets support. Many servers include support (e.g. @@ -103,20 +108,89 @@ use a WebSockets to TCP socket proxy. noVNC has a sister project proxy. -### Quick Start +### Quick start -* Use the launch script to automatically download and start websockify, which +* Use the `novnc_proxy` script to automatically download and start websockify, which includes a mini-webserver and the WebSockets proxy. The `--vnc` option is used to specify the location of a running VNC server: - `./utils/launch.sh --vnc localhost:5901` + `./utils/novnc_proxy --vnc localhost:5901` + +* If you don't need to expose the web server to public internet, you can + bind to localhost: + + `./utils/novnc_proxy --vnc localhost:5901 --listen localhost:6081` -* Point your browser to the cut-and-paste URL that is output by the launch +* Point your browser to the cut-and-paste URL that is output by the `novnc_proxy` script. Hit the Connect button, enter a password if the VNC server has one configured, and enjoy! +### Installation from snap package +Running the command below will install the latest release of noVNC from snap: -### Integration and Deployment +`sudo snap install novnc` + +#### Running noVNC from snap directly + +You can run the snap package installed novnc directly with, for example: + +`novnc --listen 6081 --vnc localhost:5901 # /snap/bin/novnc if /snap/bin is not in your PATH` + +If you want to use certificate files, due to standard snap confinement restrictions you need to have them in the /home/\/snap/novnc/current/ directory. If your username is jsmith an example command would be: + + `novnc --listen 8443 --cert ~jsmith/snap/novnc/current/self.crt --key ~jsmith/snap/novnc/current/self.key --vnc ubuntu.example.com:5901` + +#### Running noVNC from snap as a service (daemon) +The snap package also has the capability to run a 'novnc' service which can be +configured to listen on multiple ports connecting to multiple VNC servers +(effectively a service running multiple instances of novnc). +Instructions (with example values): + +List current services (out-of-box this will be blank): + +``` +sudo snap get novnc services +Key Value +services.n6080 {...} +services.n6081 {...} +``` + +Create a new service that listens on port 6082 and connects to the VNC server +running on port 5902 on localhost: + +`sudo snap set novnc services.n6082.listen=6082 services.n6082.vnc=localhost:5902` + +(Any services you define with 'snap set' will be automatically started) +Note that the name of the service, 'n6082' in this example, can be anything +as long as it doesn't start with a number or contain spaces/special characters. + +View the configuration of the service just created: + +``` +sudo snap get novnc services.n6082 +Key Value +services.n6082.listen 6082 +services.n6082.vnc localhost:5902 +``` + +Disable a service (note that because of a limitation in snap it's currently not +possible to unset config variables, setting them to blank values is the way +to disable a service): + +`sudo snap set novnc services.n6082.listen='' services.n6082.vnc=''` + +(Any services you set to blank with 'snap set' like this will be automatically stopped) + +Verify that the service is disabled (blank values): + +``` +sudo snap get novnc services.n6082 +Key Value +services.n6082.listen +services.n6082.vnc +``` + +### Integration and deployment Please see our other documents for how to integrate noVNC in your own software, or deploying the noVNC application in production environments: @@ -131,16 +205,18 @@ See [AUTHORS](AUTHORS) for a (full-ish) list of authors. If you're not on that list and you think you should be, feel free to send a PR to fix that. * Core team: - * [Joel Martin](https://github.com/kanaka) * [Samuel Mannehed](https://github.com/samhed) (Cendio) - * [Peter Åstrand](https://github.com/astrand) (Cendio) - * [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack) * [Pierre Ossman](https://github.com/CendioOssman) (Cendio) +* Previous core contributors: + * [Joel Martin](https://github.com/kanaka) (Project founder) + * [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack) + * Notable contributions: - * UI and Icons : Pierre Ossman, Chris Gordon - * Original Logo : Michael Sersen + * UI and icons : Pierre Ossman, Chris Gordon + * Original logo : Michael Sersen * tight encoding : Michael Tinglof (Mercuri.ca) + * RealVNC RSA AES authentication : USTC Vlab Team * Included libraries: * base64 : Martijn Pieters (Digital Creations 2), Samuel Sieb (sieb.net) diff --git a/VERSION b/VERSION deleted file mode 100644 index 9084fa2f7..000000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.1.0 diff --git a/app/error-handler.js b/app/error-handler.js index 8e294166f..ef1cb64c7 100644 --- a/app/error-handler.js +++ b/app/error-handler.js @@ -1,58 +1,79 @@ -// NB: this should *not* be included as a module until we have -// native support in the browsers, so that our error handler -// can catch script-loading errors. +/* + * 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. + */ -// No ES6 can be used in this file since it's used for the translation -/* eslint-disable prefer-arrow-callback */ +// Fallback for all uncaught errors +function handleError(event, err) { + try { + const msg = document.getElementById('noVNC_fallback_errormsg'); -(function _scope() { - "use strict"; + // 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; + } - // Fallback for all uncought errors - function handleError(event, err) { - try { - const msg = document.getElementById('noVNC_fallback_errormsg'); + let div = document.createElement("div"); + div.classList.add('noVNC_message'); + div.appendChild(document.createTextNode(event.message)); + msg.appendChild(div); - // Only show the initial error - if (msg.hasChildNodes()) { - return false; + 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); + } - let div = document.createElement("div"); - div.classList.add('noVNC_message'); - div.appendChild(document.createTextNode(event.message)); + if (err && err.stack) { + div = document.createElement("div"); + div.className = 'noVNC_stack'; + div.appendChild(document.createTextNode(err.stack)); 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); - } + document.getElementById('noVNC_fallback_error') + .classList.add("noVNC_open"); - if (err && err.stack) { - div = document.createElement("div"); - div.className = 'noVNC_stack'; - div.appendChild(document.createTextNode(err.stack)); - msg.appendChild(div); - } + } catch (exc) { + document.write("noVNC encountered an error."); + } - document.getElementById('noVNC_fallback_error') - .classList.add("noVNC_open"); - } catch (exc) { - document.write("noVNC encountered an error."); - } - // Don't return true since this would prevent the error - // from being printed to the browser console. - return false; + // 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 } - window.addEventListener('error', function onerror(evt) { handleError(evt, evt.error); }); - window.addEventListener('unhandledrejection', function onreject(evt) { handleError(evt.reason, evt.reason); }); -})(); + + // 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/app/images/icons/Makefile b/app/images/icons/Makefile index be564b43b..03eaed071 100644 --- a/app/images/icons/Makefile +++ b/app/images/icons/Makefile @@ -1,42 +1,42 @@ -ICONS := \ - novnc-16x16.png \ - novnc-24x24.png \ - novnc-32x32.png \ - novnc-48x48.png \ - novnc-64x64.png - -ANDROID_LAUNCHER := \ - novnc-48x48.png \ - novnc-72x72.png \ - novnc-96x96.png \ - novnc-144x144.png \ - novnc-192x192.png - -IPHONE_LAUNCHER := \ - novnc-60x60.png \ - novnc-120x120.png - -IPAD_LAUNCHER := \ - novnc-76x76.png \ - novnc-152x152.png - -ALL_ICONS := $(ICONS) $(ANDROID_LAUNCHER) $(IPHONE_LAUNCHER) $(IPAD_LAUNCHER) +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) -novnc-16x16.png: novnc-icon-sm.svg - convert -density 90 \ - -background transparent "$<" "$@" -novnc-24x24.png: novnc-icon-sm.svg - convert -density 135 \ - -background transparent "$<" "$@" -novnc-32x32.png: novnc-icon-sm.svg - convert -density 180 \ - -background transparent "$<" "$@" +# 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 -density $$[`echo $* | cut -d x -f 1` * 90 / 48] \ - -background transparent "$<" "$@" + 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/app/images/icons/novnc-120x120.png b/app/images/icons/novnc-120x120.png deleted file mode 100644 index 40823efba..000000000 Binary files a/app/images/icons/novnc-120x120.png and /dev/null differ diff --git a/app/images/icons/novnc-144x144.png b/app/images/icons/novnc-144x144.png deleted file mode 100644 index eee71f11c..000000000 Binary files a/app/images/icons/novnc-144x144.png and /dev/null differ diff --git a/app/images/icons/novnc-152x152.png b/app/images/icons/novnc-152x152.png deleted file mode 100644 index 0694b2de3..000000000 Binary files a/app/images/icons/novnc-152x152.png and /dev/null differ diff --git a/app/images/icons/novnc-16x16.png b/app/images/icons/novnc-16x16.png deleted file mode 100644 index 42108f409..000000000 Binary files a/app/images/icons/novnc-16x16.png and /dev/null differ diff --git a/app/images/icons/novnc-192x192.png b/app/images/icons/novnc-192x192.png deleted file mode 100644 index ef9201f43..000000000 Binary files a/app/images/icons/novnc-192x192.png and /dev/null differ diff --git a/app/images/icons/novnc-24x24.png b/app/images/icons/novnc-24x24.png deleted file mode 100644 index 110613594..000000000 Binary files a/app/images/icons/novnc-24x24.png and /dev/null differ diff --git a/app/images/icons/novnc-32x32.png b/app/images/icons/novnc-32x32.png deleted file mode 100644 index ff00dc305..000000000 Binary files a/app/images/icons/novnc-32x32.png and /dev/null differ diff --git a/app/images/icons/novnc-48x48.png b/app/images/icons/novnc-48x48.png deleted file mode 100644 index f24cd6cc9..000000000 Binary files a/app/images/icons/novnc-48x48.png and /dev/null differ diff --git a/app/images/icons/novnc-60x60.png b/app/images/icons/novnc-60x60.png deleted file mode 100644 index 06b0d609a..000000000 Binary files a/app/images/icons/novnc-60x60.png and /dev/null differ diff --git a/app/images/icons/novnc-64x64.png b/app/images/icons/novnc-64x64.png deleted file mode 100644 index 6d0fb3418..000000000 Binary files a/app/images/icons/novnc-64x64.png and /dev/null differ diff --git a/app/images/icons/novnc-72x72.png b/app/images/icons/novnc-72x72.png deleted file mode 100644 index 23163a22d..000000000 Binary files a/app/images/icons/novnc-72x72.png and /dev/null differ diff --git a/app/images/icons/novnc-76x76.png b/app/images/icons/novnc-76x76.png deleted file mode 100644 index aef61c480..000000000 Binary files a/app/images/icons/novnc-76x76.png and /dev/null differ diff --git a/app/images/icons/novnc-96x96.png b/app/images/icons/novnc-96x96.png deleted file mode 100644 index 1a77c53f4..000000000 Binary files a/app/images/icons/novnc-96x96.png and /dev/null differ diff --git a/app/images/icons/novnc-ios-120.png b/app/images/icons/novnc-ios-120.png new file mode 100644 index 000000000..8da7bab3d Binary files /dev/null and b/app/images/icons/novnc-ios-120.png differ diff --git a/app/images/icons/novnc-ios-152.png b/app/images/icons/novnc-ios-152.png new file mode 100644 index 000000000..60b2bcef5 Binary files /dev/null and b/app/images/icons/novnc-ios-152.png differ diff --git a/app/images/icons/novnc-ios-167.png b/app/images/icons/novnc-ios-167.png new file mode 100644 index 000000000..98fade2e2 Binary files /dev/null and b/app/images/icons/novnc-ios-167.png differ diff --git a/app/images/icons/novnc-ios-180.png b/app/images/icons/novnc-ios-180.png new file mode 100644 index 000000000..5d24df70a Binary files /dev/null and b/app/images/icons/novnc-ios-180.png differ diff --git a/app/images/icons/novnc-ios-40.png b/app/images/icons/novnc-ios-40.png new file mode 100644 index 000000000..cf14894da Binary files /dev/null and b/app/images/icons/novnc-ios-40.png differ diff --git a/app/images/icons/novnc-ios-58.png b/app/images/icons/novnc-ios-58.png new file mode 100644 index 000000000..f6dfbebd2 Binary files /dev/null and b/app/images/icons/novnc-ios-58.png differ diff --git a/app/images/icons/novnc-ios-60.png b/app/images/icons/novnc-ios-60.png new file mode 100644 index 000000000..8cda29530 Binary files /dev/null and b/app/images/icons/novnc-ios-60.png differ diff --git a/app/images/icons/novnc-ios-80.png b/app/images/icons/novnc-ios-80.png new file mode 100644 index 000000000..6c417c47e Binary files /dev/null and b/app/images/icons/novnc-ios-80.png differ diff --git a/app/images/icons/novnc-ios-87.png b/app/images/icons/novnc-ios-87.png new file mode 100644 index 000000000..4377d874b Binary files /dev/null and b/app/images/icons/novnc-ios-87.png differ diff --git a/app/images/icons/novnc-ios-icon.svg b/app/images/icons/novnc-ios-icon.svg new file mode 100644 index 000000000..009452ac6 --- /dev/null +++ b/app/images/icons/novnc-ios-icon.svg @@ -0,0 +1,183 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/images/icons/novnc.ico b/app/images/icons/novnc.ico new file mode 100644 index 000000000..c3bc58e38 Binary files /dev/null and b/app/images/icons/novnc.ico differ diff --git a/app/images/mouse_left.svg b/app/images/mouse_left.svg deleted file mode 100644 index ce4cca41c..000000000 --- a/app/images/mouse_left.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/app/images/mouse_middle.svg b/app/images/mouse_middle.svg deleted file mode 100644 index 6603425cb..000000000 --- a/app/images/mouse_middle.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/app/images/mouse_none.svg b/app/images/mouse_none.svg deleted file mode 100644 index 3e0f838a7..000000000 --- a/app/images/mouse_none.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/app/images/mouse_right.svg b/app/images/mouse_right.svg deleted file mode 100644 index f4bad7679..000000000 --- a/app/images/mouse_right.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - diff --git a/app/images/windows.svg b/app/images/windows.svg index 270405c7f..ad5eec36e 100644 --- a/app/images/windows.svg +++ b/app/images/windows.svg @@ -15,18 +15,18 @@ inkscape:export-xdpi="90" sodipodi:docname="windows.svg" inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png" - inkscape:version="0.92.3 (2405546, 2018-03-11)" + inkscape:version="0.92.4 (unknown)" x="0px" y="0px" - viewBox="-293 384 25 23" + viewBox="-293 384 25 25" xml:space="preserve" width="25" - height="23">image/svg+xml + inkscape:current-layer="svg2"> - - - - - - - - - \ No newline at end of file + + \ No newline at end of file diff --git a/app/locale/README b/app/locale/README new file mode 100644 index 000000000..ca4f548bc --- /dev/null +++ b/app/locale/README @@ -0,0 +1 @@ +DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES. diff --git a/app/locale/cs.json b/app/locale/cs.json index 589145ef3..dd31e6c18 100644 --- a/app/locale/cs.json +++ b/app/locale/cs.json @@ -14,7 +14,7 @@ "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", + "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é", @@ -22,9 +22,9 @@ "Middle mousebutton": "Prostřední tlačítko myši", "Right mousebutton": "Pravé tlačítko myši", "Keyboard": "Klávesnice", - "Show Keyboard": "Zobrazit klávesnici", + "Show keyboard": "Zobrazit klávesnici", "Extra keys": "Extra klávesy", - "Show Extra Keys": "Zobrazit extra klávesy", + "Show extra keys": "Zobrazit extra klávesy", "Ctrl": "Ctrl", "Toggle Ctrl": "Přepnout Ctrl", "Alt": "Alt", @@ -45,13 +45,13 @@ "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", + "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é", + "Local scaling": "Místní", + "Remote resizing": "Vzdálené", "Advanced": "Pokročilé", "Repeater ID:": "ID opakovače", "WebSocket": "WebSocket", @@ -59,9 +59,9 @@ "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", + "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", diff --git a/app/locale/de.json b/app/locale/de.json index 62e73360f..fa1546377 100644 --- a/app/locale/de.json +++ b/app/locale/de.json @@ -13,7 +13,7 @@ "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", + "Move/Drag viewport": "Ansichtsfenster verschieben/ziehen", "viewport drag": "Ansichtsfenster ziehen", "Active Mouse Button": "Aktive Maustaste", "No mousebutton": "Keine Maustaste", @@ -21,9 +21,9 @@ "Middle mousebutton": "Mittlere Maustaste", "Right mousebutton": "Rechte Maustaste", "Keyboard": "Tastatur", - "Show Keyboard": "Tastatur anzeigen", + "Show keyboard": "Tastatur anzeigen", "Extra keys": "Zusatztasten", - "Show Extra Keys": "Zusatztasten anzeigen", + "Show extra keys": "Zusatztasten anzeigen", "Ctrl": "Strg", "Toggle Ctrl": "Strg umschalten", "Alt": "Alt", @@ -44,13 +44,13 @@ "Clear": "Löschen", "Fullscreen": "Vollbild", "Settings": "Einstellungen", - "Shared Mode": "Geteilter Modus", - "View Only": "Nur betrachten", - "Clip to Window": "Auf Fenster begrenzen", - "Scaling Mode:": "Skalierungsmodus:", + "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", + "Local scaling": "Lokales skalieren", + "Remote resizing": "Serverseitiges skalieren", "Advanced": "Erweitert", "Repeater ID:": "Repeater ID:", "WebSocket": "WebSocket", @@ -58,12 +58,17 @@ "Host:": "Server:", "Port:": "Port:", "Path:": "Pfad:", - "Automatic Reconnect": "Automatisch wiederverbinden", - "Reconnect Delay (ms):": "Wiederverbindungsverzögerung (ms):", + "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." + "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/app/locale/el.json b/app/locale/el.json index f801251c5..57d67316c 100644 --- a/app/locale/el.json +++ b/app/locale/el.json @@ -1,4 +1,5 @@ { + "HTTPS is required for full functionality": "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα", "Connecting...": "Συνδέεται...", "Disconnecting...": "Aποσυνδέεται...", "Reconnecting...": "Επανασυνδέεται...", @@ -7,19 +8,15 @@ "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": "Απαιτείται ο κωδικός πρόσβασης", + "Credentials are required": "Απαιτούνται διαπιστευτήρια", "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:", "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου", + "Drag": "Σύρσιμο", "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου", - "viewport drag": "σύρσιμο θεατού πεδίου", - "Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού", - "No mousebutton": "Χωρίς Πλήκτρο Ποντικιού", - "Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού", - "Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού", - "Right mousebutton": "Δεξί Πλήκτρο Ποντικιού", "Keyboard": "Πληκτρολόγιο", "Show Keyboard": "Εμφάνιση Πληκτρολογίου", "Extra keys": "Επιπλέον πλήκτρα", @@ -28,6 +25,8 @@ "Toggle Ctrl": "Εναλλαγή Ctrl", "Alt": "Alt", "Toggle Alt": "Εναλλαγή Alt", + "Toggle Windows": "Εναλλαγή Παράθυρων", + "Windows": "Παράθυρα", "Send Tab": "Αποστολή Tab", "Tab": "Tab", "Esc": "Esc", @@ -41,8 +40,8 @@ "Reboot": "Επανεκκίνηση", "Reset": "Επαναφορά", "Clipboard": "Πρόχειρο", - "Clear": "Καθάρισμα", - "Fullscreen": "Πλήρης Οθόνη", + "Edit clipboard content in the textarea below.": "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω.", + "Full Screen": "Πλήρης Οθόνη", "Settings": "Ρυθμίσεις", "Shared Mode": "Κοινόχρηστη Λειτουργία", "View Only": "Μόνο Θέαση", @@ -52,6 +51,8 @@ "Local Scaling": "Τοπική Κλιμάκωση", "Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους", "Advanced": "Για προχωρημένους", + "Quality:": "Ποιότητα:", + "Compression level:": "Επίπεδο συμπίεσης:", "Repeater ID:": "Repeater ID:", "WebSocket": "WebSocket", "Encrypt": "Κρυπτογράφηση", @@ -60,10 +61,40 @@ "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": "Ακύρωση", - "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas" + "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/app/locale/es.json b/app/locale/es.json index 23f23f497..bb088243c 100644 --- a/app/locale/es.json +++ b/app/locale/es.json @@ -4,13 +4,13 @@ "Connected (unencrypted) to ": "Conectado (sin encriptación) a", "Disconnecting...": "Desconectando...", "Disconnected": "Desconectado", - "Must set host": "Debes configurar el host", + "Must set host": "Se debe configurar el host", "Reconnecting...": "Reconectando...", - "Password is required": "Contraseña es obligatoria", + "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", + "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", @@ -18,7 +18,7 @@ "Middle mousebutton": "Botón central del ratón", "Right mousebutton": "Botón derecho del ratón", "Keyboard": "Teclado", - "Show Keyboard": "Mostrar teclado", + "Show keyboard": "Mostrar teclado", "Extra keys": "Teclas adicionales", "Show Extra Keys": "Mostrar Teclas Adicionales", "Ctrl": "Ctrl", @@ -41,28 +41,28 @@ "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:", + "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", + "Remote resizing": "Cambio de tamaño remoto", "Advanced": "Avanzado", "Local Cursor": "Cursor Local", - "Repeater ID:": "ID del Repetidor", + "Repeater ID:": "ID del Repetidor:", "WebSocket": "WebSocket", - "Encrypt": "", - "Host:": "Host", - "Port:": "Puesto", - "Path:": "Ruta", - "Automatic Reconnect": "Reconexión automática", - "Reconnect Delay (ms):": "Retraso en la reconexión (ms)", - "Logging:": "Logging", + "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", + "Password:": "Contraseña:", "Cancel": "Cancelar", - "Canvas not supported.": "Canvas no está soportado" + "Canvas not supported.": "Canvas no soportado." } \ No newline at end of file diff --git a/app/locale/fr.json b/app/locale/fr.json new file mode 100644 index 000000000..c8607cebe --- /dev/null +++ b/app/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/app/locale/hu.json b/app/locale/hu.json new file mode 100644 index 000000000..ba700b5fd --- /dev/null +++ b/app/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/app/locale/it.json b/app/locale/it.json new file mode 100644 index 000000000..28e6f721b --- /dev/null +++ b/app/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/app/locale/ja.json b/app/locale/ja.json index e5fe3401f..4fc9b8a9e 100644 --- a/app/locale/ja.json +++ b/app/locale/ja.json @@ -1,35 +1,32 @@ { + "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": "何かが問題で、接続が閉じられました", + "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": "パスワードが必要です", + "Credentials are 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": "右マウスボタン", + "Drag": "ドラッグ", + "Move/Drag viewport": "ビューポートを移動/ドラッグ", "Keyboard": "キーボード", - "Show Keyboard": "キーボードを表示", + "Show keyboard": "キーボードを表示", "Extra keys": "追加キー", - "Show Extra Keys": "追加キーを表示", + "Show extra keys": "追加キーを表示", "Ctrl": "Ctrl", - "Toggle Ctrl": "Ctrl キーを切り替え", + "Toggle Ctrl": "Ctrl キーをトグル", "Alt": "Alt", - "Toggle Alt": "Alt キーを切り替え", - "Toggle Windows": "Windows キーを切り替え", + "Toggle Alt": "Alt キーをトグル", + "Toggle Windows": "Windows キーをトグル", "Windows": "Windows", "Send Tab": "Tab キーを送信", "Tab": "Tab", @@ -44,30 +41,41 @@ "Reboot": "再起動", "Reset": "リセット", "Clipboard": "クリップボード", - "Clear": "クリア", - "Fullscreen": "全画面表示", + "Edit clipboard content in the textarea below.": "以下の入力欄からクリップボードの内容を編集できます。", + "Full screen": "全画面表示", "Settings": "設定", - "Shared Mode": "共有モード", - "View Only": "表示のみ", - "Clip to Window": "ウィンドウにクリップ", - "Scaling Mode:": "スケーリングモード:", + "Shared mode": "共有モード", + "View only": "表示専用", + "Clip to window": "ウィンドウにクリップ", + "Scaling mode:": "スケーリングモード:", "None": "なし", - "Local Scaling": "ローカルスケーリング", - "Remote Resizing": "リモートでリサイズ", + "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": "カーソルがないときにドットを表示", + "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 Password": "パスワードを送信", + "Send credentials": "資格情報を送信", "Cancel": "キャンセル" } \ No newline at end of file diff --git a/app/locale/ko.json b/app/locale/ko.json index e4ecddcfd..47b0805c9 100644 --- a/app/locale/ko.json +++ b/app/locale/ko.json @@ -14,7 +14,7 @@ "Password is required": "비밀번호가 필요합니다.", "noVNC encountered an error:": "noVNC에 오류가 발생했습니다:", "Hide/Show the control bar": "컨트롤 바 숨기기/보이기", - "Move/Drag Viewport": "움직이기/드래그 뷰포트", + "Move/Drag viewport": "움직이기/드래그 뷰포트", "viewport drag": "뷰포트 드래그", "Active Mouse Button": "마우스 버튼 활성화", "No mousebutton": "마우스 버튼 없음", @@ -22,9 +22,9 @@ "Middle mousebutton": "중간 마우스 버튼", "Right mousebutton": "오른쪽 마우스 버튼", "Keyboard": "키보드", - "Show Keyboard": "키보드 보이기", + "Show keyboard": "키보드 보이기", "Extra keys": "기타 키들", - "Show Extra Keys": "기타 키들 보이기", + "Show extra keys": "기타 키들 보이기", "Ctrl": "Ctrl", "Toggle Ctrl": "Ctrl 켜기/끄기", "Alt": "Alt", @@ -45,13 +45,13 @@ "Clear": "지우기", "Fullscreen": "전체화면", "Settings": "설정", - "Shared Mode": "공유 모드", - "View Only": "보기 전용", - "Clip to Window": "창에 클립", - "Scaling Mode:": "스케일링 모드:", + "Shared mode": "공유 모드", + "View only": "보기 전용", + "Clip to window": "창에 클립", + "Scaling mode:": "스케일링 모드:", "None": "없음", - "Local Scaling": "로컬 스케일링", - "Remote Resizing": "원격 크기 조절", + "Local scaling": "로컬 스케일링", + "Remote resizing": "원격 크기 조절", "Advanced": "고급", "Repeater ID:": "중계 ID", "WebSocket": "웹소켓", @@ -59,8 +59,8 @@ "Host:": "호스트:", "Port:": "포트:", "Path:": "위치:", - "Automatic Reconnect": "자동 재연결", - "Reconnect Delay (ms):": "재연결 지연 시간 (ms)", + "Automatic reconnect": "자동 재연결", + "Reconnect delay (ms):": "재연결 지연 시간 (ms)", "Logging:": "로깅", "Disconnect": "연결 해제", "Connect": "연결", diff --git a/app/locale/nl.json b/app/locale/nl.json index 0cdcc92a9..61f2df3c7 100644 --- a/app/locale/nl.json +++ b/app/locale/nl.json @@ -1,36 +1,32 @@ { - "Connecting...": "Verbinden...", - "Disconnecting...": "Verbinding verbreken...", + "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", - "Must set host": "Host moeten worden ingesteld", + "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 omwille van de volgende reden: ", + "New connection has been rejected with reason: ": "Nieuwe verbinding is geweigerd met de volgende reden: ", "New connection has been rejected": "Nieuwe verbinding is geweigerd", - "Password is required": "Wachtwoord is vereist", + "Credentials are required": "Inloggegevens zijn nodig", "noVNC encountered an error:": "noVNC heeft een fout bemerkt:", "Hide/Show the control bar": "Verberg/Toon de bedieningsbalk", - "Move/Drag Viewport": "Verplaats/Versleep Kijkvenster", - "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", + "Drag": "Sleep", + "Move/Drag viewport": "Verplaats/Versleep Kijkvenster", "Keyboard": "Toetsenbord", - "Show Keyboard": "Toon Toetsenbord", + "Show keyboard": "Toon Toetsenbord", "Extra keys": "Extra toetsen", - "Show Extra Keys": "Toon Extra Toetsen", + "Show extra keys": "Toon Extra Toetsen", "Ctrl": "Ctrl", "Toggle Ctrl": "Ctrl omschakelen", "Alt": "Alt", "Toggle Alt": "Alt omschakelen", - "Toggle Windows": "Windows omschakelen", - "Windows": "Windows", + "Toggle Windows": "Vensters omschakelen", + "Windows": "Vensters", "Send Tab": "Tab Sturen", "Tab": "Tab", "Esc": "Esc", @@ -44,30 +40,56 @@ "Reboot": "Herstarten", "Reset": "Resetten", "Clipboard": "Klembord", - "Clear": "Wissen", - "Fullscreen": "Volledig Scherm", + "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:", + "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", + "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", + "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:", - "Cancel": "Annuleren" + "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/app/locale/pl.json b/app/locale/pl.json index 006ac7a55..87c169056 100644 --- a/app/locale/pl.json +++ b/app/locale/pl.json @@ -21,9 +21,9 @@ "Middle mousebutton": "Środkowy przycisk myszy", "Right mousebutton": "Prawy przycisk myszy", "Keyboard": "Klawiatura", - "Show Keyboard": "Pokaż klawiaturę", + "Show keyboard": "Pokaż klawiaturę", "Extra keys": "Przyciski dodatkowe", - "Show Extra Keys": "Pokaż przyciski dodatkowe", + "Show extra keys": "Pokaż przyciski dodatkowe", "Ctrl": "Ctrl", "Toggle Ctrl": "Przełącz Ctrl", "Alt": "Alt", @@ -49,8 +49,8 @@ "Clip to Window": "Przytnij do Okna", "Scaling Mode:": "Tryb Skalowania:", "None": "Brak", - "Local Scaling": "Skalowanie lokalne", - "Remote Resizing": "Skalowanie zdalne", + "Local scaling": "Skalowanie lokalne", + "Remote resizing": "Skalowanie zdalne", "Advanced": "Zaawansowane", "Repeater ID:": "ID Repeatera:", "WebSocket": "WebSocket", @@ -58,12 +58,23 @@ "Host:": "Host:", "Port:": "Port:", "Path:": "Ścieżka:", - "Automatic Reconnect": "Automatycznie wznawiaj połączenie", - "Reconnect Delay (ms):": "Opóźnienie wznawiania (ms):", + "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." + "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/app/locale/pt_BR.json b/app/locale/pt_BR.json new file mode 100644 index 000000000..9c2f7cec7 --- /dev/null +++ b/app/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/app/locale/ru.json b/app/locale/ru.json index 52e57f37f..bd1bb534a 100644 --- a/app/locale/ru.json +++ b/app/locale/ru.json @@ -9,27 +9,22 @@ "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": "Требуется пароль", + "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": "Скрыть/Показать контрольную панель", - "Move/Drag Viewport": "Переместить окно", - "viewport drag": "Переместить окно", - "Active Mouse Button": "Активировать кнопки мыши", - "No mousebutton": "Отключить кнопки мыши", - "Left mousebutton": "Левая кнопка мыши", - "Middle mousebutton": "Средняя кнопка мыши", - "Right mousebutton": "Правая кнопка мыши", + "Drag": "Переместить", + "Move/Drag viewport": "Переместить окно", "Keyboard": "Клавиатура", - "Show Keyboard": "Показать клавиатуру", - "Extra keys": "Доп. кнопки", - "Show Extra Keys": "Показать дополнительные кнопки", + "Show keyboard": "Показать клавиатуру", + "Extra keys": "Дополнительные Кнопки", + "Show Extra Keys": "Показать Дополнительные Кнопки", "Ctrl": "Ctrl", - "Toggle Ctrl": "Передать нажатие Ctrl", + "Toggle Ctrl": "Зажать Ctrl", "Alt": "Alt", - "Toggle Alt": "Передать нажатие Alt", - "Toggle Windows": "Переключение вкладок", + "Toggle Alt": "Зажать Alt", + "Toggle Windows": "Зажать Windows", "Windows": "Вкладка", "Send Tab": "Передать нажатие Tab", "Tab": "Tab", @@ -47,27 +42,31 @@ "Clear": "Очистить", "Fullscreen": "Во весь экран", "Settings": "Настройки", - "Shared Mode": "Общий режим", - "View Only": "Просмотр", - "Clip to Window": "В окно", - "Scaling Mode:": "Масштаб:", + "Shared mode": "Общий режим", + "View Only": "Только Просмотр", + "Clip to window": "В окно", + "Scaling mode:": "Масштаб:", "None": "Нет", - "Local Scaling": "Локльный масштаб", - "Remote Resizing": "Удаленный масштаб", + "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": "Показать точку вместо курсора", + "Automatic reconnect": "Автоматическое переподключение", + "Reconnect delay (ms):": "Задержка переподключения (мс):", + "Show dot when no cursor": "Показать точку вместо курсора", "Logging:": "Лог:", + "Version:": "Версия", "Disconnect": "Отключение", "Connect": "Подключение", + "Username:": "Имя Пользователя", "Password:": "Пароль:", - "Send Password": "Пароль: ", + "Send Credentials": "Передача Учетных Данных", "Cancel": "Выход" } \ No newline at end of file diff --git a/app/locale/sv.json b/app/locale/sv.json index d49ea540d..67f6675aa 100644 --- a/app/locale/sv.json +++ b/app/locale/sv.json @@ -1,9 +1,10 @@ { + "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", - "Must set host": "Du måste specifiera en värd", + "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", @@ -11,20 +12,15 @@ "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", - "Password is required": "Lösenord krävs", + "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", - "Move/Drag Viewport": "Flytta/Dra Vyn", - "viewport drag": "dra vy", - "Active Mouse Button": "Aktiv musknapp", - "No mousebutton": "Ingen musknapp", - "Left mousebutton": "Vänster musknapp", - "Middle mousebutton": "Mitten-musknapp", - "Right mousebutton": "Höger musknapp", + "Drag": "Dra", + "Move/Drag viewport": "Flytta/Dra vyn", "Keyboard": "Tangentbord", - "Show Keyboard": "Visa Tangentbord", + "Show keyboard": "Visa tangentbord", "Extra keys": "Extraknappar", - "Show Extra Keys": "Visa Extraknappar", + "Show extra keys": "Visa extraknappar", "Ctrl": "Ctrl", "Toggle Ctrl": "Växla Ctrl", "Alt": "Alt", @@ -44,30 +40,44 @@ "Reboot": "Boota om", "Reset": "Återställ", "Clipboard": "Urklipp", - "Clear": "Rensa", - "Fullscreen": "Fullskärm", + "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:", + "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", + "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", + "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 Password": "Skicka lösenord", - "Cancel": "Avbryt" + "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/app/locale/tr.json b/app/locale/tr.json index 451c1b8a6..90f816244 100644 --- a/app/locale/tr.json +++ b/app/locale/tr.json @@ -23,7 +23,7 @@ "Keyboard": "Klavye", "Show Keyboard": "Klavye Düzenini Göster", "Extra keys": "Ekstra tuşlar", - "Show Extra Keys": "Ekstra tuşları göster", + "Show extra keys": "Ekstra tuşları göster", "Ctrl": "Ctrl", "Toggle Ctrl": "Ctrl Değiştir ", "Alt": "Alt", diff --git a/app/locale/uk.json b/app/locale/uk.json new file mode 100644 index 000000000..513ed6570 --- /dev/null +++ b/app/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/app/locale/zh_CN.json b/app/locale/zh_CN.json index b66995620..2898d2c1d 100644 --- a/app/locale/zh_CN.json +++ b/app/locale/zh_CN.json @@ -1,69 +1,93 @@ { - "Connecting...": "链接中...", - "Disconnecting...": "正在中断连接...", - "Reconnecting...": "重新链接中...", + "Running without HTTPS is not recommended, crashes or other issues are likely.": "不建议在没有 HTTPS 的情况下运行,可能会出现崩溃或出现其他问题。", + "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": "请提供密码", + "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": "显示/隐藏控制列", - "Move/Drag Viewport": "拖放显示范围", - "viewport drag": "显示范围拖放", - "Active Mouse Button": "启动鼠标按鍵", - "No mousebutton": "禁用鼠标按鍵", - "Left mousebutton": "鼠标左鍵", - "Middle mousebutton": "鼠标中鍵", - "Right mousebutton": "鼠标右鍵", + "Hide/Show the control bar": "显示/隐藏控制栏", + "Drag": "拖动", + "Move/Drag viewport": "移动/拖动窗口", "Keyboard": "键盘", - "Show Keyboard": "显示键盘", + "Show keyboard": "显示键盘", "Extra keys": "额外按键", - "Show 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...": "关机/重新启动...", + "Ctrl+Alt+Del": "Ctrl+Alt+Del", + "Send Ctrl-Alt-Del": "发送 Ctrl+Alt+Del 键", + "Shutdown/Reboot": "关机/重启", + "Shutdown/Reboot...": "关机/重启...", "Power": "电源", "Shutdown": "关机", - "Reboot": "重新启动", + "Reboot": "重启", "Reset": "重置", "Clipboard": "剪贴板", - "Clear": "清除", - "Fullscreen": "全屏幕", + "Edit clipboard content in the textarea below.": "在下面的文本区域中编辑剪贴板内容。", + "Full screen": "全屏", "Settings": "设置", - "Shared Mode": "分享模式", - "View Only": "仅检视", - "Clip to Window": "限制/裁切窗口大小", - "Scaling Mode:": "缩放模式:", + "Shared mode": "分享模式", + "View only": "仅查看", + "Clip to window": "限制/裁切窗口大小", + "Scaling mode:": "缩放模式:", "None": "无", - "Local Scaling": "本地缩放", - "Remote Resizing": "远程调整大小", + "Local scaling": "本地缩放", + "Remote resizing": "远程调整大小", "Advanced": "高级", + "Quality:": "品质:", + "Compression level:": "压缩级别:", "Repeater ID:": "中继站 ID", "WebSocket": "WebSocket", "Encrypt": "加密", "Host:": "主机:", "Port:": "端口:", "Path:": "路径:", - "Automatic Reconnect": "自动重新链接", - "Reconnect Delay (ms):": "重新链接间隔 (ms):", + "Automatic reconnect": "自动重新连接", + "Reconnect delay (ms):": "重新连接间隔 (ms):", + "Show dot when no cursor": "无光标时显示点", "Logging:": "日志级别:", - "Disconnect": "终端链接", - "Connect": "链接", + "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:": "密码:", - "Cancel": "取消" + "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/app/locale/zh_TW.json b/app/locale/zh_TW.json index 8ddf813f0..9d292a315 100644 --- a/app/locale/zh_TW.json +++ b/app/locale/zh_TW.json @@ -14,7 +14,7 @@ "Password is required": "請提供密碼", "noVNC encountered an error:": "noVNC 遇到一個錯誤:", "Hide/Show the control bar": "顯示/隱藏控制列", - "Move/Drag Viewport": "拖放顯示範圍", + "Move/Drag viewport": "拖放顯示範圍", "viewport drag": "顯示範圍拖放", "Active Mouse Button": "啟用滑鼠按鍵", "No mousebutton": "無滑鼠按鍵", @@ -22,9 +22,9 @@ "Middle mousebutton": "滑鼠中鍵", "Right mousebutton": "滑鼠右鍵", "Keyboard": "鍵盤", - "Show Keyboard": "顯示鍵盤", + "Show keyboard": "顯示鍵盤", "Extra keys": "額外按鍵", - "Show Extra Keys": "顯示額外按鍵", + "Show extra keys": "顯示額外按鍵", "Ctrl": "Ctrl", "Toggle Ctrl": "切換 Ctrl", "Alt": "Alt", @@ -45,13 +45,13 @@ "Clear": "清除", "Fullscreen": "全螢幕", "Settings": "設定", - "Shared Mode": "分享模式", - "View Only": "僅檢視", - "Clip to Window": "限制/裁切視窗大小", - "Scaling Mode:": "縮放模式:", + "Shared mode": "分享模式", + "View only": "僅檢視", + "Clip to window": "限制/裁切視窗大小", + "Scaling mode:": "縮放模式:", "None": "無", - "Local Scaling": "本機縮放", - "Remote Resizing": "遠端調整大小", + "Local scaling": "本機縮放", + "Remote resizing": "遠端調整大小", "Advanced": "進階", "Repeater ID:": "中繼站 ID", "WebSocket": "WebSocket", @@ -59,8 +59,8 @@ "Host:": "主機:", "Port:": "連接埠:", "Path:": "路徑:", - "Automatic Reconnect": "自動重新連線", - "Reconnect Delay (ms):": "重新連線間隔 (ms):", + "Automatic reconnect": "自動重新連線", + "Reconnect delay (ms):": "重新連線間隔 (ms):", "Logging:": "日誌級別:", "Disconnect": "中斷連線", "Connect": "連線", diff --git a/app/localization.js b/app/localization.js index 100901c9d..c8257fdbe 100644 --- a/app/localization.js +++ b/app/localization.js @@ -1,13 +1,13 @@ /* * noVNC: HTML5 VNC client - * Copyright (C) 2018 The noVNC Authors + * Copyright (C) 2018 The noVNC authors * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. */ /* - * Localization Utilities + * Localization utilities */ export class Localizer { @@ -16,13 +16,19 @@ export class Localizer { this.language = 'en'; // Current dictionary of translations - this.dictionary = undefined; + this._dictionary = undefined; } // Configure suitable language based on user preferences - setup(supportedLanguages) { + 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 @@ -40,12 +46,6 @@ export class Localizer { .replace("_", "-") .split("-"); - // Built-in default? - if ((userLang[0] === 'en') && - ((userLang[1] === undefined) || (userLang[1] === 'us'))) { - return; - } - // First pass: perfect match for (let j = 0; j < supportedLanguages.length; j++) { const supLang = supportedLanguages[j] @@ -64,7 +64,12 @@ export class Localizer { return; } - // Second pass: fallback + // 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() @@ -84,10 +89,32 @@ export class Localizer { } } + 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]; + if (typeof this._dictionary !== 'undefined' && + this._dictionary[id]) { + return this._dictionary[id]; } else { return id; } @@ -103,13 +130,20 @@ export class Localizer { 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 = self.get(elem.getAttribute(attr)); + const str = translateString(elem.getAttribute(attr)); elem.setAttribute(attr, str); } function translateTextNode(node) { - const str = self.get(node.data.trim()); + const str = translateString(node.data); node.data = str; } diff --git a/app/styles/base.css b/app/styles/base.css index 3ca9894dc..33f0f3596 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -1,6 +1,6 @@ /* * noVNC base CSS - * Copyright (C) 2018 The noVNC Authors + * 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). */ @@ -19,28 +19,42 @@ * 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; - font-family: Helvetica; - /*Background image with light grey curve.*/ - background-color:#494949; - background-repeat:no-repeat; - background-position:right bottom; - height:100%; - touch-action: none; + 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%; + height:100%; } .noVNC_only_touch.noVNC_hidden { - display: none; + display: none; } .noVNC_disabled { - color: rgb(128, 128, 128); + color: var(--novnc-grey); } /* ---------------------------------------- @@ -49,115 +63,33 @@ html { */ .noVNC_spinner { - position: relative; + 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; + 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; + 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; + 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; } -} - -/* ---------------------------------------- - * Input Elements - * ---------------------------------------- - */ - -input[type=input], input[type=password], input[type=number], -input:not([type]), textarea { - /* Disable default rendering */ - -webkit-appearance: none; - -moz-appearance: none; - background: none; - - margin: 2px; - padding: 2px; - border: 1px solid rgb(192, 192, 192); - border-radius: 5px; - color: black; - background: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240)); -} - -input[type=button], input[type=submit], select { - /* Disable default rendering */ - -webkit-appearance: none; - -moz-appearance: none; - background: none; - - margin: 2px; - padding: 2px; - border: 1px solid rgb(192, 192, 192); - border-bottom-width: 2px; - border-radius: 5px; - color: black; - background: linear-gradient(to top, rgb(255, 255, 255), rgb(240, 240, 240)); - - /* This avoids it jumping around when :active */ - vertical-align: middle; -} - -input[type=button], input[type=submit] { - padding-left: 20px; - padding-right: 20px; -} - -option { - color: black; - background: white; -} - -input[type=input]:focus, input[type=password]:focus, -input:not([type]):focus, input[type=button]:focus, -input[type=submit]:focus, -textarea:focus, select:focus { - box-shadow: 0px 0px 3px rgba(74, 144, 217, 0.5); - border-color: rgb(74, 144, 217); - outline: none; -} - -input[type=button]::-moz-focus-inner, -input[type=submit]::-moz-focus-inner { - border: none; -} - -input[type=input]:disabled, input[type=password]:disabled, -input:not([type]):disabled, input[type=button]:disabled, -input[type=submit]:disabled, input[type=number]:disabled, -textarea:disabled, select:disabled { - color: rgb(128, 128, 128); - background: rgb(240, 240, 240); -} - -input[type=button]:active, input[type=submit]:active, -select:active { - border-bottom-width: 1px; - margin-top: 3px; -} - -:root:not(.noVNC_touch) input[type=button]:hover:not(:disabled), -:root:not(.noVNC_touch) input[type=submit]:hover:not(:disabled), -:root:not(.noVNC_touch) select:hover:not(:disabled) { - background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250)); + 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; } } /* ---------------------------------------- @@ -166,37 +98,39 @@ select:active { */ .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; + /* + * 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; + pointer-events: auto; } .noVNC_vcenter { - display: flex; - flex-direction: column; - justify-content: center; - position: fixed; - top: 0; - left: 0; - height: 100%; - pointer-events: none; + 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_vcenter > * { - pointer-events: auto; + pointer-events: auto; } /* ---------------------------------------- @@ -205,7 +139,7 @@ select:active { */ .noVNC_connect_layer { - z-index: 60; + z-index: 60; } /* ---------------------------------------- @@ -214,666 +148,759 @@ select:active { */ #noVNC_fallback_error { - z-index: 1000; - visibility: hidden; + 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; + visibility: visible; } #noVNC_fallback_error > div { - max-width: 90%; - padding: 15px; + max-width: calc(100vw - 30px - 30px); + max-height: calc(100vh - 30px - 30px); + overflow: auto; + + padding: 15px; - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - transform: translateY(-50px); - opacity: 0; + transform: translateY(-50px); + opacity: 0; - text-align: center; - font-weight: bold; - color: #fff; + text-align: center; + font-weight: bold; + color: #fff; - border-radius: 10px; - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); - background: rgba(200,55,55,0.8); + 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; + transform: translateY(0); + opacity: 1; } #noVNC_fallback_errormsg { - font-weight: normal; + font-weight: normal; } #noVNC_fallback_errormsg .noVNC_message { - display: inline-block; - text-align: left; - font-family: monospace; - white-space: pre-wrap; + 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); + font-style: italic; + font-size: 0.8em; + color: rgba(255, 255, 255, 0.8); } #noVNC_fallback_error .noVNC_stack { - max-height: 50vh; - 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; + 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 + * Control bar * ---------------------------------------- */ #noVNC_control_bar_anchor { - /* The anchor is needed to get z-stacking to work */ - position: fixed; - z-index: 10; + /* The anchor is needed to get z-stacking to work */ + position: fixed; + z-index: 10; - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - /* Edge misrenders animations wihthout this */ - transform: translateX(0); + /* Edge misrenders animations wihthout this */ + transform: translateX(0); } :root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle { - opacity: 0.8; + opacity: 0.8; } #noVNC_control_bar_anchor.noVNC_right { - left: auto; - right: 0; + left: auto; + right: 0; } #noVNC_control_bar { - position: relative; - left: -100%; + position: relative; + left: -100%; - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - background-color: rgb(110, 132, 163); - border-radius: 0 10px 10px 0; + 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_control_bar.noVNC_open { - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); - left: 0; + box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); + left: 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; + /* 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_control_bar.noVNC_open::before { - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); + box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); } .noVNC_right #noVNC_control_bar { - left: 100%; - border-radius: 10px 0 0 10px; + left: 100%; + border-radius: 12px 0 0 12px; } .noVNC_right #noVNC_control_bar.noVNC_open { - left: 0; + left: 0; } .noVNC_right #noVNC_control_bar::before { - visibility: hidden; + visibility: hidden; } #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: 5px; - background-color: rgb(83, 99, 122); - background-image: url("../images/handle_bg.svg"); - background-repeat: no-repeat; - background-position: right; - box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5); + 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); + background-image: url("../images/handle_bg.svg"); + background-repeat: no-repeat; + background-position: right; + box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5); } #noVNC_control_bar_handle:after { - content: ""; - transition: transform 0.5s ease-in-out; - background: url("../images/handle.svg"); - position: absolute; - top: 22px; /* (50px-6px)/2 */ - right: 5px; - width: 5px; - height: 6px; + content: ""; + transition: transform 0.5s ease-in-out; + background: url("../images/handle.svg"); + position: absolute; + top: 22px; /* (50px-6px)/2 */ + right: 5px; + width: 5px; + height: 6px; } #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after { - transform: translateX(1px) rotate(180deg); + transform: translateX(1px) rotate(180deg); } :root:not(.noVNC_connected) #noVNC_control_bar_handle { - display: none; + display: none; } .noVNC_right #noVNC_control_bar_handle { - background-position: left; + background-position: left; } .noVNC_right #noVNC_control_bar_handle:after { - left: 5px; - right: 0; - transform: translateX(1px) rotate(180deg); + left: 5px; + right: 0; + transform: translateX(1px) rotate(180deg); } .noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after { - transform: none; + transform: none; } +/* Larger touch area for the handle, used when a touch screen is available */ #noVNC_control_bar_handle div { - position: absolute; - right: -35px; - top: 0; - width: 50px; - height: 50px; -} -:root:not(.noVNC_touch) #noVNC_control_bar_handle div { - display: none; + position: absolute; + 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; + left: -35px; + right: auto; } -#noVNC_control_bar .noVNC_scroll { - max-height: 100vh; /* Chrome is buggy with 100% */ - overflow-x: hidden; - overflow-y: auto; - padding: 0 10px 0 5px; -} -.noVNC_right #noVNC_control_bar .noVNC_scroll { - padding: 0 5px 0 10px; +#noVNC_control_bar > .noVNC_scroll { + max-height: 100vh; /* Chrome is buggy with 100% */ + overflow-x: hidden; + overflow-y: auto; + padding: 0 10px; } -/* Control bar hint */ -#noVNC_control_bar_hint { - position: fixed; - left: calc(100vw - 50px); - right: auto; - top: 50%; - transform: translateY(-50%) scale(0); - width: 100px; - height: 50%; - max-height: 600px; - - visibility: hidden; - opacity: 0; - transition: 0.2s ease-in-out; - background: transparent; - box-shadow: 0 0 10px black, inset 0 0 10px 10px rgba(110, 132, 163, 0.8); - border-radius: 10px; - transition-delay: 0s; -} -#noVNC_control_bar_anchor.noVNC_right #noVNC_control_bar_hint{ - left: auto; - right: calc(100vw - 50px); -} -#noVNC_control_bar_hint.noVNC_active { - visibility: visible; - opacity: 1; - transition-delay: 0.2s; - transform: translateY(-50%) scale(1); +#noVNC_control_bar > .noVNC_scroll > * { + display: block; + margin: 10px auto; } -/* General button style */ -.noVNC_button { - display: block; - padding: 4px 4px; - margin: 10px 0; - vertical-align: middle; - border:1px solid rgba(255, 255, 255, 0.2); - border-radius: 6px; +/* Control bar hint */ +#noVNC_hint_anchor { + position: fixed; + right: -50px; + left: auto; } -.noVNC_button.noVNC_selected { - border-color: rgba(0, 0, 0, 0.8); - background: rgba(0, 0, 0, 0.5); +#noVNC_control_bar_anchor.noVNC_right + #noVNC_hint_anchor { + left: -50px; + right: auto; } -.noVNC_button:disabled { - opacity: 0.4; +#noVNC_control_bar_hint { + position: relative; + transform: scale(0); + width: 100px; + height: 50%; + max-height: 600px; + + 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; } -.noVNC_button:focus { - outline: none; +#noVNC_control_bar_hint.noVNC_active { + visibility: visible; + opacity: 1; + transition-delay: 0.2s; + transform: scale(1); } -.noVNC_button:active { - padding-top: 5px; - padding-bottom: 3px; +#noVNC_control_bar_hint.noVNC_notransition { + transition: none !important; } -/* Android browsers don't properly update hover state if touch events - * are intercepted, but focus should be safe to display */ -:root:not(.noVNC_touch) .noVNC_button.noVNC_selected:hover, -.noVNC_button.noVNC_selected:focus { - border-color: rgba(0, 0, 0, 0.4); - background: rgba(0, 0, 0, 0.2); + +/* Control bar buttons */ +#noVNC_control_bar .noVNC_button { + min-width: unset; + padding: 4px 4px; + vertical-align: middle; + border:1px solid rgba(255, 255, 255, 0.2); + border-radius: 6px; + background-color: transparent; } -:root:not(.noVNC_touch) .noVNC_button:hover, -.noVNC_button:focus { - background: rgba(255, 255, 255, 0.2); +#noVNC_control_bar .noVNC_button.noVNC_selected { + border-color: rgba(0, 0, 0, 0.8); + background-color: rgba(0, 0, 0, 0.5); } -.noVNC_button.noVNC_hidden { - display: none; +#noVNC_control_bar .noVNC_button.noVNC_hidden { + display: none !important; } /* Panels */ .noVNC_panel { - transform: translateX(25px); + transform: translateX(25px); - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - max-height: 100vh; /* Chrome is buggy with 100% */ - overflow-x: hidden; - overflow-y: auto; + 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: 100vh; /* Chrome is buggy with 100% */ + overflow-x: hidden; + overflow-y: auto; - visibility: hidden; - opacity: 0; + visibility: hidden; + opacity: 0; - padding: 15px; + padding: 15px; - background: #fff; - border-radius: 10px; - color: #000; - border: 2px solid #E0E0E0; - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); + 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); + visibility: visible; + opacity: 1; + transform: translateX(75px); } .noVNC_right .noVNC_vcenter { - left: auto; - right: 0; + left: auto; + right: 0; } .noVNC_right .noVNC_panel { - transform: translateX(-25px); + transform: translateX(-25px); } .noVNC_right .noVNC_panel.noVNC_open { - transform: translateX(-75px); + transform: translateX(-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 rgb(192, 192, 192); + 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; + 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: rgb(110, 132, 163); - border-radius: 5px; - padding: 5px; - /* Compensate for padding in image */ - padding-right: 8px; - color: white; - font-size: 20px; - margin-bottom: 10px; - white-space: nowrap; + 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; + vertical-align: bottom; +} + +.noVNC_panel form { + display: flex; + flex-direction: column; + gap: 12px } -.noVNC_submit { - float: right; +.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; + cursor: pointer; } .noVNC_expander::before { - content: url("../images/expander.svg"); - display: inline-block; - margin-right: 5px; - transition: 0.2s ease-in-out; + 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); + transform: rotateZ(90deg); } .noVNC_expander ~ * { - margin: 5px; - margin-left: 10px; - padding: 5px; - background: rgba(0, 0, 0, 0.05); - border-radius: 5px; + margin: 5px; + margin-left: 10px; + padding: 5px; + background: rgba(0, 0, 0, 0.04); + border-radius: 6px; } .noVNC_expander:not(.noVNC_open) ~ * { - display: none; + display: none; } /* Control bar content */ #noVNC_control_bar .noVNC_logo { - font-size: 13px; + font-size: 13px; +} + +.noVNC_logo + hr { + /* Remove all but top border */ + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.2); } :root:not(.noVNC_connected) #noVNC_view_drag_button { - display: none; + display: none; } /* noVNC Touch Device only buttons */ :root:not(.noVNC_connected) #noVNC_mobile_buttons { - display: none; + display: none; } -:root:not(.noVNC_touch) #noVNC_mobile_buttons { - display: none; +@media not all and (any-pointer: coarse) { + /* FIXME: The button for the virtual keyboard is the only button in this + group of "mobile buttons". 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_mobile_buttons { + display: none; + } } /* Extra manual keys */ -:root:not(.noVNC_connected) #noVNC_extra_keys { - display: none; +:root:not(.noVNC_connected) #noVNC_toggle_extra_keys_button { + display: none; } #noVNC_modifiers { - background-color: rgb(92, 92, 92); - border: none; - padding: 0 10px; + background-color: var(--novnc-darkgrey); + border: none; + padding: 10px; } /* Shutdown/Reboot */ :root:not(.noVNC_connected) #noVNC_power_button { - display: none; + display: none; } #noVNC_power { } #noVNC_power_buttons { - display: none; + display: none; } #noVNC_power input[type=button] { - width: 100%; + width: 100%; } /* Clipboard */ :root:not(.noVNC_connected) #noVNC_clipboard_button { - display: none; -} -#noVNC_clipboard { - /* Full screen, minus padding and left and right margins */ - max-width: calc(100vw - 2*15px - 75px - 25px); + display: none; } #noVNC_clipboard_text { - width: 500px; - max-width: 100%; + 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; - margin: 0px; - padding: 0px; + 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; + width: 80px; } #noVNC_setting_path { - width: 100px; + width: 100px; } -/* Connection Controls */ +/* Version */ + +.noVNC_version_wrapper { + font-size: small; +} + +.noVNC_version { + margin-left: 1rem; +} + +/* Connection controls */ :root:not(.noVNC_connected) #noVNC_disconnect_button { - display: none; + display: none; } /* ---------------------------------------- - * Status Dialog + * Status dialog * ---------------------------------------- */ #noVNC_status { - position: fixed; - top: 0; - left: 0; - width: 100%; - z-index: 100; - transform: translateY(-100%); + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 100; + transform: translateY(-100%); - cursor: pointer; + cursor: pointer; - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - visibility: hidden; - opacity: 0; + visibility: hidden; + opacity: 0; - padding: 5px; + padding: 5px; - display: flex; - flex-direction: row; - justify-content: center; - align-content: center; + display: flex; + flex-direction: row; + justify-content: center; + align-content: center; - line-height: 25px; - word-wrap: break-word; - color: #fff; + line-height: 1.6; + word-wrap: break-word; + color: #fff; - border-bottom: 1px solid rgba(0, 0, 0, 0.9); + border-bottom: 1px solid rgba(0, 0, 0, 0.9); } #noVNC_status.noVNC_open { - transform: translateY(0); - visibility: visible; - opacity: 1; + transform: translateY(0); + visibility: visible; + opacity: 1; } #noVNC_status::before { - content: ""; - display: inline-block; - width: 25px; - height: 25px; - margin-right: 5px; + content: ""; + display: inline-block; + width: 25px; + height: 25px; + margin-right: 5px; } #noVNC_status.noVNC_status_normal { - background: rgba(128,128,128,0.9); + background: rgba(128,128,128,0.9); } #noVNC_status.noVNC_status_normal::before { - content: url("../images/info.svg") " "; + content: url("../images/info.svg") " "; } #noVNC_status.noVNC_status_error { - background: rgba(200,55,55,0.9); + background: rgba(200,55,55,0.9); } #noVNC_status.noVNC_status_error::before { - content: url("../images/error.svg") " "; + content: url("../images/error.svg") " "; } #noVNC_status.noVNC_status_warn { - background: rgba(180,180,30,0.9); + background: rgba(180,180,30,0.9); } #noVNC_status.noVNC_status_warn::before { - content: url("../images/warning.svg") " "; + content: url("../images/warning.svg") " "; } /* ---------------------------------------- - * Connect Dialog + * Connect dialog * ---------------------------------------- */ #noVNC_connect_dlg { - transition: 0.5s ease-in-out; + transition: 0.5s ease-in-out; - transform: scale(0, 0); - visibility: hidden; - opacity: 0; + transform: scale(0, 0); + visibility: hidden; + opacity: 0; } #noVNC_connect_dlg.noVNC_open { - transform: scale(1, 1); - visibility: visible; - opacity: 1; + transform: scale(1, 1); + visibility: visible; + opacity: 1; } #noVNC_connect_dlg .noVNC_logo { - transition: 0.5s ease-in-out; - padding: 10px; - margin-bottom: 10px; + transition: 0.5s ease-in-out; + padding: 10px; + margin-bottom: 10px; - font-size: 80px; - text-align: center; + font-size: 80px; + text-align: center; - border-radius: 5px; + 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 { + max-width: calc(100vw - 100px); + } + #noVNC_connect_dlg .noVNC_logo { + font-size: calc(25vw - 30px); + } } -#noVNC_connect_button { - cursor: pointer; - - padding: 10px; +#noVNC_connect_dlg div { + padding: 18px; - color: white; - background-color: rgb(110, 132, 163); - border-radius: 12px; + background-color: var(--novnc-darkgrey); + border-radius: 12px; + text-align: center; + font-size: 20px; - 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; - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + place-items: center; + gap: 4px; } -#noVNC_connect_button div { - margin: 2px; - padding: 5px 30px; - border: 1px solid rgb(83, 99, 122); - border-bottom-width: 2px; - border-radius: 5px; - background: linear-gradient(to top, rgb(110, 132, 163), rgb(99, 119, 147)); - /* This avoids it jumping around when :active */ - vertical-align: middle; +#noVNC_connect_button img { + vertical-align: bottom; + height: 1.3em; } -#noVNC_connect_button div:active { - border-bottom-width: 1px; - margin-top: 3px; + +/* ---------------------------------------- + * Server verification dialog + * ---------------------------------------- + */ + +#noVNC_verify_server_dlg { + position: relative; + + transform: translateY(-50px); } -:root:not(.noVNC_touch) #noVNC_connect_button div:hover { - background: linear-gradient(to top, rgb(110, 132, 163), rgb(105, 125, 155)); +#noVNC_verify_server_dlg.noVNC_open { + transform: translateY(0); } - -#noVNC_connect_button img { - vertical-align: bottom; - height: 1.3em; +#noVNC_fingerprint_block { + margin: 10px; } /* ---------------------------------------- - * Password Dialog + * Password dialog * ---------------------------------------- */ -#noVNC_password_dlg { - position: relative; +#noVNC_credentials_dlg { + position: relative; - transform: translateY(-50px); + transform: translateY(-50px); } -#noVNC_password_dlg.noVNC_open { - transform: translateY(0); +#noVNC_credentials_dlg.noVNC_open { + transform: translateY(0); } -#noVNC_password_dlg ul { - list-style: none; - margin: 0px; - padding: 0px; +#noVNC_username_block.noVNC_hidden, +#noVNC_password_block.noVNC_hidden { + display: none; } + /* ---------------------------------------- - * Main Area + * Main area * ---------------------------------------- */ /* Transition screen */ #noVNC_transition { - display: none; + transition: 0.5s ease-in-out; - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; + display: flex; + opacity: 0; + visibility: hidden; - color: white; - background: rgba(0, 0, 0, 0.5); - z-index: 50; + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; - /*display: flex;*/ - align-items: center; - justify-content: center; - flex-direction: column; + 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 { - display: flex; + opacity: 1; + visibility: visible; } :root:not(.noVNC_reconnecting) #noVNC_cancel_reconnect_button { - display: none; + display: none; } #noVNC_transition_text { - font-size: 1.5em; + 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;*/ + 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; + 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'); + font-family: 'Orbitron'; + font-style: normal; + font-weight: 700; + src: local('?'), url('Orbitron700.woff') format('woff'), + url('Orbitron700.ttf') format('truetype'); } .noVNC_logo { - color:yellow; - font-family: 'Orbitron', 'OrbitronTTF', sans-serif; - line-height:90%; - text-shadow: 0.1em 0.1em 0 black; + 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:green; + color: var(--novnc-green); } #noVNC_bell { - display: none; + display: none; } /* ---------------------------------------- @@ -882,19 +909,19 @@ select:active { */ @media screen and (max-width: 640px){ - #noVNC_logo { - font-size: 150px; - } + #noVNC_logo { + font-size: 150px; + } } @media screen and (min-width: 321px) and (max-width: 480px) { - #noVNC_logo { - font-size: 110px; - } + #noVNC_logo { + font-size: 110px; + } } @media screen and (max-width: 320px) { - #noVNC_logo { - font-size: 90px; - } + #noVNC_logo { + font-size: 90px; + } } diff --git a/app/styles/constants.css b/app/styles/constants.css new file mode 100644 index 000000000..1123a3efc --- /dev/null +++ b/app/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/app/styles/input.css b/app/styles/input.css new file mode 100644 index 000000000..8273d70ad --- /dev/null +++ b/app/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 + + - +
-
-
    -
  • - - -
  • -
  • - -
  • -
+
+
+ Server identity +
+
+ The server has provided the following identifying information: +
+
+ Fingerprint: + +
+
+ Please verify that the information is correct and press + "Approve". Otherwise press "Reject". +
+
+ + +
+
+
+ + +
+
+
+ Credentials +
+
+ + +
+
+ + +
+
+ +
- +
- +
diff --git a/vnc_lite.html b/vnc_lite.html index 426d79b35..79d481460 100644 --- a/vnc_lite.html +++ b/vnc_lite.html @@ -7,7 +7,7 @@ This is a self-contained file which doesn't import WebUtil or external CSS. - Copyright (C) 2018 The noVNC Authors + 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). @@ -16,8 +16,6 @@ --> noVNC - - - - - - - - - -