aboutsummaryrefslogtreecommitdiff
path: root/pogen
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-09-26 22:46:38 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-09-26 22:46:38 +0200
commit2a2833f96f341a2a7566093fa1f1d973dd64ded5 (patch)
treee2a39117333f140960b6ade524387ad079f7cd0f /pogen
parentca8f32ad62d4d3377f5d190deb190913ae3b52a4 (diff)
Add pluralization to ts pogen
Diffstat (limited to 'pogen')
-rw-r--r--pogen/example/test.ts8
-rw-r--r--pogen/pogen.ts142
2 files changed, 120 insertions, 30 deletions
diff --git a/pogen/example/test.ts b/pogen/example/test.ts
index 2cc15b063..ffb01e0b9 100644
--- a/pogen/example/test.ts
+++ b/pogen/example/test.ts
@@ -20,7 +20,9 @@ It has multiple lines, and a trailing empty line.
console.log(/*lol*/i18n.foo`Hello7,${123} World${42}`);
-i18n.plural()
+i18n.plural(i18n`one ${"foo"}`, i18`many ${"bar"}`);
+
+i18n.plural(i18n.foo`one bla ${"foo"}`, i18.foo`many bla ${"bar"}`);
console.log(i18n`${"foo"}Hello8,${123} World${42}`);
@@ -45,6 +47,10 @@ it should be wrapped and stuff`);
// This is a single line comment
console.log(i18n`Hello12 this is a long long string it will go over multiple lines and in the pofile it should be wrapped and stuff. asdf asdf asdf asdf asdf asdf asdf asdf adsf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf`);
+function foo(...args: any[]) {
+}
+
+console.log(foo`Another string, must be excluded`);
// First occurence
diff --git a/pogen/pogen.ts b/pogen/pogen.ts
index 086066d3c..32e786b0c 100644
--- a/pogen/pogen.ts
+++ b/pogen/pogen.ts
@@ -70,7 +70,8 @@ export function processFile(sourceFile: ts.SourceFile) {
}
}
- function getComment(node: ts.Node, lc): string {
+ function getComment(node: ts.Node): string {
+ let lc = ts.getLineAndCharacterOfPosition(sourceFile, node.pos);
let lastComments;
for (let l = preLastTokLine; l < lastTokLine; l++) {
let pos = ts.getPositionOfLineAndCharacter(sourceFile, l, 0);
@@ -104,42 +105,125 @@ export function processFile(sourceFile: ts.SourceFile) {
return text;
}
+ function getPath(node: ts.Node): string[] {
+ switch (node.kind) {
+ case ts.SyntaxKind.PropertyAccessExpression:
+ let pae = <ts.PropertyAccessExpression>node;
+ return Array.prototype.concat(getPath(pae.expression), [pae.name.text]);
+ case ts.SyntaxKind.Identifier:
+ let id = <ts.Identifier>node;
+ return [id.text];
+ }
+ return ["(other)"];
+ }
+
+ function arrayEq<T>(a1: T[], a2: T[]) {
+ if (a1.length != a2.length) {
+ return false;
+ }
+ for (let i = 0; i < a1.length; i++) {
+ if (a1[i] != a2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ interface TemplateResult {
+ comment: string;
+ path: string[];
+ template: string;
+ line: number;
+ }
+
+ function processTaggedTemplateExpression(tte: ts.TaggedTemplateExpression): TemplateResult {
+ let lc = ts.getLineAndCharacterOfPosition(sourceFile, tte.pos);
+ if (lc.line != lastTokLine) {
+ preLastTokLine = lastTokLine;
+ lastTokLine = lc.line;
+ }
+ let path = getPath(tte.tag)
+ let res: TemplateResult = {
+ path,
+ line: lc.line,
+ comment: getComment(tte),
+ template: getTemplate(tte.template).replace(/"/g, '\\"'),
+ };
+ return res;
+ }
+
+ function formatMsgComment(line: number, comment?: string) {
+ if (comment) {
+ for (let cl of comment.split('\n')) {
+ console.log(`#. ${cl}`);
+ }
+ }
+ console.log(`#: ${sourceFile.fileName}:${line+1}`);
+ console.log(`#, c-format`);
+ }
+
+ function formatMsgLine(head: string, msg: string) {
+ // Do escaping, wrap break at newlines
+ let parts = msg
+ .match(/(.*\n|.+$)/g)
+ .map((x) => x.replace(/\n/g, '\\n'))
+ .map((p) => wordwrap(p))
+ .reduce((a,b) => a.concat(b));
+ if (parts.length == 1) {
+ console.log(`${head} "${parts[0]}"`);
+ } else {
+ console.log(`${head} ""`);
+ for (let p of parts) {
+ console.log(`"${p}"`);
+ }
+ }
+ }
+
+
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;
+ case ts.SyntaxKind.CallExpression:
+ {
+ // might be i18n.plural(i18n[.X]`...`, i18n[.X]`...`)
+ let ce = <ts.CallExpression>node;
+ let path = getPath(ce.expression);
+ if (!arrayEq(path, ["i18n", "plural"])) {
+ break;
}
- let tte = <ts.TaggedTemplateExpression>node;
- let headName = getHeadName(tte.tag);
- let comment = getComment(tte, lc);
- let tpl = getTemplate(tte.template).replace(/"/g, '\\"');
- // Do escaping, wrap break at newlines
- 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}`);
- }
+ if (ce.arguments[0].kind != ts.SyntaxKind.TaggedTemplateExpression) {
+ break;
}
- console.log(`#: ${sourceFile.fileName}:${lc.line+1}`);
- console.log(`#, c-format`);
- if (parts.length == 1) {
- console.log(`msgid "${parts[0]}"`);
- } else {
- console.log(`msgid ""`);
- for (let p of parts) {
- console.log(`"${p}"`);
- }
+ if (ce.arguments[1].kind != ts.SyntaxKind.TaggedTemplateExpression) {
+ break;
}
+ let comment = getComment(ce);
+ let {line} = ts.getLineAndCharacterOfPosition(sourceFile, ce.pos);
+ let t1 = processTaggedTemplateExpression(<ts.TaggedTemplateExpression>ce.arguments[0]);
+ let t2 = processTaggedTemplateExpression(<ts.TaggedTemplateExpression>ce.arguments[1]);
+
+ formatMsgComment(line, comment);
+ formatMsgLine("msgid", t1.template);
+ formatMsgLine("msgid_plural", t2.template);
+ console.log(`msgstr[0] ""`);
+ console.log(`msgstr[1] ""`);
+ console.log();
+
+ // Important: no processing for child i18n expressions here
+ return;
+ }
+ case ts.SyntaxKind.TaggedTemplateExpression:
+ {
+ let tte = <ts.TaggedTemplateExpression>node;
+ let {comment, template, line, path} = processTaggedTemplateExpression(tte);
+ if (path[0] != "i18n") {
+ break;
+ }
+ formatMsgComment(line, comment);
+ formatMsgLine("msgid", template);
console.log(`msgstr ""`);
console.log();
break;
+ }
}
ts.forEachChild(node, processNode);