diff --git a/packages/pogen/package.json b/packages/pogen/package.json
index 763edca78..04c7ba1c0 100644
--- a/packages/pogen/package.json
+++ b/packages/pogen/package.json
@@ -11,6 +11,7 @@
"compile": "tsc"
},
"devDependencies": {
+ "po2json": "^0.4.5",
"typescript": "^4.5.5"
},
"dependencies": {
diff --git a/packages/pogen/po2.js b/packages/pogen/po2.js
deleted file mode 100644
index 532a1522f..000000000
--- a/packages/pogen/po2.js
+++ /dev/null
@@ -1,32 +0,0 @@
-const ts = require("typescript");
-
-const configPath = ts.findConfigFile(
- /*searchPath*/ "./",
- ts.sys.fileExists,
- "tsconfig.json"
- );
-if (!configPath) {
- throw new Error("Could not find a valid 'tsconfig.json'.");
-}
-
-console.log(configPath);
-
-const cmdline = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
- fileExists: ts.sys.fileExists,
- getCurrentDirectory: ts.sys.getCurrentDirectory,
- onUnRecoverableConfigFileDiagnostic: (e) => console.log(e),
- readDirectory: ts.sys.readDirectory,
- readFile: ts.sys.readFile,
- useCaseSensitiveFileNames: true,
-})
-
-console.log(cmdline);
-
-const prog = ts.createProgram({
- options: cmdline.options,
- rootNames: cmdline.fileNames,
-});
-
-const allFiles = prog.getSourceFiles();
-
-console.log(allFiles.map(x => x.path));
\ No newline at end of file
diff --git a/packages/pogen/dumpTree.ts b/packages/pogen/src/dumpTree.ts
similarity index 100%
rename from packages/pogen/dumpTree.ts
rename to packages/pogen/src/dumpTree.ts
diff --git a/packages/pogen/src/po2ts.ts b/packages/pogen/src/po2ts.ts
new file mode 100644
index 000000000..d0f4ed34d
--- /dev/null
+++ b/packages/pogen/src/po2ts.ts
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU 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.
+
+ GNU 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
+ GNU Taler; see the file COPYING. If not, see
+ */
+
+/**
+ * Convert a .po file into a JavaScript / TypeScript expression.
+ */
+
+// @ts-ignore
+import * as po2json from "po2json";
+import * as fs from "fs";
+import * as path from "path";
+
+const files = fs
+ .readdirSync("./src/i18n")
+ .filter((x) => x.endsWith(".po"))
+ .map((x) => path.join("./src/i18n/", x));
+
+if (files.length === 0) {
+ console.error("no .po files found in src/i18n/");
+ process.exit(1);
+}
+
+console.log(files);
+
+const chunks: string[] = [];
+
+for (const filename of files) {
+ const m = filename.match(/([a-zA-Z0-9-_]+).po/);
+
+ if (!m) {
+ console.error("error: unexpected filename (expected .po)");
+ process.exit(1);
+ }
+
+ const lang = m[1];
+ const pojson = po2json.parseFileSync(filename, {
+ format: "jed1.x",
+ fuzzy: true,
+ });
+ const s =
+ "strings['" + lang + "'] = " + JSON.stringify(pojson, null, " ") + ";\n\n";
+ chunks.push(s);
+}
+
+const tsContents = chunks.join("");
+
+fs.writeFileSync("src/i18n/strings.ts", tsContents);
diff --git a/packages/pogen/pogen.ts b/packages/pogen/src/potextract.ts
similarity index 81%
rename from packages/pogen/pogen.ts
rename to packages/pogen/src/potextract.ts
index 23ac389f4..5999d9e1c 100644
--- a/packages/pogen/pogen.ts
+++ b/packages/pogen/src/potextract.ts
@@ -1,32 +1,23 @@
/*
- This file is part of TALER
- (C) 2016 GNUnet e.V.
+ This file is part of GNU Taler
+ (C) 2019-2022 Taler Systems S.A.
- TALER is free software; you can redistribute it and/or modify it under the
+ GNU 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
+ GNU 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, see
+ GNU Taler; see the file COPYING. If not, see
*/
-/**
- * Generate .po file from list of source files.
- *
- * Note that duplicate message IDs are NOT merged, to get the same output as
- * you would from xgettext, just run msguniq.
- *
- * @author Florian Dold
- */
/**
* Imports.
*/
-import { readFileSync } from "fs";
import * as ts from "typescript";
function wordwrap(str: string, width: number = 80): string[] {
@@ -34,7 +25,7 @@ function wordwrap(str: string, width: number = 80): string[] {
return str.match(RegExp(regex, "g"));
}
-export function processFile(sourceFile: ts.SourceFile) {
+export function processFile(sourceFile: ts.SourceFile, outChunks: string[]) {
processNode(sourceFile);
let lastTokLine = 0;
let preLastTokLine = 0;
@@ -146,11 +137,11 @@ export function processFile(sourceFile: ts.SourceFile) {
function formatMsgComment(line: number, comment?: string) {
if (comment) {
for (let cl of comment.split("\n")) {
- console.log(`#. ${cl}`);
+ outChunks.push(`#. ${cl}\n`);
}
}
- console.log(`#: ${sourceFile.fileName}:${line + 1}`);
- console.log(`#, c-format`);
+ outChunks.push(`#: ${sourceFile.fileName}:${line + 1}\n`);
+ outChunks.push(`#, c-format\n`);
}
function formatMsgLine(head: string, msg: string) {
@@ -161,11 +152,11 @@ export function processFile(sourceFile: ts.SourceFile) {
.map((p) => wordwrap(p))
.reduce((a, b) => a.concat(b));
if (parts.length == 1) {
- console.log(`${head} "${parts[0]}"`);
+ outChunks.push(`${head} "${parts[0]}"\n`);
} else {
- console.log(`${head} ""`);
+ outChunks.push(`${head} ""\n`);
for (let p of parts) {
- console.log(`"${p}"`);
+ outChunks.push(`"${p}"\n`);
}
}
}
@@ -208,7 +199,7 @@ export function processFile(sourceFile: ts.SourceFile) {
switch (childNode.kind) {
case ts.SyntaxKind.JsxText: {
let e = childNode as ts.JsxText;
- let s = e.getFullText();
+ let s = e.text;
let t = s.split("\n").map(trim).join(" ");
if (s[0] === " ") {
t = " " + t;
@@ -295,8 +286,8 @@ export function processFile(sourceFile: ts.SourceFile) {
let comment = getComment(node);
formatMsgComment(line, comment);
formatMsgLine("msgid", content);
- console.log(`msgstr ""`);
- console.log();
+ outChunks.push(`msgstr ""\n`);
+ outChunks.push("\n");
return;
}
if (arrayEq(path, ["i18n", "TranslateSwitch"])) {
@@ -315,9 +306,9 @@ export function processFile(sourceFile: ts.SourceFile) {
}
formatMsgLine("msgid", singularForm);
formatMsgLine("msgid_plural", pluralForm);
- console.log(`msgstr[0] ""`);
- console.log(`msgstr[1] ""`);
- console.log();
+ outChunks.push(`msgstr[0] ""\n`);
+ outChunks.push(`msgstr[1] ""\n`);
+ outChunks.push(`\n`);
return;
}
break;
@@ -346,25 +337,24 @@ export function processFile(sourceFile: ts.SourceFile) {
formatMsgComment(line, comment);
formatMsgLine("msgid", t1.template);
formatMsgLine("msgid_plural", t2.template);
- console.log(`msgstr[0] ""`);
- console.log(`msgstr[1] ""`);
- console.log();
+ outChunks.push(`msgstr[0] ""\n`);
+ outChunks.push(`msgstr[1] ""\n`);
+ outChunks.push("\n");
// Important: no processing for child i18n expressions here
return;
}
case ts.SyntaxKind.TaggedTemplateExpression: {
let tte = node;
- let { comment, template, line, path } = processTaggedTemplateExpression(
- tte,
- );
+ let { comment, template, line, path } =
+ processTaggedTemplateExpression(tte);
if (path[0] != "i18n") {
break;
}
formatMsgComment(line, comment);
formatMsgLine("msgid", template);
- console.log(`msgstr ""`);
- console.log();
+ outChunks.push(`msgstr ""\n`);
+ outChunks.push("\n");
break;
}
}
@@ -373,36 +363,51 @@ export function processFile(sourceFile: ts.SourceFile) {
}
}
-export function main() {
- const configPath = ts.findConfigFile(
- /*searchPath*/ "./",
- ts.sys.fileExists,
- "tsconfig.json",
- );
- if (!configPath) {
- throw new Error("Could not find a valid 'tsconfig.json'.");
- }
+const configPath = ts.findConfigFile(
+ /*searchPath*/ "./",
+ ts.sys.fileExists,
+ "tsconfig.json",
+);
+if (!configPath) {
+ throw new Error("Could not find a valid 'tsconfig.json'.");
+}
- const cmdline = ts.getParsedCommandLineOfConfigFile(
- configPath,
- {},
- {
- fileExists: ts.sys.fileExists,
- getCurrentDirectory: ts.sys.getCurrentDirectory,
- onUnRecoverableConfigFileDiagnostic: (e) => console.log(e),
- readDirectory: ts.sys.readDirectory,
- readFile: ts.sys.readFile,
- useCaseSensitiveFileNames: true,
- },
- );
+console.log(configPath);
- const fileNames = cmdline.fileNames;
+const cmdline = ts.getParsedCommandLineOfConfigFile(
+ configPath,
+ {},
+ {
+ fileExists: ts.sys.fileExists,
+ getCurrentDirectory: ts.sys.getCurrentDirectory,
+ onUnRecoverableConfigFileDiagnostic: (e) => console.log(e),
+ readDirectory: ts.sys.readDirectory,
+ readFile: ts.sys.readFile,
+ useCaseSensitiveFileNames: true,
+ },
+);
- fileNames.sort();
+console.log(cmdline);
- const outChunks: string[] = [];
+const prog = ts.createProgram({
+ options: cmdline.options,
+ rootNames: cmdline.fileNames,
+});
- outChunks.push(`# SOME DESCRIPTIVE TITLE.
+const allFiles = prog.getSourceFiles();
+
+const ownFiles = allFiles.filter(
+ (x) =>
+ !x.isDeclarationFile &&
+ !prog.isSourceFileFromExternalLibrary(x) &&
+ !prog.isSourceFileDefaultLibrary(x),
+);
+
+console.log(ownFiles.map((x) => x.fileName));
+
+const chunks = [];
+
+chunks.push(`# 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 , YEAR.
@@ -421,16 +426,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\\n"
"Content-Transfer-Encoding: 8bit\\n"`);
- fileNames.forEach((fileName) => {
- let sourceFile = ts.createSourceFile(
- fileName,
- readFileSync(fileName).toString(),
- ts.ScriptTarget.ES2016,
- /*setParentNodes */ true,
- );
- processFile(sourceFile);
- });
-
- const out = outChunks.join("");
- console.log(out);
+for (const f of ownFiles) {
+ processFile(f, chunks);
}
+
+console.log(chunks.join(""));
diff --git a/packages/pogen/tsconfig.json b/packages/pogen/tsconfig.json
index d51c5326e..68225832d 100644
--- a/packages/pogen/tsconfig.json
+++ b/packages/pogen/tsconfig.json
@@ -10,5 +10,5 @@
"lib": ["es6"],
"types": ["node"]
},
- "files": ["pogen.ts"]
+ "include": ["src/**/*.ts"]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6353ef5fb..d1832bf90 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -150,10 +150,12 @@ importers:
packages/pogen:
specifiers:
'@types/node': ^17.0.17
+ po2json: ^0.4.5
typescript: ^4.5.5
dependencies:
'@types/node': 17.0.17
devDependencies:
+ po2json: 0.4.5
typescript: 4.5.5
packages/taler-util: