You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
| #!/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);
 |