locize-cli 10.0.3 → 10.1.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ 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
+ ## [10.1.1](https://github.com/locize/locize-cli/compare/v10.1.0...v10.1.1) - 2025-07-12
9
+
10
+ - create-branch: nicer feedback, if branch already exists
11
+
12
+ ## [10.1.0](https://github.com/locize/locize-cli/compare/v10.0.3...v10.1.0) - 2025-07-10
13
+
14
+ - introduce branching features
15
+
8
16
  ## [10.0.3](https://github.com/locize/locize-cli/compare/v10.0.2...v10.0.3) - 2025-07-09
9
17
 
10
18
  - introduce `--ignore-if-version-exists` option for `copy-version`
package/README.md CHANGED
@@ -325,6 +325,27 @@ locize format path/to/dictionary --format android
325
325
  ```
326
326
 
327
327
 
328
+ ## Working with branches
329
+ ### Create a new branch
330
+
331
+ ```sh
332
+ locize create-branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba --ver latest
333
+ ```
334
+
335
+ ### Sync or Download that branch
336
+
337
+ ```sh
338
+ locize sync --branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
339
+
340
+ locize download --branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
341
+ ```
342
+
343
+ ### Merge that branch
344
+
345
+ ```sh
346
+ locize merge-branch featureXYZ --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba --delete true
347
+ ```
348
+
328
349
 
329
350
  ## Other information
330
351
 
package/bin/locize CHANGED
@@ -26,6 +26,8 @@ const removeVersion = require('../removeVersion.js');
26
26
  const publishVersion = require('../publishVersion');
27
27
  const deleteNamespace = require('../deleteNamespace');
28
28
  const formatFn = require('../format');
29
+ const createBranch = require('../createBranch');
30
+ const mergeBranch = require('../mergeBranch');
29
31
 
30
32
  var config = {};
31
33
  try {
@@ -239,6 +241,7 @@ program
239
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}}`)
240
242
  .option('-c, --clean <true|false>', 'Removes all local files by removing the whole folder (default: false)', 'false')
241
243
  .option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
244
+ .option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
242
245
  .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
