@esgettext/tools 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/command.js +0 -1
- package/dist/commands/add-language.js +100 -0
- package/dist/commands/convert.js +17 -15
- package/dist/commands/init.js +743 -0
- package/dist/commands/install.js +21 -6
- package/dist/commands/msgfmt-all.js +72 -50
- package/dist/commands/msgmerge-all.js +71 -49
- package/dist/commands/potfiles.js +165 -0
- package/dist/commands/xgettext/file-resolver.js +0 -1
- package/dist/commands/xgettext/files-collector.js +1 -1
- package/dist/commands/xgettext.js +37 -17
- package/dist/configuration.js +174 -115
- package/dist/esgettext-package-json.js +0 -1
- package/dist/index.js +97 -29
- package/dist/optspec.js +28 -0
- package/dist/package.js +4 -2
- package/dist/parser/javascript.js +2 -1
- package/dist/parser/parser.js +17 -2
- package/dist/parser/po.js +34 -1
- package/dist/parser/typescript.js +2 -1
- package/dist/pot/catalog.js +36 -1
- package/dist/pot/entry.js +71 -1
- package/dist/pot/keyword.js +10 -5
- package/package.json +11 -6
- package/dist/command.d.ts +0 -11
- package/dist/command.js.map +0 -1
- package/dist/commands/convert.d.ts +0 -24
- package/dist/commands/convert.js.map +0 -1
- package/dist/commands/install.d.ts +0 -22
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/msgfmt-all.d.ts +0 -20
- package/dist/commands/msgfmt-all.js.map +0 -1
- package/dist/commands/msgmerge-all.d.ts +0 -21
- package/dist/commands/msgmerge-all.js.map +0 -1
- package/dist/commands/xgettext/file-resolver.d.ts +0 -5
- package/dist/commands/xgettext/file-resolver.js.map +0 -1
- package/dist/commands/xgettext/file-resolver.spec.d.ts +0 -1
- package/dist/commands/xgettext/file-resolver.spec.js +0 -22
- package/dist/commands/xgettext/file-resolver.spec.js.map +0 -1
- package/dist/commands/xgettext/files-collector.d.ts +0 -5
- package/dist/commands/xgettext/files-collector.js.map +0 -1
- package/dist/commands/xgettext/files-collector.spec.d.ts +0 -1
- package/dist/commands/xgettext/files-collector.spec.js +0 -96
- package/dist/commands/xgettext/files-collector.spec.js.map +0 -1
- package/dist/commands/xgettext.d.ts +0 -29
- package/dist/commands/xgettext.js.map +0 -1
- package/dist/commands/xgettext.spec.d.ts +0 -1
- package/dist/commands/xgettext.spec.js +0 -897
- package/dist/commands/xgettext.spec.js.map +0 -1
- package/dist/configuration.d.ts +0 -36
- package/dist/configuration.js.map +0 -1
- package/dist/esgettext-package-json.d.ts +0 -15
- package/dist/esgettext-package-json.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/package.d.ts +0 -5
- package/dist/package.js.map +0 -1
- package/dist/parser/javascript.d.ts +0 -4
- package/dist/parser/javascript.js.map +0 -1
- package/dist/parser/javascript.spec.d.ts +0 -1
- package/dist/parser/javascript.spec.js +0 -535
- package/dist/parser/javascript.spec.js.map +0 -1
- package/dist/parser/parser.d.ts +0 -45
- package/dist/parser/parser.js.map +0 -1
- package/dist/parser/po.d.ts +0 -22
- package/dist/parser/po.js.map +0 -1
- package/dist/parser/po.spec.d.ts +0 -1
- package/dist/parser/po.spec.js +0 -486
- package/dist/parser/po.spec.js.map +0 -1
- package/dist/parser/typescript.d.ts +0 -4
- package/dist/parser/typescript.js.map +0 -1
- package/dist/parser/typescript.spec.d.ts +0 -1
- package/dist/parser/typescript.spec.js +0 -121
- package/dist/parser/typescript.spec.js.map +0 -1
- package/dist/pot/catalog.d.ts +0 -26
- package/dist/pot/catalog.js.map +0 -1
- package/dist/pot/catalog.spec.d.ts +0 -1
- package/dist/pot/catalog.spec.js +0 -244
- package/dist/pot/catalog.spec.js.map +0 -1
- package/dist/pot/entry.d.ts +0 -35
- package/dist/pot/entry.js.map +0 -1
- package/dist/pot/entry.spec.d.ts +0 -1
- package/dist/pot/entry.spec.js +0 -433
- package/dist/pot/entry.spec.js.map +0 -1
- package/dist/pot/keyword.d.ts +0 -17
- package/dist/pot/keyword.js.map +0 -1
- package/dist/pot/keyword.spec.d.ts +0 -1
- package/dist/pot/keyword.spec.js +0 -54
- package/dist/pot/keyword.spec.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,56 +1,91 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
3
12
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
14
|
};
|
|
6
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
16
|
const yargs_1 = __importDefault(require("yargs"));
|
|
8
|
-
const
|
|
17
|
+
const package_js_1 = require("./package.js");
|
|
9
18
|
const runtime_1 = require("@esgettext/runtime");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
19
|
+
const configuration_js_1 = require("./configuration.js");
|
|
20
|
+
const xgettext_js_1 = require("./commands/xgettext.js");
|
|
21
|
+
const msgmerge_all_js_1 = require("./commands/msgmerge-all.js");
|
|
22
|
+
const install_js_1 = require("./commands/install.js");
|
|
23
|
+
const convert_js_1 = require("./commands/convert.js");
|
|
24
|
+
const msgfmt_all_js_1 = require("./commands/msgfmt-all.js");
|
|
25
|
+
const init_js_1 = require("./commands/init.js");
|
|
26
|
+
const potfiles_js_1 = require("./commands/potfiles.js");
|
|
27
|
+
const add_language_js_1 = require("./commands/add-language.js");
|
|
16
28
|
const commandNames = [
|
|
17
|
-
'
|
|
18
|
-
'msgmerge-all',
|
|
19
|
-
'msgfmt-all',
|
|
20
|
-
'install',
|
|
29
|
+
'add-language',
|
|
21
30
|
'convert',
|
|
31
|
+
'install',
|
|
32
|
+
'init',
|
|
33
|
+
'msgfmt-all',
|
|
34
|
+
'msgmerge-all',
|
|
35
|
+
'potfiles',
|
|
36
|
+
'xgettext',
|
|
22
37
|
];
|
|
38
|
+
const configFiles = locateConfigFiles();
|
|
39
|
+
const pkgJsonFile = locatePkgJsonFile();
|
|
23
40
|
const gtx = runtime_1.Textdomain.getInstance('com.cantanea.esgettext-tools');
|
|
24
41
|
gtx
|
|
25
42
|
.resolve()
|
|
26
|
-
.then(
|
|
43
|
+
.then(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
var _a;
|
|
27
45
|
const locale = runtime_1.Textdomain.selectLocale(['en-US', 'en-GB', 'de']);
|
|
28
46
|
const ulocale = locale.replace('-', '_');
|
|
29
|
-
const configuration =
|
|
47
|
+
const configuration = yield configuration_js_1.ConfigurationFactory.create(configFiles, pkgJsonFile, locale);
|
|
30
48
|
if (!configuration)
|
|
31
49
|
process.exit(1);
|
|
32
50
|
const commands = {
|
|
33
|
-
xgettext: new
|
|
34
|
-
'msgmerge-all': new
|
|
35
|
-
'msgfmt-all': new
|
|
36
|
-
install: new
|
|
37
|
-
convert: new
|
|
51
|
+
xgettext: new xgettext_js_1.XGettext(configuration),
|
|
52
|
+
'msgmerge-all': new msgmerge_all_js_1.MsgmergeAll(configuration),
|
|
53
|
+
'msgfmt-all': new msgfmt_all_js_1.MsgfmtAll(configuration),
|
|
54
|
+
install: new install_js_1.Install(configuration),
|
|
55
|
+
convert: new convert_js_1.Convert(configuration),
|
|
56
|
+
init: new init_js_1.Init(configuration),
|
|
57
|
+
potfiles: new potfiles_js_1.Potfiles(configuration),
|
|
58
|
+
'add-language': new add_language_js_1.AddLanguage(configuration),
|
|
38
59
|
};
|
|
39
60
|
const program = (0, yargs_1.default)(process.argv.slice(2))
|
|
40
61
|
.locale(ulocale)
|
|
41
62
|
.strict()
|
|
63
|
+
.options({
|
|
64
|
+
configuration: {
|
|
65
|
+
alias: ['config-file'],
|
|
66
|
+
type: 'string',
|
|
67
|
+
describe: gtx._('Path to configuration file'),
|
|
68
|
+
default: 'esgettext.config.{mjs,cjs,js,json}',
|
|
69
|
+
},
|
|
70
|
+
package: {
|
|
71
|
+
alias: ['package-json'],
|
|
72
|
+
type: 'string',
|
|
73
|
+
describe: gtx._("Path to 'package.json'"),
|
|
74
|
+
default: 'package.json',
|
|
75
|
+
},
|
|
76
|
+
})
|
|
42
77
|
.showHelpOnFail(false, gtx._x("Try {programName} '--help' for more information!", {
|
|
43
|
-
programName:
|
|
78
|
+
programName: package_js_1.Package.getName(),
|
|
44
79
|
}))
|
|
45
80
|
.demandCommand(1, gtx._('Error: No command given.'))
|
|
46
|
-
.scriptName(
|
|
47
|
-
let epilogue = configuration.files.length
|
|
81
|
+
.scriptName(package_js_1.Package.getName());
|
|
82
|
+
let epilogue = ((_a = configuration.files) === null || _a === void 0 ? void 0 : _a.length)
|
|
48
83
|
? gtx._x('Additional defaults read from: {files}.', {
|
|
49
84
|
files: configuration.files.join(', '),
|
|
50
85
|
}) + '\n\n'
|
|
51
86
|
: '';
|
|
52
87
|
epilogue += gtx._x('Report bugs in the bugtracker at {url}!', {
|
|
53
|
-
url:
|
|
88
|
+
url: package_js_1.Package.getBugTrackerUrl(),
|
|
54
89
|
});
|
|
55
90
|
for (const name of commandNames) {
|
|
56
91
|
const command = commands[name];
|
|
@@ -66,19 +101,52 @@ gtx
|
|
|
66
101
|
command.additional(argv);
|
|
67
102
|
return argv.options(command.args());
|
|
68
103
|
},
|
|
69
|
-
handler:
|
|
70
|
-
argv._.shift();
|
|
71
|
-
const exitCode =
|
|
104
|
+
handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
105
|
+
argv._.shift(); // Remove the command name.
|
|
106
|
+
const exitCode = yield command.run(argv);
|
|
72
107
|
process.exit(exitCode);
|
|
73
|
-
},
|
|
108
|
+
}),
|
|
74
109
|
});
|
|
75
110
|
}
|
|
76
111
|
program.help().epilogue(epilogue).parse();
|
|
77
|
-
})
|
|
112
|
+
}))
|
|
78
113
|
.catch((exception) => {
|
|
79
114
|
console.error(gtx._x('{programName}: unhandled exception: {exception}'), {
|
|
80
|
-
programName:
|
|
115
|
+
programName: package_js_1.Package.getName(),
|
|
81
116
|
exception,
|
|
82
117
|
});
|
|
83
118
|
});
|
|
84
|
-
|
|
119
|
+
function getArgument(option) {
|
|
120
|
+
const longOption = '--' + option;
|
|
121
|
+
const longOptionRe = new RegExp(`^${longOption}=.+`);
|
|
122
|
+
const args = process.argv.slice(2);
|
|
123
|
+
for (const [index, arg] of args.entries()) {
|
|
124
|
+
if (arg == longOption && index < args.length) {
|
|
125
|
+
return args[index + 1];
|
|
126
|
+
}
|
|
127
|
+
else if (arg.match(longOptionRe)) {
|
|
128
|
+
return arg.substring(longOption.length + 1);
|
|
129
|
+
}
|
|
130
|
+
else if (arg[0] !== '-') {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
function locateConfigFiles() {
|
|
137
|
+
var _a;
|
|
138
|
+
const configFile = (_a = getArgument('config-file')) !== null && _a !== void 0 ? _a : getArgument('configuration');
|
|
139
|
+
return configFile !== null
|
|
140
|
+
? [configFile]
|
|
141
|
+
: [
|
|
142
|
+
'esgettext.config.mjs',
|
|
143
|
+
'esgettext.config.cjs',
|
|
144
|
+
'esgettext.config.js',
|
|
145
|
+
'esgettext.config.json',
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
function locatePkgJsonFile() {
|
|
149
|
+
var _a;
|
|
150
|
+
const configFile = (_a = getArgument('package')) !== null && _a !== void 0 ? _a : getArgument('package-json');
|
|
151
|
+
return configFile !== null ? configFile : 'package.json';
|
|
152
|
+
}
|
package/dist/optspec.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.coerceOptions = void 0;
|
|
4
|
+
const runtime_1 = require("@esgettext/runtime");
|
|
5
|
+
const package_1 = require("./package");
|
|
6
|
+
const gtx = runtime_1.Textdomain.getInstance('com.cantanea.esgettext-tools');
|
|
7
|
+
function coerceOptions(args, optspecs) {
|
|
8
|
+
for (const optname in optspecs) {
|
|
9
|
+
const optspec = optspecs[optname];
|
|
10
|
+
const optkey = optname.replace(/-(.)/g, (_, group1) => group1.toUpperCase());
|
|
11
|
+
const arg = args[optkey];
|
|
12
|
+
const isArray = typeof arg === 'object' && Array.isArray(arg);
|
|
13
|
+
if (optspec.multi) {
|
|
14
|
+
if (typeof arg !== 'undefined' && !isArray) {
|
|
15
|
+
args[optkey] = [args[optkey]];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
if (isArray) {
|
|
20
|
+
console.error(gtx._x('{programName}: Error: The option' +
|
|
21
|
+
' {optname} cannot be specified more than once!', { programName: package_1.Package.getName(), optname }));
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
exports.coerceOptions = coerceOptions;
|
package/dist/package.js
CHANGED
|
@@ -9,8 +9,10 @@ class Package {
|
|
|
9
9
|
return 'https://github.com/gflohr/esgettext/issues';
|
|
10
10
|
}
|
|
11
11
|
static getVersion() {
|
|
12
|
-
return '1.
|
|
12
|
+
return '1.3.0';
|
|
13
|
+
}
|
|
14
|
+
static getNpmRunAllVersion() {
|
|
15
|
+
return '^4.1.5';
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
exports.Package = Package;
|
|
16
|
-
//# sourceMappingURL=package.js.map
|
|
@@ -11,6 +11,8 @@ class JavaScriptParser extends parser_2.Parser {
|
|
|
11
11
|
allowReturnOutsideFunction: true,
|
|
12
12
|
allowSuperOutsideMethod: true,
|
|
13
13
|
allowUndeclaredExports: true,
|
|
14
|
+
// Documented but not supported. FIXME! Maybe only missing in types.
|
|
15
|
+
// errorRecovery: true,
|
|
14
16
|
sourceFilename: filename,
|
|
15
17
|
plugins: [
|
|
16
18
|
'flow',
|
|
@@ -24,4 +26,3 @@ class JavaScriptParser extends parser_2.Parser {
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
exports.JavaScriptParser = JavaScriptParser;
|
|
27
|
-
//# sourceMappingURL=javascript.js.map
|
package/dist/parser/parser.js
CHANGED
|
@@ -38,6 +38,9 @@ class Parser {
|
|
|
38
38
|
constructor(catalog, options = {}) {
|
|
39
39
|
this.catalog = catalog;
|
|
40
40
|
this.options = options;
|
|
41
|
+
this.filename = '';
|
|
42
|
+
this.errors = 0;
|
|
43
|
+
this.comments = [];
|
|
41
44
|
this.keywords = {};
|
|
42
45
|
(options.keyword || Parser.cookedDefaultKeywords()).forEach(keyword => {
|
|
43
46
|
this.keywords[keyword.method] = keyword;
|
|
@@ -81,6 +84,7 @@ class Parser {
|
|
|
81
84
|
filename,
|
|
82
85
|
identifierName: null,
|
|
83
86
|
};
|
|
87
|
+
// Find the offending character.
|
|
84
88
|
for (let i = 0; i < pos; ++i) {
|
|
85
89
|
if (buf[i] === 10) {
|
|
86
90
|
++loc.start.line;
|
|
@@ -105,6 +109,7 @@ class Parser {
|
|
|
105
109
|
input = buf.toString();
|
|
106
110
|
}
|
|
107
111
|
else {
|
|
112
|
+
// Convert.
|
|
108
113
|
try {
|
|
109
114
|
input = (0, iconv_lite_1.decode)(buf, this.options.fromCode);
|
|
110
115
|
}
|
|
@@ -136,11 +141,15 @@ class Parser {
|
|
|
136
141
|
});
|
|
137
142
|
}
|
|
138
143
|
extractAllStrings(ast) {
|
|
144
|
+
// Step 1: Transform string concatenations into one string.
|
|
139
145
|
(0, traverse_1.default)(ast, {
|
|
140
146
|
StringLiteral: path => {
|
|
141
147
|
this.concatStrings(path);
|
|
142
148
|
},
|
|
143
149
|
});
|
|
150
|
+
// Step 2: Extract the remaining strings. Those that are part of a
|
|
151
|
+
// binary expression have not been recognized in step 1 and must be
|
|
152
|
+
// ignored.
|
|
144
153
|
(0, traverse_1.default)(ast, {
|
|
145
154
|
StringLiteral: path => {
|
|
146
155
|
if (!t.isBinaryExpression(path.parentPath.node)) {
|
|
@@ -165,7 +174,7 @@ class Parser {
|
|
|
165
174
|
return true;
|
|
166
175
|
}
|
|
167
176
|
checkInstance(instance) {
|
|
168
|
-
if (!this.
|
|
177
|
+
if (!this.instances) {
|
|
169
178
|
return true;
|
|
170
179
|
}
|
|
171
180
|
for (let i = 0; i < this.instances.length; ++i) {
|
|
@@ -197,6 +206,7 @@ class Parser {
|
|
|
197
206
|
if (!Object.prototype.hasOwnProperty.call(this.keywords, method)) {
|
|
198
207
|
return;
|
|
199
208
|
}
|
|
209
|
+
// Enough arguments?
|
|
200
210
|
const keywordSpec = this.keywords[method];
|
|
201
211
|
if (keywordSpec.totalArgs &&
|
|
202
212
|
path.node.arguments.length !== keywordSpec.totalArgs) {
|
|
@@ -347,12 +357,14 @@ class Parser {
|
|
|
347
357
|
else if (t.isMemberExpression(me.object) &&
|
|
348
358
|
t.isIdentifier(me.property) &&
|
|
349
359
|
!me.computed) {
|
|
360
|
+
// Recurse.
|
|
350
361
|
instance.push(me.property.name);
|
|
351
362
|
return this.methodFromMemberExpression(me.object, instance);
|
|
352
363
|
}
|
|
353
364
|
else if (t.isMemberExpression(me.object) &&
|
|
354
365
|
t.isLiteral(me.property) &&
|
|
355
366
|
me.computed) {
|
|
367
|
+
// Recurse.
|
|
356
368
|
instance.push(this.literalValue(me.property));
|
|
357
369
|
return this.methodFromMemberExpression(me.object, instance);
|
|
358
370
|
}
|
|
@@ -376,6 +388,8 @@ class Parser {
|
|
|
376
388
|
}
|
|
377
389
|
findPrecedingComments(loc) {
|
|
378
390
|
let last;
|
|
391
|
+
// Find the last relevant comment, which is the first one that
|
|
392
|
+
// immediately precedes the location.
|
|
379
393
|
for (last = 0; last < this.comments.length; ++last) {
|
|
380
394
|
const commentLocation = this.comments[last].loc;
|
|
381
395
|
if (commentLocation.end.line === loc.start.line ||
|
|
@@ -391,6 +405,7 @@ class Parser {
|
|
|
391
405
|
this.comments.splice(0, this.comments.length);
|
|
392
406
|
return [];
|
|
393
407
|
}
|
|
408
|
+
// Now go back and find all adjacent comments.
|
|
394
409
|
let ptr = this.comments[last].loc;
|
|
395
410
|
const preceding = this.comments.splice(0, last + 1);
|
|
396
411
|
if (!last) {
|
|
@@ -476,6 +491,7 @@ class Parser {
|
|
|
476
491
|
console.error(gtx._x('{location}: Error: {msg}', { location, msg }));
|
|
477
492
|
}
|
|
478
493
|
canonicalizeEncoding(encoding) {
|
|
494
|
+
// This is taken from iconv-lite.
|
|
479
495
|
const canonical = ('' + encoding)
|
|
480
496
|
.toLowerCase()
|
|
481
497
|
.replace(/:[0-9]{4}$|[^0-9a-z]/g, '');
|
|
@@ -592,4 +608,3 @@ class Parser {
|
|
|
592
608
|
}
|
|
593
609
|
}
|
|
594
610
|
exports.Parser = Parser;
|
|
595
|
-
//# sourceMappingURL=parser.js.map
|
package/dist/parser/po.js
CHANGED
|
@@ -7,6 +7,26 @@ const entry_1 = require("../pot/entry");
|
|
|
7
7
|
const parser_1 = require("./parser");
|
|
8
8
|
const gtx = runtime_1.Textdomain.getInstance('tools');
|
|
9
9
|
class PoParser extends parser_1.Parser {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
// All those get reset on each call to parse().
|
|
13
|
+
this.entry = undefined;
|
|
14
|
+
this.loc = undefined;
|
|
15
|
+
this.entryLoc = undefined;
|
|
16
|
+
this.msgType = undefined;
|
|
17
|
+
this.seen = {};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse a po file into a catalog. This parser is very forgiving and
|
|
21
|
+
* accepts input that actually does not follow the standard in certain
|
|
22
|
+
* areas.
|
|
23
|
+
*
|
|
24
|
+
* The encoding will always be read from the PO header if present.
|
|
25
|
+
*
|
|
26
|
+
* @param input - the content of the po file
|
|
27
|
+
* @param filename - the filename
|
|
28
|
+
* @param encoding - an optional encoding
|
|
29
|
+
*/
|
|
10
30
|
parse(buf, filename, encoding) {
|
|
11
31
|
if (typeof encoding !== 'undefined') {
|
|
12
32
|
if (!(0, iconv_lite_1.encodingExists)(encoding)) {
|
|
@@ -15,6 +35,7 @@ class PoParser extends parser_1.Parser {
|
|
|
15
35
|
}
|
|
16
36
|
}
|
|
17
37
|
const input = typeof encoding === 'undefined' ? buf.toString() : (0, iconv_lite_1.decode)(buf, encoding);
|
|
38
|
+
// Reset parser.
|
|
18
39
|
this.entry = undefined;
|
|
19
40
|
this.filename = filename;
|
|
20
41
|
this.loc = {
|
|
@@ -34,6 +55,8 @@ class PoParser extends parser_1.Parser {
|
|
|
34
55
|
this.msgType = undefined;
|
|
35
56
|
this.seen = {};
|
|
36
57
|
this.errors = 0;
|
|
58
|
+
// We cannot use forEach here because we may have to return from
|
|
59
|
+
// inside the loop.
|
|
37
60
|
const lines = input.split('\n');
|
|
38
61
|
for (let i = 0; i < lines.length; ++i) {
|
|
39
62
|
const line = lines[i];
|
|
@@ -48,6 +71,9 @@ class PoParser extends parser_1.Parser {
|
|
|
48
71
|
if (charset &&
|
|
49
72
|
(typeof encoding === 'undefined' ||
|
|
50
73
|
charset.toLowerCase() !== encoding.toLowerCase())) {
|
|
74
|
+
// FIXME! This must only happen, if the header is the first
|
|
75
|
+
// entry that has been added. Otherwise, we'll add the entries
|
|
76
|
+
// before this, twice.
|
|
51
77
|
return this.parse(buf, filename, charset);
|
|
52
78
|
}
|
|
53
79
|
}
|
|
@@ -99,6 +125,9 @@ class PoParser extends parser_1.Parser {
|
|
|
99
125
|
if (charset &&
|
|
100
126
|
(typeof encoding === 'undefined' ||
|
|
101
127
|
charset.toLowerCase() !== encoding.toLowerCase())) {
|
|
128
|
+
// FIXME! This must only happen, if the header is the first
|
|
129
|
+
// entry that has been added. Otherwise, we'll add the entries
|
|
130
|
+
// before this, twice.
|
|
102
131
|
return this.parse(buf, filename, charset);
|
|
103
132
|
}
|
|
104
133
|
}
|
|
@@ -106,9 +135,11 @@ class PoParser extends parser_1.Parser {
|
|
|
106
135
|
if (this.errors) {
|
|
107
136
|
return false;
|
|
108
137
|
}
|
|
138
|
+
// FIXME! This must go into the caller!
|
|
109
139
|
this.catalog.makePOT();
|
|
110
140
|
return true;
|
|
111
141
|
}
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
112
143
|
doParse(_input, _filename) {
|
|
113
144
|
throw new Error('not implemented');
|
|
114
145
|
}
|
|
@@ -150,6 +181,7 @@ class PoParser extends parser_1.Parser {
|
|
|
150
181
|
const msgctxt = this.entry.properties.msgctxt;
|
|
151
182
|
const msgid = this.entry.properties.msgid;
|
|
152
183
|
if (typeof msgid === 'undefined') {
|
|
184
|
+
// TRANSLATORS: Do not translate "msgid".
|
|
153
185
|
this.error(gtx._('missing "msgid" section'), this.loc);
|
|
154
186
|
return;
|
|
155
187
|
}
|
|
@@ -275,6 +307,7 @@ class PoParser extends parser_1.Parser {
|
|
|
275
307
|
retval = '\r';
|
|
276
308
|
break;
|
|
277
309
|
default:
|
|
310
|
+
// We have to take the leading quote into account.
|
|
278
311
|
this.loc.start.column += offset + 1;
|
|
279
312
|
this.error(gtx._('invalid control sequence'), this.loc);
|
|
280
313
|
retval = '';
|
|
@@ -298,6 +331,7 @@ class PoParser extends parser_1.Parser {
|
|
|
298
331
|
this.entry.addToMsgctxt(msg);
|
|
299
332
|
break;
|
|
300
333
|
default:
|
|
334
|
+
// Ignore plural translations.
|
|
301
335
|
break;
|
|
302
336
|
}
|
|
303
337
|
}
|
|
@@ -374,4 +408,3 @@ class PoParser extends parser_1.Parser {
|
|
|
374
408
|
}
|
|
375
409
|
}
|
|
376
410
|
exports.PoParser = PoParser;
|
|
377
|
-
//# sourceMappingURL=po.js.map
|
|
@@ -11,6 +11,8 @@ class TypeScriptParser extends parser_2.Parser {
|
|
|
11
11
|
allowReturnOutsideFunction: true,
|
|
12
12
|
allowSuperOutsideMethod: true,
|
|
13
13
|
allowUndeclaredExports: true,
|
|
14
|
+
// Documented but not supported. FIXME! Maybe only missing in types.
|
|
15
|
+
// errorRecovery: true,
|
|
14
16
|
sourceFilename: filename,
|
|
15
17
|
plugins: [
|
|
16
18
|
'typescript',
|
|
@@ -25,4 +27,3 @@ class TypeScriptParser extends parser_2.Parser {
|
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
exports.TypeScriptParser = TypeScriptParser;
|
|
28
|
-
//# sourceMappingURL=typescript.js.map
|
package/dist/pot/catalog.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Catalog = void 0;
|
|
4
4
|
const entry_1 = require("./entry");
|
|
5
|
+
/**
|
|
6
|
+
* An entire message catalog that is subsequently filled.
|
|
7
|
+
*/
|
|
5
8
|
class Catalog {
|
|
6
9
|
constructor(properties = {}) {
|
|
7
10
|
this.properties = properties;
|
|
@@ -26,6 +29,7 @@ class Catalog {
|
|
|
26
29
|
}
|
|
27
30
|
if (typeof properties.date === 'undefined') {
|
|
28
31
|
const now = new Date();
|
|
32
|
+
// Avoid if/else, so we do not spoil our test coverage. :)
|
|
29
33
|
let year = now.getFullYear().toString();
|
|
30
34
|
year = '0'.repeat(4 - year.length) + year;
|
|
31
35
|
let month = (1 + now.getMonth()).toString();
|
|
@@ -36,6 +40,7 @@ class Catalog {
|
|
|
36
40
|
hour = '0'.repeat(2 - hour.length) + hour;
|
|
37
41
|
let minutes = now.getMinutes().toString();
|
|
38
42
|
minutes = '0'.repeat(2 - minutes.length) + minutes;
|
|
43
|
+
// Do not depend on the timezone for test coverage.
|
|
39
44
|
let offset = now.getTimezoneOffset();
|
|
40
45
|
const sign = ['+', '-'][Math.sign(offset) + 1];
|
|
41
46
|
offset = Math.abs(offset);
|
|
@@ -85,6 +90,17 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
85
90
|
});
|
|
86
91
|
this.addEntry(headerEntry);
|
|
87
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Render the entire catalog.
|
|
95
|
+
*
|
|
96
|
+
* @param renderOptions - options for rendering
|
|
97
|
+
*
|
|
98
|
+
* The following options are supported:
|
|
99
|
+
*
|
|
100
|
+
* width: wrap lines to that page width (default: 76)
|
|
101
|
+
*
|
|
102
|
+
* @returns the catalog rendered as a po(t) file
|
|
103
|
+
*/
|
|
88
104
|
toString(options = {}) {
|
|
89
105
|
const width = options && typeof options.width !== 'undefined' ? options.width : 76;
|
|
90
106
|
const isNotHeader = (entry) => {
|
|
@@ -111,6 +127,9 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
111
127
|
}
|
|
112
128
|
const actx = a.properties.msgctxt;
|
|
113
129
|
const bctx = b.properties.msgctxt;
|
|
130
|
+
// It is impossible that both msgctxts are undefined
|
|
131
|
+
// because that would mean that the msgids are identical
|
|
132
|
+
// which is prevented.
|
|
114
133
|
if (typeof bctx === 'undefined') {
|
|
115
134
|
return +1;
|
|
116
135
|
}
|
|
@@ -130,6 +149,7 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
130
149
|
const filename = parts.join(':');
|
|
131
150
|
return { filename, lineno };
|
|
132
151
|
};
|
|
152
|
+
// First order all references
|
|
133
153
|
copy.entries.forEach(entry => {
|
|
134
154
|
if (entry.properties.references) {
|
|
135
155
|
entry.properties.references = entry.properties.references
|
|
@@ -183,6 +203,13 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
183
203
|
return header || body || '';
|
|
184
204
|
}
|
|
185
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Add an entry to the catalog. If an entry with the same msgid
|
|
208
|
+
* and msgctxt already exists, the entry is merged into
|
|
209
|
+
* the existing one instead.
|
|
210
|
+
*
|
|
211
|
+
* @param entry - the `POTEntry` to add
|
|
212
|
+
*/
|
|
186
213
|
addEntry(entry) {
|
|
187
214
|
const msgid = entry.properties.msgid;
|
|
188
215
|
const msgctxt = entry.properties.msgctxt;
|
|
@@ -208,11 +235,20 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
208
235
|
delete this.cache[msgid][msgctxt];
|
|
209
236
|
this.entries = this.entries.filter(other => other !== entry);
|
|
210
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Copy a catalog with other options. This is for testing only.
|
|
240
|
+
*
|
|
241
|
+
* @returns a deep copy of the catalog.
|
|
242
|
+
*/
|
|
211
243
|
copy(properties) {
|
|
212
244
|
const other = new Catalog(properties);
|
|
213
245
|
this.entries.forEach(entry => other.addEntry(entry));
|
|
214
246
|
return other;
|
|
215
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Removes all translations from a catalog, so that it can be used as
|
|
250
|
+
* a .pot file.
|
|
251
|
+
*/
|
|
216
252
|
makePOT() {
|
|
217
253
|
this.entries.forEach(entry => {
|
|
218
254
|
if (!(entry.properties.msgid === '' &&
|
|
@@ -223,4 +259,3 @@ FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
|
223
259
|
}
|
|
224
260
|
}
|
|
225
261
|
exports.Catalog = Catalog;
|
|
226
|
-
//# sourceMappingURL=catalog.js.map
|