@lingui/cli 3.17.2 → 4.0.0-next.1

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.
@@ -4,74 +4,101 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _fs = _interopRequireDefault(require("fs"));
8
- var R = _interopRequireWildcard(require("ramda"));
7
+ exports.deserialize = deserialize;
8
+ exports.serialize = void 0;
9
9
  var _dateFns = require("date-fns");
10
10
  var _pofile = _interopRequireDefault(require("pofile"));
11
11
  var _utils = require("../utils");
12
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
12
+ var _generateMessageId = require("../generateMessageId");
14
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- const getCreateHeaders = (language = "no") => ({
16
- "POT-Creation-Date": (0, _dateFns.format)(new Date(), "yyyy-MM-dd HH:mmxxxx"),
17
- "MIME-Version": "1.0",
18
- "Content-Type": "text/plain; charset=utf-8",
19
- "Content-Transfer-Encoding": "8bit",
20
- "X-Generator": "@lingui/cli",
21
- Language: language
22
- });
23
- const serialize = (items, options) => R.compose(R.values, R.mapObjIndexed((message, key) => {
24
- const item = new _pofile.default.Item();
25
- item.msgid = key;
26
- item.msgstr = [message.translation];
27
- item.comments = message.comments || [];
28
- item.extractedComments = message.extractedComments || [];
29
- if (message.context) {
30
- item.msgctxt = message.context;
31
- }
32
- if (options.origins !== false) {
33
- if (message.origin && options.lineNumbers === false) {
34
- item.references = message.origin.map(([path]) => path);
14
+ function isGeneratedId(id, message) {
15
+ return id === (0, _generateMessageId.generateMessageId)(message.message, message.context);
16
+ }
17
+ function getCreateHeaders(language = "no") {
18
+ return {
19
+ "POT-Creation-Date": (0, _dateFns.format)(new Date(), "yyyy-MM-dd HH:mmxxxx"),
20
+ "MIME-Version": "1.0",
21
+ "Content-Type": "text/plain; charset=utf-8",
22
+ "Content-Transfer-Encoding": "8bit",
23
+ "X-Generator": "@lingui/cli",
24
+ Language: language
25
+ };
26
+ }
27
+ const EXPLICIT_ID_FLAG = "explicit-id";
28
+ const serialize = (catalog, options, postProcessItem) => {
29
+ return Object.keys(catalog).map(id => {
30
+ const message = catalog[id];
31
+ const item = new _pofile.default.Item();
32
+
33
+ // The extractedComments array may be modified in this method,
34
+ // so create a new array with the message's elements.
35
+ item.extractedComments = [...(message.extractedComments || [])];
36
+ item.flags = (message.flags || []).reduce((acc, flag) => {
37
+ acc[flag] = true;
38
+ return acc;
39
+ }, {});
40
+ const _isGeneratedId = isGeneratedId(id, message);
41
+ if (_isGeneratedId) {
42
+ item.msgid = message.message;
43
+ if (!item.extractedComments.find(c => c.includes("js-lingui-id"))) {
44
+ item.extractedComments.push(`js-lingui-id: ${id}`);
45
+ }
35
46
  } else {
36
- item.references = message.origin ? message.origin.map(_utils.joinOrigin) : [];
47
+ item.flags[EXPLICIT_ID_FLAG] = true;
48
+ item.msgid = id;
37
49
  }
50
+ if (message.context) {
51
+ item.msgctxt = message.context;
52
+ }
53
+ item.msgstr = [message.translation];
54
+ item.comments = message.comments || [];
55
+ if (options.origins !== false) {
56
+ if (message.origin && options.lineNumbers === false) {
57
+ item.references = message.origin.map(([path]) => path);
58
+ } else {
59
+ item.references = message.origin ? message.origin.map(_utils.joinOrigin) : [];
60
+ }
61
+ }
62
+ item.obsolete = message.obsolete;
63
+ return postProcessItem ? postProcessItem(item, message, id, _isGeneratedId) : item;
64
+ });
65
+ };
66
+ exports.serialize = serialize;
67
+ function deserialize(items, onItem) {
68
+ return items.reduce((catalog, item) => {
69
+ onItem(item);
70
+ const message = {
71
+ translation: item.msgstr[0],
72
+ extractedComments: item.extractedComments || [],
73
+ comments: item.comments || [],
74
+ context: item.msgctxt ?? null,
75
+ obsolete: item.flags.obsolete || item.obsolete,
76
+ origin: (item.references || []).map(ref => (0, _utils.splitOrigin)(ref)),
77
+ flags: Object.keys(item.flags).map(flag => flag.trim())
78
+ };
79
+ let id = item.msgid;
80
+
81
+ // if generated id, recreate it
82
+ if (!item.flags[EXPLICIT_ID_FLAG]) {
83
+ id = (0, _generateMessageId.generateMessageId)(item.msgid, item.msgctxt);
84
+ message.message = item.msgid;
85
+ }
86
+ catalog[id] = message;
87
+ return catalog;
88
+ }, {});
89
+ }
90
+ function validateItem(item) {
91
+ if (item.msgstr.length > 1) {
92
+ console.warn(`Multiple translations for item with key ${item.msgid} is not supported and it will be ignored.`);
38
93
  }
39
- // @ts-ignore: Figure out how to set this flag
40
- item.obsolete = message.obsolete;
41
- item.flags = message.flags ? R.fromPairs(message.flags.map(flag => [flag, true])) : {};
42
- return item;
43
- }))(items);
44
- const getMessageKey = R.prop("msgid");
45
- const getTranslations = R.prop("msgstr");
46
- const getExtractedComments = R.prop("extractedComments");
47
- const getTranslatorComments = R.prop("comments");
48
- const getMessageContext = R.prop("msgctxt");
49
- const getOrigins = R.prop("references");
50
- const getFlags = R.compose(R.map(R.trim), R.keys, R.dissoc("obsolete"),
51
- // backward-compatibility, remove in 3.x
52
- R.prop("flags"));
53
- const isObsolete = R.either(R.path(["flags", "obsolete"]), R.prop("obsolete"));
54
- const deserialize = R.map(R.applySpec({
55
- translation: R.compose(R.head, R.defaultTo([]), getTranslations),
56
- extractedComments: R.compose(R.defaultTo([]), getExtractedComments),
57
- comments: R.compose(R.defaultTo([]), getTranslatorComments),
58
- context: R.compose(R.defaultTo(null), getMessageContext),
59
- obsolete: isObsolete,
60
- origin: R.compose(R.map(_utils.splitOrigin), R.defaultTo([]), getOrigins),
61
- flags: getFlags
62
- }));
63
- const validateItems = R.forEach(item => {
64
- if (R.length(getTranslations(item)) > 1) {
65
- console.warn("Multiple translations for item with key %s is not supported and it will be ignored.", getMessageKey(item));
66
- }
67
- });
68
- const indexItems = R.indexBy(getMessageKey);
94
+ }
69
95
  const po = {
70
96
  catalogExtension: ".po",
97
+ templateExtension: ".pot",
71
98
  write(filename, catalog, options) {
72
99
  let po;
73
- if (_fs.default.existsSync(filename)) {
74
- const raw = _fs.default.readFileSync(filename).toString();
100
+ const raw = (0, _utils.readFile)(filename);
101
+ if (raw) {
75
102
  po = _pofile.default.parse(raw);
76
103
  } else {
77
104
  po = new _pofile.default();
@@ -79,19 +106,23 @@ const po = {
79
106
  if (options.locale === undefined) {
80
107
  delete po.headers.Language;
81
108
  }
82
- po.headerOrder = R.keys(po.headers);
109
+ // accessing private property
110
+ ;
111
+ po.headerOrder = Object.keys(po.headers);
83
112
  }
84
113
  po.items = serialize(catalog, options);
85
114
  (0, _utils.writeFileIfChanged)(filename, po.toString());
86
115
  },
87
116
  read(filename) {
88
- const raw = _fs.default.readFileSync(filename).toString();
117
+ const raw = (0, _utils.readFile)(filename);
118
+ if (!raw) {
119
+ return null;
120
+ }
89
121
  return this.parse(raw);
90
122
  },
91
123
  parse(raw) {
92
124
  const po = _pofile.default.parse(raw);
93
- validateItems(po.items);
94
- return deserialize(indexItems(po.items));
125
+ return deserialize(po.items, validateItem);
95
126
  }
96
127
  };
97
128
  var _default = po;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.generateMessageId = generateMessageId;
7
+ var _crypto = _interopRequireDefault(require("crypto"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const UNIT_SEPARATOR = "\u001F";
10
+ function generateMessageId(msg, context = "") {
11
+ return _crypto.default.createHash("sha256").update(msg + UNIT_SEPARATOR + (context || "")).digest("base64").slice(0, 6);
12
+ }
package/build/api/help.js CHANGED
@@ -36,7 +36,7 @@ function helpRun(command) {
36
36
  command = res[0];
37
37
  }
38
38
  }
39
+ const isYarn = process.env.npm_config_user_agent && process.env.npm_config_user_agent.includes("yarn");
40
+ const runCommand = isYarn ? "yarn" : "npm run";
39
41
  return `${runCommand} ${command}`;
40
- }
41
- const isYarn = process.env.npm_config_user_agent && process.env.npm_config_user_agent.includes("yarn");
42
- const runCommand = isYarn ? "yarn" : "npm run";
42
+ }
@@ -3,31 +3,56 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _exportNames = {
7
+ getFormat: true,
8
+ getCatalogForFile: true,
9
+ getCatalogs: true,
10
+ createCompiledCatalog: true,
11
+ generateMessageId: true
12
+ };
6
13
  Object.defineProperty(exports, "createCompiledCatalog", {
7
14
  enumerable: true,
8
15
  get: function () {
9
16
  return _compile.createCompiledCatalog;
10
17
  }
11
18
  });
19
+ Object.defineProperty(exports, "generateMessageId", {
20
+ enumerable: true,
21
+ get: function () {
22
+ return _generateMessageId.generateMessageId;
23
+ }
24
+ });
12
25
  Object.defineProperty(exports, "getCatalogForFile", {
13
26
  enumerable: true,
14
27
  get: function () {
15
- return _catalog.getCatalogForFile;
28
+ return _getCatalogs.getCatalogForFile;
16
29
  }
17
30
  });
18
31
  Object.defineProperty(exports, "getCatalogs", {
19
32
  enumerable: true,
20
33
  get: function () {
21
- return _catalog.getCatalogs;
34
+ return _getCatalogs.getCatalogs;
22
35
  }
23
36
  });
24
37
  Object.defineProperty(exports, "getFormat", {
25
38
  enumerable: true,
26
39
  get: function () {
27
- return _formats.default;
40
+ return _formats.getFormat;
28
41
  }
29
42
  });
30
- var _formats = _interopRequireDefault(require("./formats"));
31
- var _catalog = require("./catalog");
43
+ var _formats = require("./formats");
44
+ var _getCatalogs = require("./catalog/getCatalogs");
32
45
  var _compile = require("./compile");
33
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
46
+ var _generateMessageId = require("./generateMessageId");
47
+ var _types = require("./types");
48
+ Object.keys(_types).forEach(function (key) {
49
+ if (key === "default" || key === "__esModule") return;
50
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
51
+ if (key in exports && exports[key] === _types[key]) return;
52
+ Object.defineProperty(exports, key, {
53
+ enumerable: true,
54
+ get: function () {
55
+ return _types[key];
56
+ }
57
+ });
58
+ });
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -3,38 +3,25 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.PATHSEP = void 0;
6
7
  exports.hasYarn = hasYarn;
7
- exports.helpMisspelledCommand = helpMisspelledCommand;
8
+ exports.isDirectory = isDirectory;
8
9
  exports.joinOrigin = void 0;
9
10
  exports.makeInstall = makeInstall;
11
+ exports.normalizeRelativePath = normalizeRelativePath;
12
+ exports.normalizeSlashes = normalizeSlashes;
10
13
  exports.prettyOrigin = prettyOrigin;
11
- exports.removeDirectory = removeDirectory;
14
+ exports.readFile = readFile;
15
+ exports.replacePlaceholders = replacePlaceholders;
12
16
  exports.splitOrigin = void 0;
17
+ exports.writeFile = writeFile;
13
18
  exports.writeFileIfChanged = writeFileIfChanged;
14
19
  var _fs = _interopRequireDefault(require("fs"));
15
20
  var _path = _interopRequireDefault(require("path"));
16
- var _chalk = _interopRequireDefault(require("chalk"));
17
- var _fuzzaldrin = require("fuzzaldrin");
21
+ var _normalizePath = _interopRequireDefault(require("normalize-path"));
18
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
- function removeDirectory(dir, onlyContent = false) {
20
- if (!_fs.default.existsSync(dir)) return;
21
- const list = _fs.default.readdirSync(dir);
22
- for (let i = 0; i < list.length; i++) {
23
- const filename = _path.default.join(dir, list[i]);
24
- const stat = _fs.default.statSync(filename);
25
- if (filename === "." || filename === "..") {
26
- // pass these files
27
- } else if (stat.isDirectory()) {
28
- // rmdir recursively
29
- removeDirectory(filename);
30
- } else {
31
- _fs.default.unlinkSync(filename);
32
- }
33
- }
34
- if (!onlyContent) {
35
- _fs.default.rmdirSync(dir);
36
- }
37
- }
23
+ const PATHSEP = "/"; // force posix everywhere
24
+ exports.PATHSEP = PATHSEP;
38
25
  function prettyOrigin(origins) {
39
26
  try {
40
27
  return origins.map(origin => origin.join(":")).join(", ");
@@ -42,44 +29,59 @@ function prettyOrigin(origins) {
42
29
  return "";
43
30
  }
44
31
  }
45
-
46
- /**
47
- * .. js:function:: helpMisspelledCommand(command [, availableCommands = []])
48
- * :param: command - command passed to CLI
49
- * :param: availableCommands - all commands defined in commander.js
50
- *
51
- * If unknown commands is passed to CLI, check it agains all available commands
52
- * for possible misspelled letter. Output help with suggestions to console.
53
- */
54
- function helpMisspelledCommand(command, availableCommands = []) {
55
- const commandNames = availableCommands.map(command => command.name());
56
-
57
- // if no command is supplied, then commander.js shows help automatically
58
- if (!command || commandNames.includes(command)) {
59
- return;
60
- }
61
- const suggestions = commandNames.map(name => ({
62
- name,
63
- score: (0, _fuzzaldrin.score)(name, command.slice(0, name.length))
64
- })).filter(nameScore => nameScore.score > 0).slice(0, 3).map(commandScore => _chalk.default.inverse(commandScore.name)).join(", ");
65
- console.log(`lingui: command ${command} is not a lingui command. ` + `See 'lingui --help' for the list of available commands.`);
66
- if (suggestions) {
67
- console.log();
68
- console.log(`Did you mean: ${suggestions}?`);
69
- }
32
+ function replacePlaceholders(input, values) {
33
+ return input.replace(/\{([^}]+)}/g, (m, placeholder) => {
34
+ return values[placeholder] || m;
35
+ });
70
36
  }
71
- const splitOrigin = origin => origin.split(":");
37
+ const splitOrigin = origin => {
38
+ const [file, line] = origin.split(":");
39
+ return [file, line ? Number(line) : null];
40
+ };
72
41
  exports.splitOrigin = splitOrigin;
73
42
  const joinOrigin = origin => origin.join(":");
74
43
  exports.joinOrigin = joinOrigin;
44
+ function readFile(fileName) {
45
+ try {
46
+ return _fs.default.readFileSync(fileName).toString();
47
+ } catch (err) {
48
+ if (err.code != "ENOENT") {
49
+ throw err;
50
+ }
51
+ }
52
+ }
53
+ function mkdirp(dir) {
54
+ try {
55
+ _fs.default.mkdirSync(dir, {
56
+ recursive: true
57
+ });
58
+ } catch (err) {
59
+ if (err.code != "EEXIST") {
60
+ throw err;
61
+ }
62
+ }
63
+ }
64
+ function isDirectory(filePath) {
65
+ try {
66
+ return _fs.default.lstatSync(filePath).isDirectory();
67
+ } catch (err) {
68
+ if (err.code != "ENOENT") {
69
+ throw err;
70
+ }
71
+ }
72
+ }
73
+ function writeFile(fileName, content) {
74
+ mkdirp(_path.default.dirname(fileName));
75
+ _fs.default.writeFileSync(fileName, content);
76
+ }
75
77
  function writeFileIfChanged(filename, newContent) {
76
- if (_fs.default.existsSync(filename)) {
77
- const raw = _fs.default.readFileSync(filename).toString();
78
+ const raw = readFile(filename);
79
+ if (raw) {
78
80
  if (newContent !== raw) {
79
- _fs.default.writeFileSync(filename, newContent);
81
+ writeFile(filename, newContent);
80
82
  }
81
83
  } else {
82
- _fs.default.writeFileSync(filename, newContent);
84
+ writeFile(filename, newContent);
83
85
  }
84
86
  }
85
87
  function hasYarn() {
@@ -88,4 +90,26 @@ function hasYarn() {
88
90
  function makeInstall() {
89
91
  const withYarn = hasYarn();
90
92
  return (packageName, dev = false) => withYarn ? `yarn add ${dev ? "--dev " : ""}${packageName}` : `npm install ${dev ? "--save-dev" : "--save"} ${packageName}`;
93
+ }
94
+
95
+ /**
96
+ * Normalize Windows backslashes in path so they look always as posix
97
+ */
98
+ function normalizeSlashes(path) {
99
+ return path.replace("\\", "/");
100
+ }
101
+
102
+ /**
103
+ * Remove ./ at the beginning: ./relative => relative
104
+ * relative => relative
105
+ * Preserve directories: ./relative/ => relative/
106
+ * Preserve absolute paths: /absolute/path => /absolute/path
107
+ */
108
+ function normalizeRelativePath(sourcePath) {
109
+ if (_path.default.isAbsolute(sourcePath)) {
110
+ // absolute path
111
+ return (0, _normalizePath.default)(sourcePath, false);
112
+ }
113
+ const isDir = isDirectory(sourcePath);
114
+ return (0, _normalizePath.default)(_path.default.relative(process.cwd(), sourcePath), false) + (isDir ? "/" : "");
91
115
  }
@@ -7,57 +7,43 @@ exports.command = command;
7
7
  var _chalk = _interopRequireDefault(require("chalk"));
8
8
  var _chokidar = _interopRequireDefault(require("chokidar"));
9
9
  var _fs = _interopRequireDefault(require("fs"));
10
- var R = _interopRequireWildcard(require("ramda"));
11
- var _commander = _interopRequireDefault(require("commander"));
12
- var plurals = _interopRequireWildcard(require("make-plural"));
10
+ var _commander = require("commander");
13
11
  var _conf = require("@lingui/conf");
14
- var _catalog = require("./api/catalog");
15
12
  var _compile = require("./api/compile");
16
13
  var _help = require("./api/help");
17
14
  var _api = require("./api");
18
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+ var _getCatalogs = require("./api/catalog/getCatalogs");
20
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
- const noMessages = R.pipe(R.map(R.isEmpty), R.values, R.all(R.equals(true)));
22
17
  function command(config, options) {
23
- const catalogs = (0, _catalog.getCatalogs)(config);
24
-
25
- // fixme: this is definitely doesn't work
26
- if (noMessages(catalogs)) {
27
- console.error("Nothing to compile, message catalogs are empty!\n");
28
- console.error(`(use "${_chalk.default.yellow((0, _help.helpRun)("extract"))}" to extract messages from source files)`);
29
- return false;
30
- }
18
+ const catalogs = (0, _api.getCatalogs)(config);
31
19
 
32
20
  // Check config.compile.merge if catalogs for current locale are to be merged into a single compiled file
33
21
  const doMerge = !!config.catalogsMergePath;
34
22
  let mergedCatalogs = {};
35
23
  console.log("Compiling message catalogs…");
36
24
  for (const locale of config.locales) {
37
- const [language] = locale.split(/[_-]/);
38
- // todo: this validation should be in @lingui/conf
39
- if (locale !== config.pseudoLocale && !plurals[language]) {
40
- console.error(_chalk.default.red(`Error: Invalid locale ${_chalk.default.bold(locale)} (missing plural rules)!`));
41
- console.error();
42
- }
43
25
  for (const catalog of catalogs) {
26
+ const missingMessages = [];
44
27
  const messages = catalog.getTranslations(locale, {
45
28
  fallbackLocales: config.fallbackLocales,
46
- sourceLocale: config.sourceLocale
29
+ sourceLocale: config.sourceLocale,
30
+ onMissing: missing => {
31
+ missingMessages.push(missing);
32
+ }
47
33
  });
48
- if (!options.allowEmpty) {
49
- const missingMsgIds = R.pipe(R.pickBy(R.isNil), R.keys)(messages);
50
- if (missingMsgIds.length > 0) {
51
- console.error(_chalk.default.red(`Error: Failed to compile catalog for locale ${_chalk.default.bold(locale)}!`));
52
- if (options.verbose) {
53
- console.error(_chalk.default.red("Missing translations:"));
54
- missingMsgIds.forEach(msgId => console.error(msgId));
55
- } else {
56
- console.error(_chalk.default.red(`Missing ${missingMsgIds.length} translation(s)`));
57
- }
58
- console.error();
59
- return false;
34
+ if (!options.allowEmpty && missingMessages.length > 0) {
35
+ console.error(_chalk.default.red(`Error: Failed to compile catalog for locale ${_chalk.default.bold(locale)}!`));
36
+ if (options.verbose) {
37
+ console.error(_chalk.default.red("Missing translations:"));
38
+ missingMessages.forEach(missing => {
39
+ const source = missing.source || missing.source === missing.id ? `: (${missing.source})` : "";
40
+ console.error(`${missing.id}${source}`);
41
+ });
42
+ } else {
43
+ console.error(_chalk.default.red(`Missing ${missingMessages.length} translation(s)`));
60
44
  }
45
+ console.error();
46
+ return false;
61
47
  }
62
48
  if (doMerge) {
63
49
  mergedCatalogs = {
@@ -84,7 +70,7 @@ function command(config, options) {
84
70
  }
85
71
  }
86
72
  if (doMerge) {
87
- const compileCatalog = (0, _catalog.getCatalogForMerge)(config);
73
+ const compileCatalog = (0, _getCatalogs.getCatalogForMerge)(config);
88
74
  const namespace = options.namespace || config.compileNamespace;
89
75
  const compiledCatalog = (0, _compile.createCompiledCatalog)(locale, mergedCatalogs, {
90
76
  strict: false,
@@ -99,7 +85,7 @@ function command(config, options) {
99
85
  return true;
100
86
  }
101
87
  if (require.main === module) {
102
- _commander.default.description("Add compile message catalogs and add language data (plurals) to compiled bundle.").option("--config <path>", "Path to the config file").option("--strict", "Disable defaults for missing translations").option("--verbose", "Verbose output").option("--format <format>", "Format of message catalog").option("--typescript", "Create Typescript definition for compiled bundle").option("--namespace <namespace>", "Specify namespace for compiled bundle. Ex: cjs(default) -> module.exports, es -> export, window.test -> window.test").option("--watch", "Enables Watch Mode").option("--debounce <delay>", "Debounces compilation for given amount of milliseconds").on("--help", function () {
88
+ _commander.program.description("Add compile message catalogs and add language data (plurals) to compiled bundle.").option("--config <path>", "Path to the config file").option("--strict", "Disable defaults for missing translations").option("--verbose", "Verbose output").option("--typescript", "Create Typescript definition for compiled bundle").option("--namespace <namespace>", "Specify namespace for compiled bundle. Ex: cjs(default) -> module.exports, es -> export, window.test -> window.test").option("--watch", "Enables Watch Mode").option("--debounce <delay>", "Debounces compilation for given amount of milliseconds").on("--help", function () {
103
89
  console.log("\n Examples:\n");
104
90
  console.log(" # Compile translations and use defaults or message IDs for missing translations");
105
91
  console.log(` $ ${(0, _help.helpRun)("compile")}`);
@@ -109,35 +95,31 @@ if (require.main === module) {
109
95
  console.log(" # default messages or message IDs)");
110
96
  console.log(` $ ${(0, _help.helpRun)("compile --strict")}`);
111
97
  }).parse(process.argv);
98
+ const options = _commander.program.opts();
112
99
  const config = (0, _conf.getConfig)({
113
- configPath: _commander.default.config
100
+ configPath: options.config
114
101
  });
115
- if (_commander.default.format) {
116
- const msg = "--format option is deprecated and will be removed in @lingui/cli@3.0.0." + " Please set format in configuration https://lingui.dev/ref/conf#format";
117
- console.warn(msg);
118
- config.format = _commander.default.format;
119
- }
120
102
  const compile = () => command(config, {
121
- verbose: _commander.default.watch || _commander.default.verbose || false,
122
- allowEmpty: !_commander.default.strict,
123
- typescript: _commander.default.typescript || config.compileNamespace === "ts" || false,
124
- namespace: _commander.default.namespace // we want this to be undefined if user does not specify so default can be used
103
+ verbose: options.watch || options.verbose || false,
104
+ allowEmpty: !options.strict,
105
+ typescript: options.typescript || config.compileNamespace === "ts" || false,
106
+ namespace: options.namespace // we want this to be undefined if user does not specify so default can be used
125
107
  });
126
108
 
127
109
  let debounceTimer;
128
110
  const dispatchCompile = () => {
129
111
  // Skip debouncing if not enabled
130
- if (!_commander.default.debounce) return compile();
112
+ if (!options.debounce) return compile();
131
113
 
132
114
  // CLear the previous timer if there is any, and schedule the next
133
115
  debounceTimer && clearTimeout(debounceTimer);
134
- debounceTimer = setTimeout(() => compile(), _commander.default.debounce);
116
+ debounceTimer = setTimeout(() => compile(), options.debounce);
135
117
  };
136
118
 
137
119
  // Check if Watch Mode is enabled
138
- if (_commander.default.watch) {
120
+ if (options.watch) {
139
121
  console.info(_chalk.default.bold("Initializing Watch Mode..."));
140
- const catalogs = (0, _catalog.getCatalogs)(config);
122
+ const catalogs = (0, _api.getCatalogs)(config);
141
123
  let paths = [];
142
124
  const catalogExtension = (0, _api.getFormat)(config.format).catalogExtension;
143
125
  config.locales.forEach(locale => {
@@ -5,50 +5,41 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = command;
7
7
  var _chalk = _interopRequireDefault(require("chalk"));
8
- var _commander = _interopRequireDefault(require("commander"));
8
+ var _commander = require("commander");
9
9
  var _conf = require("@lingui/conf");
10
- var _catalog = require("./api/catalog");
11
- var _detect = require("./api/detect");
10
+ var _api = require("./api");
11
+ var _path = _interopRequireDefault(require("path"));
12
+ var _utils = require("./api/utils");
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  async function command(config, options) {
14
- // `react-app` babel plugin used by CRA requires either BABEL_ENV or NODE_ENV to be
15
- // set. We're setting it here, because lingui macros are going to use them as well.
16
- if (!process.env.BABEL_ENV && !process.env.NODE_ENV) {
17
- process.env.BABEL_ENV = "development";
18
- }
19
-
20
- // We need macros to keep imports, so extract-messages plugin know what componets
21
- // to collect. Users usually use both BABEN_ENV and NODE_ENV, so it's probably
22
- // safer to introduce a new env variable. LINGUI_EXTRACT=1 during `lingui extract`
23
- process.env.LINGUI_EXTRACT = "1";
24
- options.verbose && console.error("Extracting messages from source files…");
25
- const catalogs = (0, _catalog.getCatalogs)(config);
15
+ options.verbose && console.log("Extracting messages from source files…");
16
+ const catalogs = (0, _api.getCatalogs)(config);
26
17
  const catalogStats = {};
18
+ let commandSuccess = true;
27
19
  await Promise.all(catalogs.map(async catalog => {
28
- await catalog.makeTemplate({
20
+ const result = await catalog.makeTemplate({
29
21
  ...options,
30
- orderBy: config.orderBy,
31
- projectType: (0, _detect.detect)()
22
+ orderBy: config.orderBy
32
23
  });
33
- const catalogTemplate = catalog.readTemplate();
34
- if (catalogTemplate !== null && catalogTemplate !== undefined) {
35
- catalogStats[catalog.templateFile] = Object.keys(catalogTemplate).length;
24
+ if (result) {
25
+ catalogStats[(0, _utils.normalizeSlashes)(_path.default.relative(config.rootDir, catalog.templateFile))] = Object.keys(result).length;
36
26
  }
27
+ commandSuccess && (commandSuccess = Boolean(result));
37
28
  }));
38
29
  Object.entries(catalogStats).forEach(([key, value]) => {
39
30
  console.log(`Catalog statistics for ${_chalk.default.bold(key)}: ${_chalk.default.green(value)} messages`);
40
31
  console.log();
41
32
  });
42
- return true;
33
+ return commandSuccess;
43
34
  }
44
35
  if (require.main === module) {
45
- _commander.default.option("--config <path>", "Path to the config file").option("--verbose", "Verbose output").parse(process.argv);
36
+ _commander.program.option("--config <path>", "Path to the config file").option("--verbose", "Verbose output").parse(process.argv);
37
+ const options = _commander.program.opts();
46
38
  const config = (0, _conf.getConfig)({
47
- configPath: _commander.default.config || process.env.LINGUI_CONFIG
39
+ configPath: options.config
48
40
  });
49
41
  const result = command(config, {
50
- verbose: _commander.default.verbose || false,
51
- configPath: _commander.default.config || process.env.LINGUI_CONFIG
42
+ verbose: options.verbose || false
52
43
  }).then(() => {
53
44
  if (!result) process.exit(1);
54
45
  });