Also translate HTML elements
This commit is contained in:
parent
3cdc603aa4
commit
edffd9e2f8
|
@ -96,6 +96,9 @@ var UI;
|
|||
|
||||
UI.initSettings();
|
||||
|
||||
// Translate the DOM
|
||||
Util.Localisation.translateDOM();
|
||||
|
||||
// Adapt the interface for touch screen devices
|
||||
if (Util.isTouchDevice) {
|
||||
document.documentElement.classList.add("noVNC_touch");
|
||||
|
|
76
core/util.js
76
core/util.js
|
@ -440,7 +440,81 @@ Util.Localisation = {
|
|||
} else {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Traverses the DOM and translates relevant fields
|
||||
// See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
|
||||
translateDOM: function () {
|
||||
function process(elem, enabled) {
|
||||
function isAnyOf(searchElement, items) {
|
||||
return items.indexOf(searchElement) !== -1;
|
||||
}
|
||||
|
||||
function translateAttribute(elem, attr) {
|
||||
var str = elem.getAttribute(attr);
|
||||
str = Util.Localisation.get(str);
|
||||
elem.setAttribute(attr, str);
|
||||
}
|
||||
|
||||
function translateTextNode(node) {
|
||||
var str = node.data.trim();
|
||||
str = Util.Localisation.get(str);
|
||||
node.data = str;
|
||||
}
|
||||
|
||||
if (elem.hasAttribute("translate")) {
|
||||
if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) {
|
||||
enabled = true;
|
||||
} else if (isAnyOf(elem.getAttribute("translate"), ["no"])) {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
if (elem.hasAttribute("abbr") &&
|
||||
elem.tagName === "TH") {
|
||||
translateAttribute(elem, "abbr");
|
||||
}
|
||||
if (elem.hasAttribute("alt") &&
|
||||
isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) {
|
||||
translateAttribute(elem, "alt");
|
||||
}
|
||||
if (elem.hasAttribute("download") &&
|
||||
isAnyOf(elem.tagName, ["A", "AREA"])) {
|
||||
translateAttribute(elem, "download");
|
||||
}
|
||||
if (elem.hasAttribute("label") &&
|
||||
isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP",
|
||||
"OPTION", "TRACK"])) {
|
||||
translateAttribute(elem, "label");
|
||||
}
|
||||
// FIXME: Should update "lang"
|
||||
if (elem.hasAttribute("placeholder") &&
|
||||
isAnyOf(elem.tagName in ["INPUT", "TEXTAREA"])) {
|
||||
translateAttribute(elem, "placeholder");
|
||||
}
|
||||
if (elem.hasAttribute("title")) {
|
||||
translateAttribute(elem, "title");
|
||||
}
|
||||
if (elem.hasAttribute("value") &&
|
||||
elem.tagName === "INPUT" &&
|
||||
isAnyOf(elem.getAttribute("type"), ["reset", "button"])) {
|
||||
translateAttribute(elem, "value");
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0;i < elem.childNodes.length;i++) {
|
||||
node = elem.childNodes[i];
|
||||
if (node.nodeType === node.ELEMENT_NODE) {
|
||||
process(node, enabled);
|
||||
} else if (node.nodeType === node.TEXT_NODE && enabled) {
|
||||
translateTextNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process(document.body, true);
|
||||
},
|
||||
};
|
||||
|
||||
/* [module] export default Util; */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"chai": "^3.5.0",
|
||||
"commander": "^2.9.0",
|
||||
"fs-extra": "^1.0.0",
|
||||
"jsdom": "*",
|
||||
"karma": "^1.3.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"karma-sinon": "^1.0.5",
|
||||
"karma-sinon-chai-latest": "^0.1.0",
|
||||
"mocha": "^3.1.2",
|
||||
"node-getopt": "*",
|
||||
"open": "^0.0.5",
|
||||
"phantomjs-prebuilt": "^2.1.13",
|
||||
"po2json": "*",
|
||||
|
|
|
@ -17,7 +17,7 @@ update-js: $(JSFILES)
|
|||
./po2js $< $@
|
||||
|
||||
update-pot:
|
||||
xgettext --output=noVNC.pot \
|
||||
xgettext --output=noVNC.js.pot \
|
||||
--copyright-holder="Various Authors" \
|
||||
--package-name="noVNC" \
|
||||
--package-version="$(VERSION)" \
|
||||
|
@ -27,3 +27,8 @@ update-pot:
|
|||
../app/*.js \
|
||||
../core/*.js \
|
||||
../core/input/*.js
|
||||
./xgettext-html --output=noVNC.html.pot \
|
||||
../vnc.html
|
||||
msgcat --output-file=noVNC.pot \
|
||||
--sort-by-file noVNC.js.pot noVNC.html.pot
|
||||
rm -f noVNC.js.pot noVNC.html.pot
|
||||
|
|
254
po/noVNC.pot
254
po/noVNC.pot
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: noVNC 0.6.1\n"
|
||||
"Report-Msgid-Bugs-To: novnc@googlegroups.com\n"
|
||||
"POT-Creation-Date: 2016-11-15 08:11+0100\n"
|
||||
"POT-Creation-Date: 2016-11-15 19:32+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,35 +17,35 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../app/ui.js:402
|
||||
#: ../app/ui.js:405
|
||||
msgid "Connecting..."
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:409
|
||||
#: ../app/ui.js:412
|
||||
msgid "Connected (encrypted) to "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:411
|
||||
#: ../app/ui.js:414
|
||||
msgid "Connected (unencrypted) to "
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:416
|
||||
#: ../app/ui.js:419
|
||||
msgid "Disconnecting..."
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:421
|
||||
#: ../app/ui.js:424
|
||||
msgid "Disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1006 ../core/rfb.js:278
|
||||
#: ../app/ui.js:1009 ../core/rfb.js:278
|
||||
msgid "Must set host and port"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1059
|
||||
#: ../app/ui.js:1062
|
||||
msgid "Password is required"
|
||||
msgstr ""
|
||||
|
||||
#: ../app/ui.js:1272
|
||||
#: ../app/ui.js:1275
|
||||
msgid ""
|
||||
"Forcing clipping mode since scrollbars aren't supported by IE in fullscreen"
|
||||
msgstr ""
|
||||
|
@ -53,3 +53,239 @@ msgstr ""
|
|||
#: ../core/rfb.js:556
|
||||
msgid "Disconnect timeout"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:70
|
||||
msgid "noVNC encountered an error:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:78
|
||||
msgid "Hide/Show the control bar"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:85
|
||||
msgid "Move/Drag Viewport"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:85
|
||||
msgid "viewport drag"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:91 ../vnc.html:94 ../vnc.html:97 ../vnc.html:100
|
||||
msgid "Active Mouse Button"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:91
|
||||
msgid "No mousebutton"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:94
|
||||
msgid "Left mousebutton"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:97
|
||||
msgid "Middle mousebutton"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:100
|
||||
msgid "Right mousebutton"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:103
|
||||
msgid "Keyboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:103
|
||||
msgid "Show Keyboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:110
|
||||
msgid "Extra keys"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:110
|
||||
msgid "Show Extra Keys"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:115
|
||||
msgid "Ctrl"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:115
|
||||
msgid "Toggle Ctrl"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:118
|
||||
msgid "Alt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:118
|
||||
msgid "Toggle Alt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:121
|
||||
msgid "Send Tab"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:121
|
||||
msgid "Tab"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:124
|
||||
msgid "Esc"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:124
|
||||
msgid "Send Escape"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:127
|
||||
msgid "Ctrl+Alt+Del"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:127
|
||||
msgid "Send Ctrl-Alt-Del"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:135
|
||||
msgid "Shutdown/Reboot"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:135
|
||||
msgid "Shutdown/Reboot..."
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:141
|
||||
msgid "Power"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:143
|
||||
msgid "Shutdown"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:144
|
||||
msgid "Reboot"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:145
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:150 ../vnc.html:156
|
||||
msgid "Clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:160
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:166
|
||||
msgid "Fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:171 ../vnc.html:178
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:181
|
||||
msgid "Encrypt"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:184
|
||||
msgid "True Color"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:187
|
||||
msgid "Local Cursor"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:190
|
||||
msgid "Clip to Window"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:193
|
||||
msgid "Shared Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:196
|
||||
msgid "View Only"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:200
|
||||
msgid "Path:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:204
|
||||
msgid "Scaling Mode:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:206
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:207
|
||||
msgid "Local Scaling"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:208
|
||||
msgid "Local Downscaling"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:209
|
||||
msgid "Remote Resizing"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:213
|
||||
msgid "Repeater ID:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:219
|
||||
msgid "Style:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:221
|
||||
msgid "default"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:227
|
||||
msgid "Logging:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:234
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:241 ../vnc.html:271
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:244
|
||||
msgid "Disconnect"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:251
|
||||
msgid "Connection"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:254
|
||||
msgid "Host:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:258
|
||||
msgid "Port:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:262 ../vnc.html:290
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:266
|
||||
msgid "Token:"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:294
|
||||
msgid "Send Password"
|
||||
msgstr ""
|
||||
|
||||
#: ../vnc.html:319
|
||||
msgid "Canvas not supported."
|
||||
msgstr ""
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/env node
|
||||
/*
|
||||
* xgettext-html: HTML gettext parser
|
||||
* Copyright (C) 2016 Pierre Ossman
|
||||
* Licensed under MPL 2.0 (see LICENSE.txt)
|
||||
*/
|
||||
|
||||
var getopt = require('node-getopt');
|
||||
|
||||
var jsdom = require("jsdom");
|
||||
var fs = require("fs");
|
||||
|
||||
opt = getopt.create([
|
||||
['o' , 'output=FILE' , 'write output to specified file'],
|
||||
['h' , 'help' , 'display this help'],
|
||||
]).bindHelp().parseSystem();
|
||||
|
||||
var strings = {};
|
||||
|
||||
function addString(str, location) {
|
||||
if (str.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strings[str] === undefined) {
|
||||
strings[str] = {}
|
||||
}
|
||||
strings[str][location] = null;
|
||||
}
|
||||
|
||||
// See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
|
||||
function process(elem, locator, enabled) {
|
||||
function isAnyOf(searchElement, items) {
|
||||
return items.indexOf(searchElement) !== -1;
|
||||
}
|
||||
|
||||
if (elem.hasAttribute("translate")) {
|
||||
if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) {
|
||||
enabled = true;
|
||||
} else if (isAnyOf(elem.getAttribute("translate"), ["no"])) {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
if (elem.hasAttribute("abbr") &&
|
||||
elem.tagName === "TH") {
|
||||
addString(elem.getAttribute("abbr"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("alt") &&
|
||||
isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) {
|
||||
addString(elem.getAttribute("alt"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("download") &&
|
||||
isAnyOf(elem.tagName, ["A", "AREA"])) {
|
||||
addString(elem.getAttribute("download"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("label") &&
|
||||
isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP",
|
||||
"OPTION", "TRACK"])) {
|
||||
addString(elem.getAttribute("label"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("placeholder") &&
|
||||
isAnyOf(elem.tagName in ["INPUT", "TEXTAREA"])) {
|
||||
addString(elem.getAttribute("placeholder"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("title")) {
|
||||
addString(elem.getAttribute("title"), locator(elem));
|
||||
}
|
||||
if (elem.hasAttribute("value") &&
|
||||
elem.tagName === "INPUT" &&
|
||||
isAnyOf(elem.getAttribute("type"), ["reset", "button"])) {
|
||||
addString(elem.getAttribute("value"), locator(elem));
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0;i < elem.childNodes.length;i++) {
|
||||
node = elem.childNodes[i];
|
||||
if (node.nodeType === node.ELEMENT_NODE) {
|
||||
process(node, locator, enabled);
|
||||
} else if (node.nodeType === node.TEXT_NODE && enabled) {
|
||||
addString(node.data.trim(), locator(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0;i < opt.argv.length;i++) {
|
||||
var file;
|
||||
|
||||
fn = opt.argv[i];
|
||||
file = fs.readFileSync(fn, "utf8");
|
||||
doc = jsdom.jsdom(file);
|
||||
|
||||
locator = function (elem) {
|
||||
offset = jsdom.nodeLocation(elem).start;
|
||||
line = file.slice(0, offset).split("\n").length;
|
||||
return fn + ":" + line;
|
||||
};
|
||||
|
||||
process(doc.body, locator, true);
|
||||
}
|
||||
|
||||
var output = "";
|
||||
|
||||
for (str in strings) {
|
||||
output += "#:";
|
||||
for (location in strings[str]) {
|
||||
output += " " + location;
|
||||
}
|
||||
output += "\n";
|
||||
|
||||
output += "msgid " + JSON.stringify(str) + "\n";
|
||||
output += "msgstr \"\"\n";
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
fs.writeFileSync(opt.options.output, output);
|
4
vnc.html
4
vnc.html
|
@ -79,7 +79,7 @@
|
|||
|
||||
<div class="noVNC_scroll">
|
||||
|
||||
<h1 class="noVNC_logo"><span>no</span><br />VNC</h1>
|
||||
<h1 class="noVNC_logo" translate="no"><span>no</span><br />VNC</h1>
|
||||
|
||||
<!-- Drag/Pan the viewport -->
|
||||
<input type="image" alt="viewport drag" src="app/images/drag.svg"
|
||||
|
@ -304,7 +304,7 @@
|
|||
</div>
|
||||
|
||||
<div id="noVNC_container">
|
||||
<h1 id="noVNC_logo" class="noVNC_logo"><span>no</span><br />VNC</h1>
|
||||
<h1 id="noVNC_logo" class="noVNC_logo" translate="no"><span>no</span><br />VNC</h1>
|
||||
|
||||
<!-- HTML5 Canvas -->
|
||||
<div id="noVNC_screen">
|
||||
|
|
Loading…
Reference in New Issue