| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- #!/usr/bin/env node
- /*
- * xgettext-html: HTML gettext parser
- * Copyright (C) 2018 The noVNC Authors
- * Licensed under MPL 2.0 (see LICENSE.txt)
- */
- const getopt = require('node-getopt');
- const jsdom = require("jsdom");
- const fs = require("fs");
- const opt = getopt.create([
- ['o', 'output=FILE', 'write output to specified file'],
- ['h', 'help', 'display this help'],
- ]).bindHelp().parseSystem();
- const 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", "submit"])) {
- addString(elem.getAttribute("value"), locator(elem));
- }
- }
- for (let i = 0; i < elem.childNodes.length; i++) {
- let 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 (let i = 0; i < opt.argv.length; i++) {
- const fn = opt.argv[i];
- const file = fs.readFileSync(fn, "utf8");
- const dom = new jsdom.JSDOM(file, { includeNodeLocations: true });
- const body = dom.window.document.body;
- let locator = (elem) => {
- const offset = dom.nodeLocation(elem).startOffset;
- const line = file.slice(0, offset).split("\n").length;
- return fn + ":" + line;
- };
- process(body, locator, true);
- }
- let output = "";
- for (let 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);
|