@lingui/cli 3.17.1 → 4.0.0-next.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/build/api/catalog/extractFromFiles.js +45 -0
- package/build/api/catalog/getCatalogs.js +129 -0
- package/build/api/catalog/getTranslationsForCatalog.js +77 -0
- package/build/api/catalog/mergeCatalog.js +44 -0
- package/build/api/catalog.js +75 -336
- package/build/api/compile.js +0 -12
- package/build/api/extractors/babel.js +67 -24
- package/build/api/extractors/index.js +6 -11
- package/build/api/extractors/typescript.js +2 -46
- package/build/api/formats/csv.js +4 -2
- package/build/api/formats/index.js +1 -1
- package/build/api/formats/lingui.js +4 -3
- package/build/api/formats/minimal.js +8 -14
- package/build/api/formats/po-gettext.js +89 -126
- package/build/api/formats/po.js +92 -61
- package/build/api/generateMessageId.js +12 -0
- package/build/api/help.js +3 -3
- package/build/api/index.js +31 -6
- package/build/api/types.js +5 -0
- package/build/api/utils.js +77 -53
- package/build/lingui-compile.js +33 -41
- package/build/lingui-extract-template.js +17 -26
- package/build/lingui-extract.js +42 -55
- package/build/lingui.js +3 -10
- package/build/services/translationIO.js +7 -3
- package/build/tests.js +55 -10
- package/package.json +16 -19
- package/CHANGELOG.md +0 -518
- package/build/api/detect.js +0 -52
- package/build/api/extract.js +0 -59
- package/build/lingui-add-locale.js +0 -8
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.extractFromFiles = extractFromFiles;
|
|
7
|
+
var _extractors = _interopRequireDefault(require("../extractors"));
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _chalk = _interopRequireDefault(require("chalk"));
|
|
10
|
+
var _utils = require("../utils");
|
|
11
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
+
async function extractFromFiles(paths, config) {
|
|
13
|
+
const messages = {};
|
|
14
|
+
let catalogSuccess = true;
|
|
15
|
+
for (let filename of paths) {
|
|
16
|
+
const fileSuccess = await (0, _extractors.default)(filename, next => {
|
|
17
|
+
if (!messages[next.id]) {
|
|
18
|
+
messages[next.id] = {
|
|
19
|
+
message: next.message,
|
|
20
|
+
context: next.context,
|
|
21
|
+
extractedComments: [],
|
|
22
|
+
origin: []
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const prev = messages[next.id];
|
|
26
|
+
|
|
27
|
+
// there might be a case when filename was not mapped from sourcemaps
|
|
28
|
+
const filename = next.origin[0] ? _path.default.relative(config.rootDir, next.origin[0]).replace(/\\/g, "/") : "";
|
|
29
|
+
const origin = [filename, next.origin[1]];
|
|
30
|
+
if (prev.message && next.message && prev.message !== next.message) {
|
|
31
|
+
throw new Error(`Encountered different default translations for message ${_chalk.default.yellow(next.id)}` + `\n${_chalk.default.yellow((0, _utils.prettyOrigin)(prev.origin))} ${prev.message}` + `\n${_chalk.default.yellow((0, _utils.prettyOrigin)([origin]))} ${next.message}`);
|
|
32
|
+
}
|
|
33
|
+
messages[next.id] = {
|
|
34
|
+
...prev,
|
|
35
|
+
extractedComments: next.comment ? [...prev.extractedComments, next.comment] : prev.extractedComments,
|
|
36
|
+
origin: [...prev.origin, [filename, next.origin[1]]]
|
|
37
|
+
};
|
|
38
|
+
}, config, {
|
|
39
|
+
extractors: config.extractors
|
|
40
|
+
});
|
|
41
|
+
catalogSuccess && (catalogSuccess = fileSuccess);
|
|
42
|
+
}
|
|
43
|
+
if (!catalogSuccess) return undefined;
|
|
44
|
+
return messages;
|
|
45
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getCatalogForFile = getCatalogForFile;
|
|
7
|
+
exports.getCatalogForMerge = getCatalogForMerge;
|
|
8
|
+
exports.getCatalogs = getCatalogs;
|
|
9
|
+
var _glob = _interopRequireDefault(require("glob"));
|
|
10
|
+
var _path = _interopRequireDefault(require("path"));
|
|
11
|
+
var _catalog = require("../catalog");
|
|
12
|
+
var _utils = require("../utils");
|
|
13
|
+
var _micromatch = _interopRequireDefault(require("micromatch"));
|
|
14
|
+
var _formats = require("../formats");
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
const NAME_PH = "{name}";
|
|
17
|
+
const LOCALE_PH = "{locale}";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse `config.catalogs` and return a list of configured Catalog instances.
|
|
21
|
+
*/
|
|
22
|
+
function getCatalogs(config) {
|
|
23
|
+
const catalogsConfig = config.catalogs;
|
|
24
|
+
const catalogs = [];
|
|
25
|
+
catalogsConfig.forEach(catalog => {
|
|
26
|
+
validateCatalogPath(catalog.path, config);
|
|
27
|
+
const include = ensureArray(catalog.include).map(_utils.normalizeRelativePath);
|
|
28
|
+
const exclude = ensureArray(catalog.exclude).map(_utils.normalizeRelativePath);
|
|
29
|
+
|
|
30
|
+
// catalog.path without {name} pattern -> always refers to a single catalog
|
|
31
|
+
if (!catalog.path.includes(NAME_PH)) {
|
|
32
|
+
// Validate that sourcePaths doesn't use {name} pattern either
|
|
33
|
+
const invalidSource = include.find(path => path.includes(NAME_PH));
|
|
34
|
+
if (invalidSource !== undefined) {
|
|
35
|
+
throw new Error(`Catalog with path "${catalog.path}" doesn't have a {name} pattern` + ` in it, but one of source directories uses it: "${invalidSource}".` + ` Either add {name} pattern to "${catalog.path}" or remove it` + ` from all source directories.`);
|
|
36
|
+
}
|
|
37
|
+
catalogs.push(new _catalog.Catalog({
|
|
38
|
+
name: getCatalogName(catalog.path),
|
|
39
|
+
path: (0, _utils.normalizeRelativePath)(catalog.path),
|
|
40
|
+
include,
|
|
41
|
+
exclude
|
|
42
|
+
}, config));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const patterns = include.map(path => (0, _utils.replacePlaceholders)(path, {
|
|
46
|
+
name: "*"
|
|
47
|
+
}));
|
|
48
|
+
const candidates = _glob.default.sync(patterns.length > 1 ? `{${patterns.join(",")}}` : patterns[0], {
|
|
49
|
+
ignore: exclude,
|
|
50
|
+
mark: true
|
|
51
|
+
});
|
|
52
|
+
candidates.forEach(catalogDir => {
|
|
53
|
+
const name = _path.default.basename(catalogDir);
|
|
54
|
+
catalogs.push(new _catalog.Catalog({
|
|
55
|
+
name,
|
|
56
|
+
path: (0, _utils.normalizeRelativePath)((0, _utils.replacePlaceholders)(catalog.path, {
|
|
57
|
+
name
|
|
58
|
+
})),
|
|
59
|
+
include: include.map(path => (0, _utils.replacePlaceholders)(path, {
|
|
60
|
+
name
|
|
61
|
+
})),
|
|
62
|
+
exclude: exclude.map(path => (0, _utils.replacePlaceholders)(path, {
|
|
63
|
+
name
|
|
64
|
+
}))
|
|
65
|
+
}, config));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
return catalogs;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Ensure that value is always array. If not, turn it into an array of one element.
|
|
73
|
+
*/
|
|
74
|
+
const ensureArray = value => {
|
|
75
|
+
if (value == null) return [];
|
|
76
|
+
return Array.isArray(value) ? value : [value];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create catalog for merged messages.
|
|
81
|
+
*/
|
|
82
|
+
function getCatalogForMerge(config) {
|
|
83
|
+
validateCatalogPath(config.catalogsMergePath, config);
|
|
84
|
+
return new _catalog.Catalog({
|
|
85
|
+
name: getCatalogName(config.catalogsMergePath),
|
|
86
|
+
path: (0, _utils.normalizeRelativePath)(config.catalogsMergePath),
|
|
87
|
+
include: [],
|
|
88
|
+
exclude: []
|
|
89
|
+
}, config);
|
|
90
|
+
}
|
|
91
|
+
function getCatalogForFile(file, catalogs) {
|
|
92
|
+
for (const catalog of catalogs) {
|
|
93
|
+
const catalogFile = `${catalog.path}${catalog.format.catalogExtension}`;
|
|
94
|
+
const catalogGlob = (0, _utils.replacePlaceholders)(catalogFile, {
|
|
95
|
+
locale: "*"
|
|
96
|
+
});
|
|
97
|
+
const match = _micromatch.default.capture((0, _utils.normalizeRelativePath)(_path.default.relative(catalog.config.rootDir, catalogGlob)), (0, _utils.normalizeRelativePath)(file));
|
|
98
|
+
if (match) {
|
|
99
|
+
return {
|
|
100
|
+
locale: match[0],
|
|
101
|
+
catalog
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Validate that `catalogPath` doesn't end with trailing slash
|
|
110
|
+
*/
|
|
111
|
+
function validateCatalogPath(path, config) {
|
|
112
|
+
if (!path.endsWith(_utils.PATHSEP)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const extension = (0, _formats.getFormat)(config.format).catalogExtension;
|
|
116
|
+
const correctPath = path.slice(0, -1);
|
|
117
|
+
const examplePath = (0, _utils.replacePlaceholders)(correctPath, {
|
|
118
|
+
locale: (config.locales || [])[0] || "en"
|
|
119
|
+
}) + extension;
|
|
120
|
+
throw new Error(
|
|
121
|
+
// prettier-ignore
|
|
122
|
+
`Remove trailing slash from "${path}". Catalog path isn't a directory,` + ` but translation file without extension. For example, catalog path "${correctPath}"` + ` results in translation file "${examplePath}".`);
|
|
123
|
+
}
|
|
124
|
+
function getCatalogName(filePath) {
|
|
125
|
+
// catalog name is the last directory of catalogPath.
|
|
126
|
+
// If the last part is {locale}, then catalog doesn't have an explicit name
|
|
127
|
+
const _name = _path.default.basename((0, _utils.normalizeRelativePath)(filePath));
|
|
128
|
+
return _name !== LOCALE_PH ? _name : null;
|
|
129
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getTranslationsForCatalog = getTranslationsForCatalog;
|
|
7
|
+
function getTranslationsForCatalog(catalog, locale, options) {
|
|
8
|
+
const catalogs = catalog.readAll();
|
|
9
|
+
const template = catalog.readTemplate() || {};
|
|
10
|
+
const sourceLocaleCatalog = catalogs[options.sourceLocale] || {};
|
|
11
|
+
const input = {
|
|
12
|
+
...template,
|
|
13
|
+
...sourceLocaleCatalog,
|
|
14
|
+
...catalogs[locale]
|
|
15
|
+
};
|
|
16
|
+
return Object.keys(input).reduce((acc, key) => {
|
|
17
|
+
acc[key] = getTranslation(catalogs, input[key], locale, key, options);
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
}
|
|
21
|
+
function sourceLocaleFallback(catalog, key) {
|
|
22
|
+
if (!(catalog !== null && catalog !== void 0 && catalog[key])) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return catalog[key].translation || catalog[key].message;
|
|
26
|
+
}
|
|
27
|
+
function getTranslation(catalogs, msg, locale, key, options) {
|
|
28
|
+
const {
|
|
29
|
+
fallbackLocales,
|
|
30
|
+
sourceLocale,
|
|
31
|
+
onMissing
|
|
32
|
+
} = options;
|
|
33
|
+
const getTranslation = _locale => {
|
|
34
|
+
var _localeCatalog$key;
|
|
35
|
+
const localeCatalog = catalogs[_locale];
|
|
36
|
+
return localeCatalog === null || localeCatalog === void 0 ? void 0 : (_localeCatalog$key = localeCatalog[key]) === null || _localeCatalog$key === void 0 ? void 0 : _localeCatalog$key.translation;
|
|
37
|
+
};
|
|
38
|
+
const getMultipleFallbacks = _locale => {
|
|
39
|
+
const fL = fallbackLocales && (fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales[_locale]);
|
|
40
|
+
|
|
41
|
+
// some probably the fallback will be undefined, so just search by locale
|
|
42
|
+
if (!fL) return null;
|
|
43
|
+
if (Array.isArray(fL)) {
|
|
44
|
+
for (const fallbackLocale of fL) {
|
|
45
|
+
if (catalogs[fallbackLocale] && getTranslation(fallbackLocale)) {
|
|
46
|
+
return getTranslation(fallbackLocale);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
return getTranslation(fL);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// target locale -> fallback locales -> fallback locales default ->
|
|
55
|
+
// ** (following fallbacks would emit `missing` warning) **
|
|
56
|
+
// -> source locale translation -> source locale message
|
|
57
|
+
// -> template message
|
|
58
|
+
// ** last resort **
|
|
59
|
+
// -> id
|
|
60
|
+
|
|
61
|
+
let translation =
|
|
62
|
+
// Get translation in target locale
|
|
63
|
+
getTranslation(locale) ||
|
|
64
|
+
// We search in fallbackLocales as dependent of each locale
|
|
65
|
+
getMultipleFallbacks(locale) ||
|
|
66
|
+
// Get translation in fallbackLocales.default (if any)
|
|
67
|
+
(fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales.default) && getTranslation(fallbackLocales.default) || sourceLocale && sourceLocale === locale && sourceLocaleFallback(catalogs[sourceLocale], key);
|
|
68
|
+
if (!translation) {
|
|
69
|
+
onMissing && onMissing({
|
|
70
|
+
id: key,
|
|
71
|
+
source: msg.message || sourceLocaleFallback(catalogs[sourceLocale], key)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return translation || sourceLocale && sourceLocaleFallback(catalogs[sourceLocale], key) ||
|
|
75
|
+
// take from template
|
|
76
|
+
msg.message || key;
|
|
77
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.mergeCatalog = mergeCatalog;
|
|
7
|
+
var R = _interopRequireWildcard(require("ramda"));
|
|
8
|
+
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); }
|
|
9
|
+
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; }
|
|
10
|
+
function mergeCatalog(prevCatalog, nextCatalog, forSourceLocale, options) {
|
|
11
|
+
const nextKeys = Object.keys(nextCatalog);
|
|
12
|
+
const prevKeys = R.keys(prevCatalog).map(String);
|
|
13
|
+
const newKeys = R.difference(nextKeys, prevKeys);
|
|
14
|
+
const mergeKeys = R.intersection(nextKeys, prevKeys);
|
|
15
|
+
const obsoleteKeys = R.difference(prevKeys, nextKeys);
|
|
16
|
+
|
|
17
|
+
// Initialize new catalog with new keys
|
|
18
|
+
const newMessages = R.mapObjIndexed((message, key) => ({
|
|
19
|
+
translation: forSourceLocale ? message.message || key : "",
|
|
20
|
+
...message
|
|
21
|
+
}), R.pick(newKeys, nextCatalog));
|
|
22
|
+
|
|
23
|
+
// Merge translations from previous catalog
|
|
24
|
+
const mergedMessages = mergeKeys.map(key => {
|
|
25
|
+
const updateFromDefaults = forSourceLocale && (prevCatalog[key].translation === prevCatalog[key].message || options.overwrite);
|
|
26
|
+
const translation = updateFromDefaults ? nextCatalog[key].message || key : prevCatalog[key].translation;
|
|
27
|
+
return {
|
|
28
|
+
[key]: {
|
|
29
|
+
translation,
|
|
30
|
+
...R.omit(["obsolete, translation"], nextCatalog[key])
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Mark all remaining translations as obsolete
|
|
36
|
+
// Only if *options.files* is not provided
|
|
37
|
+
const obsoleteMessages = obsoleteKeys.map(key => ({
|
|
38
|
+
[key]: {
|
|
39
|
+
...prevCatalog[key],
|
|
40
|
+
obsolete: !options.files
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
return R.mergeAll([newMessages, ...mergedMessages, ...obsoleteMessages]);
|
|
44
|
+
}
|