167 lines
5.1 KiB
TypeScript
167 lines
5.1 KiB
TypeScript
/*
|
|
This file is part of TALER
|
|
(C) 2016 GNUnet e.V.
|
|
|
|
TALER is free software; you can redistribute it and/or modify it under the
|
|
terms of the GNU General Public License as published by the Free Software
|
|
Foundation; either version 3, or (at your option) any later version.
|
|
|
|
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
|
|
/**
|
|
* Generate .po file from list of source files.
|
|
*/
|
|
|
|
/// <reference path="../lib/decl/node.d.ts" />
|
|
|
|
"use strict";
|
|
|
|
import {readFileSync} from "fs";
|
|
import {execSync} from "child_process";
|
|
import * as ts from "typescript";
|
|
|
|
|
|
function wordwrap(str: string, width: number = 80): string[] {
|
|
var regex = '.{1,' + width + '}(\\s|$)|\\S+(\\s|$)';
|
|
return str.match(RegExp(regex, 'g'));
|
|
}
|
|
|
|
export function processFile(sourceFile: ts.SourceFile) {
|
|
processNode(sourceFile);
|
|
let lastTokLine = 0;
|
|
let preLastTokLine = 0;
|
|
|
|
function getHeadName(node: ts.Node): string {
|
|
switch (node.kind) {
|
|
case ts.SyntaxKind.Identifier:
|
|
return (<ts.Identifier>node).text;
|
|
case ts.SyntaxKind.CallExpression:
|
|
case ts.SyntaxKind.PropertyAccessExpression:
|
|
return getHeadName((<any>node).expression);
|
|
}
|
|
}
|
|
|
|
function getTemplate(node: ts.Node): string {
|
|
switch (node.kind) {
|
|
case ts.SyntaxKind.FirstTemplateToken:
|
|
return (<any>node).text;
|
|
case ts.SyntaxKind.TemplateExpression:
|
|
let te = <ts.TemplateExpression>node;
|
|
let textFragments = [te.head.text];
|
|
for (let tsp of te.templateSpans) {
|
|
textFragments.push(`{${(textFragments.length-1)/2}}`);
|
|
textFragments.push(tsp.literal.text);
|
|
}
|
|
return textFragments.join('');
|
|
default:
|
|
return "(pogen.ts: unable to parse)";
|
|
}
|
|
}
|
|
|
|
function getComment(node: ts.Node, lc): string {
|
|
let lastComments;
|
|
for (let l = preLastTokLine; l < lastTokLine; l++) {
|
|
let pos = ts.getPositionOfLineAndCharacter(sourceFile, l, 0);
|
|
let comments = ts.getTrailingCommentRanges(sourceFile.text, pos);
|
|
if (comments) {
|
|
lastComments = comments;
|
|
}
|
|
}
|
|
if (!lastComments) {
|
|
return;
|
|
}
|
|
let candidate = lastComments[lastComments.length-1];
|
|
let candidateEndLine = ts.getLineAndCharacterOfPosition(sourceFile, candidate.end).line;
|
|
if (candidateEndLine != lc.line -1) {
|
|
return;
|
|
}
|
|
let text = sourceFile.text.slice(candidate.pos, candidate.end);
|
|
switch (candidate.kind) {
|
|
case ts.SyntaxKind.SingleLineCommentTrivia:
|
|
text = text.replace(/^[/][/]\s*/, "");
|
|
break;
|
|
case ts.SyntaxKind.MultiLineCommentTrivia:
|
|
text = text
|
|
.replace(/^[/][*](\s*?\n|\s*)?/, "")
|
|
.replace(/(\n[ \t]*?)?[*][/]$/, "");
|
|
break;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
function processNode(node: ts.Node) {
|
|
switch (node.kind) {
|
|
case ts.SyntaxKind.TaggedTemplateExpression:
|
|
let lc = ts.getLineAndCharacterOfPosition(sourceFile, node.pos);
|
|
if (lc.line != lastTokLine) {
|
|
preLastTokLine = lastTokLine;
|
|
lastTokLine = lc.line;
|
|
}
|
|
let tte = <ts.TaggedTemplateExpression>node;
|
|
let headName = getHeadName(tte.tag);
|
|
let comment = getComment(tte, lc);
|
|
let tpl = getTemplate(tte.template).replace(/"/g, '\\"');
|
|
let parts = tpl
|
|
.match(/(.*\n|.+$)/g)
|
|
.map((x) => x.replace(/\n/g, '\\n'))
|
|
.map((p) => wordwrap(p))
|
|
.reduce((a,b) => a.concat(b));
|
|
if (comment) {
|
|
for (let cl of comment.split('\n')) {
|
|
console.log(`#. ${cl}`);
|
|
}
|
|
}
|
|
console.log(`#: ${sourceFile.fileName}:${lc.line+1}`);
|
|
console.log(`#, csharp-format`);
|
|
if (parts.length == 1) {
|
|
console.log(`msgid "${parts[0]}"`);
|
|
} else {
|
|
console.log(`msgid ""`);
|
|
for (let p of parts) {
|
|
console.log(`"${p}"`);
|
|
}
|
|
}
|
|
console.log(`msgstr ""`);
|
|
console.log();
|
|
break;
|
|
}
|
|
|
|
ts.forEachChild(node, processNode);
|
|
}
|
|
}
|
|
|
|
const fileNames = process.argv.slice(2);
|
|
|
|
console.log(
|
|
`# SOME DESCRIPTIVE TITLE.
|
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
# This file is distributed under the same license as the PACKAGE package.
|
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
#
|
|
#, fuzzy
|
|
msgid ""
|
|
msgstr ""
|
|
"Project-Id-Version: PACKAGE VERSION\\n"
|
|
"Report-Msgid-Bugs-To: \\n"
|
|
"POT-Creation-Date: ${execSync("date '+%F %H:%M%z'").toString().trim()}\\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"
|
|
"Language: \\n"
|
|
"MIME-Version: 1.0\\n"
|
|
"Content-Type: text/plain; charset=CHARSET\\n"
|
|
"Content-Transfer-Encoding: 8bit\\n"`);
|
|
console.log()
|
|
|
|
fileNames.forEach(fileName => {
|
|
let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
|
|
processFile(sourceFile);
|
|
});
|