locize-cli 10.1.0 → 10.2.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/CHANGELOG.md +9 -0
- package/bin/locize +9 -2
- package/createBranch.js +48 -28
- package/download.js +3 -0
- package/getRemoteNamespace.js +15 -1
- package/package.json +1 -1
- package/sync.js +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Project versioning adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
Change log format is based on [Keep a Changelog](http://keepachangelog.com/).
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
## [10.2.0](https://github.com/locize/locize-cli/compare/v10.1.1...v10.2.0) - 2025-07-16
|
|
10
|
+
|
|
11
|
+
- download/sync introduce `--overridden-only` option for branches or tenants
|
|
12
|
+
|
|
13
|
+
## [10.1.1](https://github.com/locize/locize-cli/compare/v10.1.0...v10.1.1) - 2025-07-12
|
|
14
|
+
|
|
15
|
+
- create-branch: nicer feedback, if branch already exists
|
|
16
|
+
|
|
8
17
|
## [10.1.0](https://github.com/locize/locize-cli/compare/v10.0.3...v10.1.0) - 2025-07-10
|
|
9
18
|
|
|
10
19
|
- introduce branching features
|
package/bin/locize
CHANGED
|
@@ -241,6 +241,7 @@ program
|
|
|
241
241
|
.option('-m, --path-mask <mask>', 'This will define the folder and file structure; do not add a file extension (default: {{language}}/{{namespace}})', `{{language}}${path.sep}{{namespace}}`)
|
|
242
242
|
.option('-c, --clean <true|false>', 'Removes all local files by removing the whole folder (default: false)', 'false')
|
|
243
243
|
.option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
|
|
244
|
+
.option('-oo, --overridden-only <true|false>', 'Downloads only the current overridden (unpublished) translations of a tenant or branch project. This will generate private download costs (default: false)', 'false')
|
|
244
245
|
.option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
|
|
245
246
|
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
246
247
|
.action((options) => {
|
|
@@ -274,6 +275,8 @@ program
|
|
|
274
275
|
|
|
275
276
|
const unpublished = options.unpublished === 'true';
|
|
276
277
|
|
|
278
|
+
const overriddenOnly = options.overriddenOnly === 'true';
|
|
279
|
+
|
|
277
280
|
const languageFolderPrefix = options.languageFolderPrefix || '';
|
|
278
281
|
|
|
279
282
|
const pathMask = options.pathMask;
|
|
@@ -295,7 +298,8 @@ program
|
|
|
295
298
|
languageFolderPrefix: languageFolderPrefix,
|
|
296
299
|
pathMask: pathMask,
|
|
297
300
|
unpublished: unpublished,
|
|
298
|
-
branch: branch
|
|
301
|
+
branch: branch,
|
|
302
|
+
overriddenOnly: overriddenOnly
|
|
299
303
|
});
|
|
300
304
|
})
|
|
301
305
|
.on('--help', () => {
|
|
@@ -386,6 +390,7 @@ program
|
|
|
386
390
|
.option('-n, --namespace <ns>', 'The namespace that should be targeted (you can also pass a comma separated list)')
|
|
387
391
|
.option('-g, --get-path <url>', `Specify the get-path url that should be used (default: ${getPathUrl})`)
|
|
388
392
|
.option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
|
|
393
|
+
.option('-oo, --overridden-only <true|false>', 'Downloads only the current overridden (unpublished) translations of a tenant or branch project. This will generate private download costs (default: false)', 'false')
|
|
389
394
|
.option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
|
|
390
395
|
.option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
|
|
391
396
|
.action((options) => {
|
|
@@ -433,6 +438,7 @@ program
|
|
|
433
438
|
const compareModificationTime = options.compareModificationTime === 'true';
|
|
434
439
|
const pathMask = options.pathMask;
|
|
435
440
|
const unpublished = options.unpublished === 'true';
|
|
441
|
+
const overriddenOnly = options.overriddenOnly === 'true';
|
|
436
442
|
const autoCreatePath = options.autoCreatePath === 'true';
|
|
437
443
|
const backupDeletedPath = options.backupDeletedPath;
|
|
438
444
|
const branch = options.branch;
|
|
@@ -462,7 +468,8 @@ program
|
|
|
462
468
|
unpublished: unpublished,
|
|
463
469
|
autoCreatePath: autoCreatePath,
|
|
464
470
|
backupDeletedPath: backupDeletedPath,
|
|
465
|
-
branch: branch
|
|
471
|
+
branch: branch,
|
|
472
|
+
overriddenOnly: overriddenOnly
|
|
466
473
|
});
|
|
467
474
|
})
|
|
468
475
|
.on('--help', () => {
|
package/createBranch.js
CHANGED
|
@@ -1,40 +1,60 @@
|
|
|
1
1
|
const colors = require('colors');
|
|
2
2
|
const request = require('./request');
|
|
3
|
+
const getBranches = require('./getBranches');
|
|
4
|
+
|
|
5
|
+
const handleError = (err, cb) => {
|
|
6
|
+
if (!cb && err) {
|
|
7
|
+
console.error(colors.red(err.stack));
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
if (cb) cb(err);
|
|
11
|
+
};
|
|
3
12
|
|
|
4
13
|
const createBranch = (opt, cb) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
getBranches(opt, (err, branches) => {
|
|
15
|
+
if (err) return handleError(err, cb);
|
|
16
|
+
|
|
17
|
+
const b = branches.find((br) => br.name === opt.branch);
|
|
18
|
+
if (b) {
|
|
19
|
+
if (!cb) console.log(colors.green('creating branch "' + b.name + '" (' + b.id + ') not necessary, because already existing'));
|
|
20
|
+
if (cb) cb(null, b);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
request(opt.apiPath + '/branch/create/' + opt.projectId + '/' + opt.version, {
|
|
25
|
+
method: 'post',
|
|
26
|
+
headers: {
|
|
27
|
+
'Authorization': opt.apiKey
|
|
28
|
+
},
|
|
29
|
+
body: { name: opt.branch }
|
|
30
|
+
}, (err, res, obj) => {
|
|
31
|
+
if (err || (obj && (obj.errorMessage || obj.message))) {
|
|
32
|
+
if (!cb) console.log(colors.red('creating branch failed...'));
|
|
14
33
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
34
|
+
if (err) {
|
|
35
|
+
if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
|
|
36
|
+
if (cb) cb(err);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (obj && (obj.errorMessage || obj.message)) {
|
|
40
|
+
if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
|
|
41
|
+
if (cb) cb(new Error((obj.errorMessage || obj.message)));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (res.status === 404) {
|
|
46
|
+
if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
47
|
+
if (cb) cb(null, null);
|
|
18
48
|
return;
|
|
19
49
|
}
|
|
20
|
-
if (
|
|
21
|
-
if (!cb) { console.error(colors.red((
|
|
22
|
-
if (cb) cb(new Error((
|
|
50
|
+
if (res.status >= 300) {
|
|
51
|
+
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
52
|
+
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
23
53
|
return;
|
|
24
54
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (cb) cb(null, null);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
if (res.status >= 300) {
|
|
32
|
-
if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
|
|
33
|
-
if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if (!cb) console.log(colors.green('creating branch "' + obj.name + '" (' + obj.id + ') successful'));
|
|
37
|
-
if (cb) cb(null, obj);
|
|
55
|
+
if (!cb) console.log(colors.green('creating branch "' + obj.name + '" (' + obj.id + ') successful'));
|
|
56
|
+
if (cb) cb(null, obj);
|
|
57
|
+
});
|
|
38
58
|
});
|
|
39
59
|
};
|
|
40
60
|
|
package/download.js
CHANGED
|
@@ -467,6 +467,9 @@ const download = (opt, cb) => {
|
|
|
467
467
|
opt.pathMaskInterpolationSuffix = opt.pathMaskInterpolationSuffix || '}}';
|
|
468
468
|
opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
|
|
469
469
|
opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
|
|
470
|
+
if (opt.overriddenOnly) {
|
|
471
|
+
opt.unpublished = true;
|
|
472
|
+
}
|
|
470
473
|
if (opt.unpublished && !opt.apiKey) {
|
|
471
474
|
return handleError(new Error('Please provide also an api-key!'), cb);
|
|
472
475
|
}
|
package/getRemoteNamespace.js
CHANGED
|
@@ -23,7 +23,7 @@ function onlyKeysFlat(resources, prefix, ret) {
|
|
|
23
23
|
|
|
24
24
|
const pullNamespacePaged = (opt, lng, ns, cb, next, retry) => {
|
|
25
25
|
next = next || '';
|
|
26
|
-
request(opt.apiPath + '/pull/' + opt.projectId + '/' + opt.version + '/' + lng + '/' + ns + '?' + 'next=' + next + (opt.raw ? '&raw=true' : '') + '&ts=' + Date.now(), {
|
|
26
|
+
request(opt.apiPath + '/pull/' + opt.projectId + '/' + opt.version + '/' + lng + '/' + ns + '?' + 'next=' + next + ((opt.raw || opt.overriddenOnly) ? '&raw=true' : '') + '&ts=' + Date.now(), {
|
|
27
27
|
method: 'get',
|
|
28
28
|
headers: {
|
|
29
29
|
'Authorization': opt.apiKey
|
|
@@ -47,6 +47,20 @@ const pullNamespacePaged = (opt, lng, ns, cb, next, retry) => {
|
|
|
47
47
|
return cb(new Error(res.statusText + ' (' + res.status + ')'));
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
if (opt.overriddenOnly && obj) {
|
|
51
|
+
const newObj = {};
|
|
52
|
+
Object.keys(obj).forEach((k) => {
|
|
53
|
+
if (obj[k].overrides !== undefined) {
|
|
54
|
+
if (opt.raw) {
|
|
55
|
+
newObj[k] = obj[k];
|
|
56
|
+
} else {
|
|
57
|
+
newObj[k] = obj[k].value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
obj = newObj;
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
cb(null, {
|
|
51
65
|
result: opt.raw ? sortFlatResources(onlyKeysFlat(obj)) : sortFlatResources(flatten(obj)),
|
|
52
66
|
next: res.headers.get('x-next-page'),
|
package/package.json
CHANGED
package/sync.js
CHANGED
|
@@ -736,6 +736,9 @@ const sync = (opt, cb) => {
|
|
|
736
736
|
opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
|
|
737
737
|
opt.languageFolderPrefix = opt.languageFolderPrefix || '';
|
|
738
738
|
opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
|
|
739
|
+
if (opt.overriddenOnly) {
|
|
740
|
+
opt.unpublished = true;
|
|
741
|
+
}
|
|
739
742
|
if (opt.unpublished && !opt.apiKey) {
|
|
740
743
|
return handleError(new Error('Please provide also an api-key!'), cb);
|
|
741
744
|
}
|