243
246
  .action((options) => {
244
247
  try {
@@ -275,6 +278,8 @@ program
275
278
 
276
279
  const pathMask = options.pathMask;
277
280
 
281
+ const branch = options.branch;
282
+
278
283
  download({
279
284
  apiKey: apiKey,
280
285
  projectId: projectId,
@@ -289,7 +294,8 @@ program
289
294
  clean: clean,
290
295
  languageFolderPrefix: languageFolderPrefix,
291
296
  pathMask: pathMask,
292
- unpublished: unpublished
297
+ unpublished: unpublished,
298
+ branch: branch
293
299
  });
294
300
  })
295
301
  .on('--help', () => {
@@ -380,6 +386,7 @@ program
380
386
  .option('-n, --namespace <ns>', 'The namespace that should be targeted (you can also pass a comma separated list)')
381
387
  .option('-g, --get-path <url>', `Specify the get-path url that should be used (default: ${getPathUrl})`)
382
388
  .option('-up, --unpublished <true|false>', 'Downloads the current (unpublished) translations. This will generate private download costs (default: false)', 'false')
389
+ .option('-b, --branch <branch>', 'The branch name (or id) that should be targeted')
383
390
  .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
384
391
  .action((options) => {
385
392
  try {
@@ -428,6 +435,7 @@ program
428
435
  const unpublished = options.unpublished === 'true';
429
436
  const autoCreatePath = options.autoCreatePath === 'true';
430
437
  const backupDeletedPath = options.backupDeletedPath;
438
+ const branch = options.branch;
431
439
 
432
440
  sync({
433
441
  apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
@@ -453,7 +461,8 @@ program
453
461
  pathMask: pathMask,
454
462
  unpublished: unpublished,
455
463
  autoCreatePath: autoCreatePath,
456
- backupDeletedPath: backupDeletedPath
464
+ backupDeletedPath: backupDeletedPath,
465
+ branch: branch
457
466
  });
458
467
  })
459
468
  .on('--help', () => {
@@ -591,8 +600,8 @@ program
591
600
  .on('--help', () => {
592
601
  console.log(' Examples:');
593
602
  console.log();
594
- console.log(' $ locize copy-version latest"');
595
- console.log(' $ locize copy-version latest --ver production"');
603
+ console.log(' $ locize copy-version latest');
604
+ console.log(' $ locize copy-version latest --ver production');
596
605
  console.log(' $ locize copy-version latest --api-key <apiKey> --project-id <projectId> --ver <version>');
597
606
  console.log();
598
607
  });
@@ -635,7 +644,7 @@ program
635
644
  .on('--help', () => {
636
645
  console.log(' Examples:');
637
646
  console.log();
638
- console.log(' $ locize remove-version tmp-ver"');
647
+ console.log(' $ locize remove-version tmp-ver');
639
648
  console.log(' $ locize remove-version tmp-ver --api-key <apiKey> --project-id <projectId>');
640
649
  console.log();
641
650
  });
@@ -685,8 +694,8 @@ program
685
694
  .on('--help', () => {
686
695
  console.log(' Examples:');
687
696
  console.log();
688
- console.log(' $ locize publish-version"');
689
- console.log(' $ locize publish-version --ver production"');
697
+ console.log(' $ locize publish-version');
698
+ console.log(' $ locize publish-version --ver production');
690
699
  console.log(' $ locize publish-version --api-key <apiKey> --project-id <projectId> --ver <version>');
691
700
  console.log();
692
701
  });
@@ -781,6 +790,100 @@ program
781
790
  console.log();
782
791
  });
783
792
 
793
+ program
794
+ .command('create-branch <branch>')
795
+ .alias('cb')
796
+ .description('create branch')
797
+ .option('-k, --api-key <apiKey>', 'The api-key that should be used')
798
+ .option('-v, --ver <version>', 'The target version to be used to copy to (default: latest)')
799
+ .option('-i, --project-id <projectId>', 'The project-id that should be used')
800
+ .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
801
+ .action((branch, options) => {
802
+ try {
803
+ config = ini.parse(fs.readFileSync(options.configPath, 'utf-8')) || config;
804
+ } catch (e) {}
805
+
806
+ const apiKey = options.apiKey || config.apiKey || process.env.LOCIZE_API_KEY || process.env.LOCIZE_KEY;
807
+ if (!apiKey) {
808
+ console.error(' error: missing required argument `apiKey`');
809
+ process.exit(1);
810
+ return;
811
+ }
812
+
813
+ const projectId = options.projectId || config.projectId || process.env.LOCIZE_PROJECTID || process.env.LOCIZE_PID;
814
+ if (!projectId) {
815
+ console.error(' error: missing required argument `projectId`');
816
+ process.exit(1);
817
+ return;
818
+ }
819
+
820
+ const version = options.ver || config.ver || config.version || process.env.LOCIZE_VERSION || process.env.LOCIZE_VER || 'latest';
821
+
822
+ const getPath = options.getPath || config.getPath || options.addPath || config.addPath || getPathUrl;
823
+
824
+ createBranch({
825
+ apiKey: apiKey,
826
+ projectId: projectId,
827
+ apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
828
+ version: version,
829
+ branch: branch
830
+ });
831
+ })
832
+ .on('--help', () => {
833
+ console.log(' Examples:');
834
+ console.log();
835
+ console.log(' $ locize creaete-branch featureX');
836
+ console.log(' $ locize creaete-branch featureX --ver production');
837
+ console.log(' $ locize creaete-branch featureX --api-key <apiKey> --project-id <projectId> --ver <version>');
838
+ console.log();
839
+ });
840
+
841
+ program
842
+ .command('merge-branch <branch>')
843
+ .alias('mb')
844
+ .description('merge branch')
845
+ .option('-k, --api-key <apiKey>', 'The api-key that should be used')
846
+ .option('-i, --project-id <projectId>', 'The project-id that should be used')
847
+ .option('-d, --delete <true|false>', 'This will delete the branch after merging. (default: false)', 'false')
848
+ .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`)
849
+ .action((branch, options) => {
850
+ try {
851
+ config = ini.parse(fs.readFileSync(options.configPath, 'utf-8')) || config;
852
+ } catch (e) {}
853
+
854
+ const apiKey = options.apiKey || config.apiKey || process.env.LOCIZE_API_KEY || process.env.LOCIZE_KEY;
855
+ if (!apiKey) {
856
+ console.error(' error: missing required argument `apiKey`');
857
+ process.exit(1);
858
+ return;
859
+ }
860
+
861
+ const projectId = options.projectId || config.projectId || process.env.LOCIZE_PROJECTID || process.env.LOCIZE_PID;
862
+ if (!projectId) {
863
+ console.error(' error: missing required argument `projectId`');
864
+ process.exit(1);
865
+ return;
866
+ }
867
+
868
+ const getPath = options.getPath || config.getPath || options.addPath || config.addPath || getPathUrl;
869
+
870
+ mergeBranch({
871
+ apiKey: apiKey,
872
+ projectId: projectId,
873
+ apiPath: url.parse(getPath).protocol + '//' + url.parse(getPath).host,
874
+ delete: options.delete === 'true',
875
+ branch: branch
876
+ });
877
+ })
878
+ .on('--help', () => {
879
+ console.log(' Examples:');
880
+ console.log();
881
+ console.log(' $ locize merge-branch featureX');
882
+ console.log(' $ locize merge-branch <projectId-of-branch>');
883
+ console.log(' $ locize merge-branch featureX --delete true');
884
+ console.log(' $ locize merge-branch featureX --api-key <apiKey> --project-id <projectId> --delete true');
885
+ console.log();
886
+ });
784
887
 
785
888
  program.parse(process.argv);
786
889
 
@@ -0,0 +1,61 @@
1
+ const colors = require('colors');
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
+ };
12
+
13
+ const createBranch = (opt, cb) => {
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...'));
33
+
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);
48
+ return;
49
+ }
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 + ')'));
53
+ return;
54
+ }
55
+ if (!cb) console.log(colors.green('creating branch "' + obj.name + '" (' + obj.id + ') successful'));
56
+ if (cb) cb(null, obj);
57
+ });
58
+ });
59
+ };
60
+
61
+ module.exports = createBranch;
package/download.js CHANGED
@@ -13,6 +13,8 @@ const formats = require('./formats');
13
13
  const getProjectStats = require('./getProjectStats');
14
14
  const reversedFileExtensionsMap = formats.reversedFileExtensionsMap;
15
15
  const locize2xcstrings = require('locize-xcstrings/cjs/locize2xcstrings');
16
+ const getBranches = require('./getBranches');
17
+ const isValidUuid = require('./isValidUuid');
16
18
 
17
19
  function getInfosInUrl(download) {
18
20
  const splitted = download.key.split('/');
@@ -370,25 +372,7 @@ const filterDownloads = (opt, downloads) => {
370
372
  return filterDownloadsLanguages(opt, downloads);
371
373
  };
372
374
 
373
- const download = (opt, cb) => {
374
- opt.format = opt.format || 'json';
375
- if (!reversedFileExtensionsMap[opt.format]) {
376
- return handleError(new Error(`${opt.format} is not a valid format!`), cb);
377
- }
378
-
379
- if (opt.skipEmpty === undefined) opt.skipEmpty = true;
380
- opt.apiPath = opt.apiPath || 'https://api.locize.app';
381
- opt.version = opt.version || 'latest';
382
- opt.languageFolderPrefix = opt.languageFolderPrefix || '';
383
- opt.path = opt.path || opt.target;
384
- opt.pathMaskInterpolationPrefix = opt.pathMaskInterpolationPrefix || '{{';
385
- opt.pathMaskInterpolationSuffix = opt.pathMaskInterpolationSuffix || '}}';
386
- opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
387
- opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
388
- if (opt.unpublished && !opt.apiKey) {
389
- return handleError(new Error('Please provide also an api-key!'), cb);
390
- }
391
-
375
+ const continueToDownload = (opt, cb) => {
392
376
  var url = opt.apiPath + '/download/' + opt.projectId;
393
377
 
394
378
  if (opt.namespace && opt.namespace.indexOf(',') > 0 && opt.namespace.indexOf(' ') < 0) {
@@ -468,4 +452,44 @@ const download = (opt, cb) => {
468
452
  });
469
453
  };
470
454
 
455
+ const download = (opt, cb) => {
456
+ opt.format = opt.format || 'json';
457
+ if (!reversedFileExtensionsMap[opt.format]) {
458
+ return handleError(new Error(`${opt.format} is not a valid format!`), cb);
459
+ }
460
+
461
+ if (opt.skipEmpty === undefined) opt.skipEmpty = true;
462
+ opt.apiPath = opt.apiPath || 'https://api.locize.app';
463
+ opt.version = opt.version || 'latest';
464
+ opt.languageFolderPrefix = opt.languageFolderPrefix || '';
465
+ opt.path = opt.path || opt.target;
466
+ opt.pathMaskInterpolationPrefix = opt.pathMaskInterpolationPrefix || '{{';
467
+ opt.pathMaskInterpolationSuffix = opt.pathMaskInterpolationSuffix || '}}';
468
+ opt.pathMask = opt.pathMask || `${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}${path.sep}${opt.pathMaskInterpolationPrefix}namespace${opt.pathMaskInterpolationSuffix}`;
469
+ opt.pathMask = opt.pathMask.replace(`${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`, `${opt.languageFolderPrefix}${opt.pathMaskInterpolationPrefix}language${opt.pathMaskInterpolationSuffix}`);
470
+ if (opt.unpublished && !opt.apiKey) {
471
+ return handleError(new Error('Please provide also an api-key!'), cb);
472
+ }
473
+
474
+ if (opt.branch) {
475
+ getBranches(opt, (err, branches) => {
476
+ if (err) return handleError(err, cb);
477
+
478
+ let b;
479
+ if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
480
+ if (!b) b = branches.find((br) => br.name === opt.branch);
481
+ if (!b) {
482
+ return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
483
+ }
484
+ opt.projectId = b.id;
485
+ opt.version = b.version;
486
+
487
+ continueToDownload(opt, cb);
488
+ });
489
+ return;
490
+ }
491
+
492
+ continueToDownload(opt, cb);
493
+ };
494
+
471
495
  module.exports = download;
package/getBranches.js ADDED
@@ -0,0 +1,40 @@
1
+ const colors = require('colors');
2
+ const request = require('./request');
3
+
4
+ const getBranches = (opt, cb) => {
5
+ request(opt.apiPath + '/branches/' + opt.projectId, {
6
+ method: 'get',
7
+ headers: {
8
+ 'Authorization': opt.apiKey
9
+ }
10
+ }, (err, res, obj) => {
11
+ if (err || (obj && (obj.errorMessage || obj.message))) {
12
+ if (!cb) console.log(colors.red('getting branches failed...'));
13
+
14
+ if (err) {
15
+ if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
16
+ if (cb) cb(err);
17
+ return;
18
+ }
19
+ if (obj && (obj.errorMessage || obj.message)) {
20
+ if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
21
+ if (cb) cb(new Error((obj.errorMessage || obj.message)));
22
+ return;
23
+ }
24
+ }
25
+ if (res.status === 404) {
26
+ if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
27
+ if (cb) cb(null, null);
28
+ return;
29
+ }
30
+ if (res.status >= 300) {
31
+ if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
32
+ if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
33
+ return;
34
+ }
35
+ if (!cb) console.log(colors.green('getting branches successful'));
36
+ if (cb) cb(null, obj);
37
+ });
38
+ };
39
+
40
+ module.exports = getBranches;
package/getJob.js CHANGED
@@ -32,7 +32,7 @@ const getJob = (opt, jobId, cb) => {
32
32
  if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
33
33
  return;
34
34
  }
35
- if (!cb) console.log(colors.green('getting job succesfull'));
35
+ if (!cb) console.log(colors.green('getting job successful'));
36
36
  if (cb) cb(null, obj);
37
37
  });
38
38
  };
@@ -32,7 +32,7 @@ const getProjectStats = (opt, cb) => {
32
32
  if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
33
33
  return;
34
34
  }
35
- if (!cb) console.log(colors.green('getting project stats succesfull'));
35
+ if (!cb) console.log(colors.green('getting project stats successful'));
36
36
  if (cb) cb(null, obj);
37
37
  });
38
38
  };
package/isValidUuid.js ADDED
@@ -0,0 +1,2 @@
1
+ const uuidRegex = /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
2
+ module.exports = (id) => uuidRegex.test(id);
package/mergeBranch.js ADDED
@@ -0,0 +1,98 @@
1
+ const colors = require('colors');
2
+ const request = require('./request');
3
+ const getBranches = require('./getBranches');
4
+ const isValidUuid = require('./isValidUuid');
5
+ const getJob = require('./getJob');
6
+
7
+ const mergeBranch = (opt, cb) => {
8
+ const queryParams = new URLSearchParams();
9
+ if (opt.delete) {
10
+ queryParams.append('delete', 'true');
11
+ }
12
+ const queryString = queryParams.size > 0 ? '?' + queryParams.toString() : '';
13
+ request(opt.apiPath + '/branch/merge/' + opt.branch + queryString, {
14
+ method: 'post',
15
+ headers: {
16
+ 'Authorization': opt.apiKey
17
+ }
18
+ }, (err, res, obj) => {
19
+ if (err || (obj && (obj.errorMessage || obj.message))) {
20
+ if (!cb) console.log(colors.red('merging branch failed...'));
21
+
22
+ if (err) {
23
+ if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
24
+ if (cb) cb(err);
25
+ return;
26
+ }
27
+ if (obj && (obj.errorMessage || obj.message)) {
28
+ if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1); }
29
+ if (cb) cb(new Error((obj.errorMessage || obj.message)));
30
+ return;
31
+ }
32
+ }
33
+ if (res.status === 404) {
34
+ if (!cb) { console.error(colors.yellow(res.statusText + ' (' + res.status + ')')); process.exit(1); }
35
+ if (cb) cb(null, null);
36
+ return;
37
+ }
38
+ if (res.status >= 300) {
39
+ if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1); }
40
+ if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'));
41
+ return;
42
+ }
43
+
44
+ if (!obj || !obj.jobId) {
45
+ if (!cb) { console.error(colors.red('No jobId! Something went wrong!')); process.exit(1); }
46
+ if (cb) cb(new Error('No jobId! Something went wrong!'));
47
+ return;
48
+ }
49
+
50
+ (function waitForJob() {
51
+ getJob(opt, obj.jobId, (err, job) => {
52
+ if (err) {
53
+ if (!cb) { console.error(colors.red(err.message)); process.exit(1); }
54
+ if (cb) cb(err);
55
+ return;
56
+ }
57
+
58
+ if (job && !job.timeouted) {
59
+ setTimeout(waitForJob, 2000);
60
+ return;
61
+ }
62
+
63
+ if (job && job.timeouted) {
64
+ if (!cb) { console.error(colors.red('Job timeouted!')); process.exit(1); }
65
+ if (cb) cb(new Error('Job timeouted!'));
66
+ return;
67
+ }
68
+
69
+ if (!cb) console.log(colors.green('merging branch successful'));
70
+ if (cb) cb(null);
71
+ });
72
+ })();
73
+ });
74
+ };
75
+
76
+ const handleError = (err, cb) => {
77
+ if (!cb && err) {
78
+ console.error(colors.red(err.stack));
79
+ process.exit(1);
80
+ }
81
+ if (cb) cb(err);
82
+ };
83
+
84
+ module.exports = (opt, cb) => {
85
+ getBranches(opt, (err, branches) => {
86
+ if (err) return handleError(err, cb);
87
+
88
+ let b;
89
+ if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
90
+ if (!b) b = branches.find((br) => br.name === opt.branch);
91
+ if (!b) {
92
+ return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
93
+ }
94
+ opt.branch = b.id;
95
+
96
+ mergeBranch(opt, cb);
97
+ });
98
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locize-cli",
3
- "version": "10.0.3",
3
+ "version": "10.1.1",
4
4
  "description": "locize cli to import locales",
5
5
  "main": "index.js",
6
6
  "bin": {
package/sync.js CHANGED
@@ -18,6 +18,8 @@ const deleteNamespace = require('./deleteNamespace');
18
18
  const getProjectStats = require('./getProjectStats');
19
19
  const reversedFileExtensionsMap = formats.reversedFileExtensionsMap;
20
20
  const locize2xcstrings = require('locize-xcstrings/cjs/locize2xcstrings');
21
+ const getBranches = require('./getBranches');
22
+ const isValidUuid = require('./isValidUuid');
21
23
 
22
24
  const getDirectories = (srcpath) => {
23
25
  return fs.readdirSync(srcpath).filter((file) => {
@@ -659,6 +661,49 @@ const handleSync = (opt, remoteLanguages, localNamespaces, cb) => {
659
661
  });
660
662
  };
661
663
 
664
+ const continueToSync = (opt, cb) => {
665
+ console.log(colors.grey('checking remote (locize)...'));
666
+ getRemoteLanguages(opt, (err, remoteLanguages) => {
667
+ if (err) return handleError(err, cb);
668
+
669
+ if (opt.referenceLanguageOnly && opt.language && opt.referenceLanguage !== opt.language) {
670
+ opt.referenceLanguage = opt.language;
671
+ }
672
+ if (opt.referenceLanguageOnly && !opt.language && opt.languages && opt.languages.length > 0 && opt.languages.indexOf(opt.referenceLanguage) < 0) {
673
+ opt.referenceLanguage = opt.languages[0];
674
+ }
675
+
676
+ if (opt.referenceLanguageOnly) {
677
+ console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''} only reference language...`));
678
+ parseLocalReference(opt, (err, localNamespaces) => {
679
+ if (err) return handleError(err, cb);
680
+
681
+ if (!opt.dry && opt.cleanLocalFiles) {
682
+ localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
683
+ localNamespaces = [];
684
+ }
685
+
686
+ console.log(colors.grey('calculate diffs...'));
687
+ handleSync(opt, remoteLanguages, localNamespaces, cb);
688
+ });
689
+ return;
690
+ }
691
+
692
+ console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''}...`));
693
+ parseLocalLanguages(opt, remoteLanguages, (err, localNamespaces) => {
694
+ if (err) return handleError(err, cb);
695
+
696
+ if (!opt.dry && opt.cleanLocalFiles) {
697
+ localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
698
+ localNamespaces = [];
699
+ }
700
+
701
+ console.log(colors.grey('calculate diffs...'));
702
+ handleSync(opt, remoteLanguages, localNamespaces, cb);
703
+ });
704
+ });
705
+ };
706
+
662
707
  const sync = (opt, cb) => {
663
708
  opt.format = opt.format || 'json';
664
709
  if (!reversedFileExtensionsMap[opt.format]) {
@@ -695,46 +740,25 @@ const sync = (opt, cb) => {
695
740
  return handleError(new Error('Please provide also an api-key!'), cb);
696
741
  }
697
742
 
698
- console.log(colors.grey('checking remote (locize)...'));
699
- getRemoteLanguages(opt, (err, remoteLanguages) => {
700
- if (err) return handleError(err, cb);
701
-
702
- if (opt.referenceLanguageOnly && opt.language && opt.referenceLanguage !== opt.language) {
703
- opt.referenceLanguage = opt.language;
704
- }
705
- if (opt.referenceLanguageOnly && !opt.language && opt.languages && opt.languages.length > 0 && opt.languages.indexOf(opt.referenceLanguage) < 0) {
706
- opt.referenceLanguage = opt.languages[0];
707
- }
708
-
709
- if (opt.referenceLanguageOnly) {
710
- console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''} only reference language...`));
711
- parseLocalReference(opt, (err, localNamespaces) => {
712
- if (err) return handleError(err, cb);
713
-
714
- if (!opt.dry && opt.cleanLocalFiles) {
715
- localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
716
- localNamespaces = [];
717
- }
718
-
719
- console.log(colors.grey('calculate diffs...'));
720
- handleSync(opt, remoteLanguages, localNamespaces, cb);
721
- });
722
- return;
723
- }
724
-
725
- console.log(colors.grey(`checking local${opt.path !== process.cwd() ? ` (${opt.path})` : ''}...`));
726
- parseLocalLanguages(opt, remoteLanguages, (err, localNamespaces) => {
743
+ if (opt.branch) {
744
+ getBranches(opt, (err, branches) => {
727
745
  if (err) return handleError(err, cb);
728
746
 
729
- if (!opt.dry && opt.cleanLocalFiles) {
730
- localNamespaces.forEach((ln) => fs.unlinkSync(ln.path));
731
- localNamespaces = [];
747
+ let b;
748
+ if (isValidUuid(opt.branch)) b = branches.find((br) => br.id === opt.branch);
749
+ if (!b) b = branches.find((br) => br.name === opt.branch);
750
+ if (!b) {
751
+ return handleError(new Error(`Branch ${opt.branch} not found!`), cb);
732
752
  }
753
+ opt.projectId = b.id;
754
+ opt.version = b.version;
733
755
 
734
- console.log(colors.grey('calculate diffs...'));
735
- handleSync(opt, remoteLanguages, localNamespaces, cb);
756
+ continueToSync(opt, cb);
736
757
  });
737
- });
758
+ return;
759
+ }
760
+
761
+ continueToSync(opt, cb);
738
762
  };
739
763
 
740
764
  module.exports = sync;