locize-cli 12.3.1 → 12.4.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 CHANGED
@@ -5,6 +5,21 @@ 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
+ ## [12.4.0](https://github.com/locize/locize-cli/compare/v12.3.1...v12.4.0) - 2026-07-06
9
+
10
+ - xliff: proper support for inline elements (e.g. Angular's
11
+ `<x id="INTERPOLATION" equiv-text="{{ count }}"/>` placeholders, or
12
+ `<ph>`/`<pc>`/`<g>`/`<bpt>` tags from other TMS exports). On import they are
13
+ flattened into stable placeholder tokens inside the translation value
14
+ (previously such values were silently corrupted into arrays); on export the
15
+ tokens are restored as real XLIFF inline elements, so Angular `.xlf` files
16
+ round-trip cleanly. Requires `xliff` >= 6.4.0 (the encoding is implemented
17
+ in the library and shared with the locize CAT editor).
18
+ - xliff: new formats `xliff21`, `xliff22`, `xlf21`, `xlf22` for XLIFF 2.1 and
19
+ 2.2 (import of 2.1/2.2 files already worked via `xliff2`; exports now emit
20
+ the matching `version` attribute). XLIFF 2.1 exports carry the
21
+ OASIS-correct `urn:oasis:names:tc:xliff:document:2.0` core namespace.
22
+
8
23
  ## [12.3.1](https://github.com/locize/locize-cli/compare/v12.3.0...v12.3.1) - 2026-06-18
9
24
 
10
25
  - request: retry transient network failures with exponential backoff and jitter
package/README.md CHANGED
@@ -105,7 +105,7 @@ locize download --cdn-type standard
105
105
  locize download --cdn-type pro
106
106
  ```
107
107
 
108
- or add a format like (json, nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
108
+ or add a format like (json, nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
109
109
 
110
110
  *Special formats:*
111
111
  - use yaml-rails to have the language code in the resulting yaml as root object
@@ -160,7 +160,7 @@ locize sync --cdn-type standard --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672
160
160
  locize sync --cdn-type pro --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
161
161
  ```
162
162
 
163
- or add a format like (json, nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
163
+ or add a format like (json, nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
164
164
 
165
165
  *Special formats:*
166
166
  - use yaml-rails to have the language code in the resulting yaml as root object
@@ -227,7 +227,7 @@ locize save-missing --cdn-type standard --api-key my-api-key-d9de-4f55-9855-a9ef
227
227
  locize save-missing --cdn-type pro --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba
228
228
  ```
229
229
 
230
- or add a format like (json, nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
230
+ or add a format like (json, nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings)
231
231
 
232
232
  ```sh
233
233
  locize save-missing --api-key my-api-key-d9de-4f55-9855-a9ef0ed44672 --project-id my-project-id-93e1-442a-ab35-24331fa294ba --format android
package/dist/cjs/cli.js CHANGED
@@ -50,7 +50,7 @@ const program = new commander.Command();
50
50
 
51
51
  program
52
52
  .description('The official locize CLI.')
53
- .version('12.3.1'); // This string is replaced with the actual version at build time by rollup
53
+ .version('12.4.0'); // This string is replaced with the actual version at build time by rollup
54
54
  // .option('-a, --api-endpoint <url>', `Specify the api-endpoint url that should be used (default: ${defaultApiEndpoint})`)
55
55
  // .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`);
56
56
 
@@ -263,7 +263,7 @@ program
263
263
  .option('-n, --namespace <ns>', 'The namespace that should be targeted')
264
264
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
265
265
  .option('-k, --api-key <apiKey>', 'The api-key that should be used')
266
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
266
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
267
267
  .option('-s, --skip-empty <true|false>', 'Skips to download empty files (default: true)', 'true')
268
268
  .option('-P, --language-folder-prefix <prefix>', 'This will be added as a local folder name prefix in front of the language.', '')
269
269
  .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}}`)
@@ -412,7 +412,7 @@ program
412
412
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
413
413
  .option('-B, --backup-deleted-path <path>', 'Saves the segments that will be deleted in this path')
414
414
  .option('-A, --auto-create-path <true|false>', 'This will automatically make sure the --path is created. (default: true)', 'true')
415
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
415
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
416
416
  .option('-s, --skip-empty <true|false>', 'Skips to download empty files (default: false)', 'false')
417
417
  .option('-c, --clean <true|false>', 'Removes all local files by removing the whole folder (default: false)', 'false')
418
418
  .option('--cf, --clean-local-files <true|false>', 'Removes all local files without removing any folder (default: false)', 'false')
@@ -540,7 +540,7 @@ program
540
540
  .option('-i, --project-id <projectId>', 'The project-id that should be used')
541
541
  .option('-v, --ver <version>', 'Found namespaces will be matched to this version (default: latest)')
542
542
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
543
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
543
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
544
544
  .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}}`)
545
545
  .option('-P, --language-folder-prefix <prefix>', 'This will be added as a local folder name prefix in front of the language.', '')
546
546
  .option('-d, --dry <true|false>', 'Dry run (default: false)', 'false')
@@ -835,7 +835,7 @@ program
835
835
  .command('format [fileOrDirectory]')
836
836
  .alias('ft')
837
837
  .description('format local files')
838
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
838
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
839
839
  .option('-l, --reference-language <lng>', 'Some format conversions need to know the reference language.', 'en')
840
840
  .option('-d, --dry <true|false>', 'Dry run (default: false)', 'false')
841
841
  .action((fileOrDirectory, options) => {
@@ -143,19 +143,17 @@ const convertToDesiredFormat = async (
143
143
  });
144
144
  return stringsFile.compile(data)
145
145
  }
146
- if (
147
- opt.format === 'xliff2' ||
148
- opt.format === 'xliff12' ||
149
- opt.format === 'xlf2' ||
150
- opt.format === 'xlf12'
151
- ) {
152
- const fn =
153
- opt.format === 'xliff12' || opt.format === 'xlf12'
154
- ? xliff.createxliff12
155
- : xliff.createxliff;
146
+ if (['xliff2', 'xliff21', 'xliff22', 'xliff12', 'xlf2', 'xlf21', 'xlf22', 'xlf12'].indexOf(opt.format) > -1) {
156
147
  const refNs = await opt.getNamespace(opt, opt.referenceLanguage, namespace);
157
148
  const prepared = combineSubkeyPreprocessor.prepareExport(refNs, flatten(data));
158
- return await fn(opt.referenceLanguage, lng, prepared.ref, prepared.trg, namespace)
149
+ const js = await xliff.createjs(opt.referenceLanguage, lng, prepared.ref, prepared.trg, namespace);
150
+ if (opt.format === 'xliff12' || opt.format === 'xlf12') {
151
+ return await xliff.jsToXliff12(js, { inlineAsString: true })
152
+ }
153
+ let targetXliffVersion; // default 2.0
154
+ if (opt.format === 'xliff21' || opt.format === 'xlf21') targetXliffVersion = '2.1';
155
+ if (opt.format === 'xliff22' || opt.format === 'xlf22') targetXliffVersion = '2.2';
156
+ return await xliff.js2xliff(js, { targetXliffVersion, inlineAsString: true })
159
157
  }
160
158
  if (opt.format === 'resx') {
161
159
  return await resx.js2resx(flatten(data))
@@ -116,17 +116,13 @@ const convertToFlatFormat = async (opt, data, lng) => {
116
116
  // CRLF => LF
117
117
  return stringsFile.parse(data.toString().replace(/\r\n/g, '\n'), false)
118
118
  }
119
- if (
120
- opt.format === 'xliff2' ||
121
- opt.format === 'xliff12' ||
122
- opt.format === 'xlf2' ||
123
- opt.format === 'xlf12'
124
- ) {
119
+ if (['xliff2', 'xliff21', 'xliff22', 'xliff12', 'xlf2', 'xlf21', 'xlf22', 'xlf12'].indexOf(opt.format) > -1) {
120
+ // xliff2js parses 2.0, 2.1 and 2.2
125
121
  const fn =
126
122
  opt.format === 'xliff12' || opt.format === 'xlf12'
127
123
  ? xliff.xliff12ToJs
128
124
  : xliff.xliff2js;
129
- const res = await fn(data.toString());
125
+ const res = await fn(data.toString(), { inlineAsString: true });
130
126
  res.resources = res.resources || {};
131
127
  const ns = Object.keys(res.resources)[0];
132
128
  const orgRes = res.resources[ns] || res.resources;
@@ -10,8 +10,8 @@ const fileExtensionsMap = {
10
10
  '.yaml': ['yaml', 'yaml-rails', 'yaml-rails-ns', 'yaml-nested'],
11
11
  '.yml': ['yml', 'yml-rails', 'yml-rails-ns', 'yml-nested'],
12
12
  '.xlsx': ['xlsx'],
13
- '.xliff': ['xliff2', 'xliff12'],
14
- '.xlf': ['xlf2', 'xlf12'],
13
+ '.xliff': ['xliff2', 'xliff21', 'xliff22', 'xliff12'],
14
+ '.xlf': ['xlf2', 'xlf21', 'xlf22', 'xlf12'],
15
15
  '.ftl': ['fluent'],
16
16
  '.tmx': ['tmx'],
17
17
  '.php': ['laravel'],
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "locize-cli",
3
- "version": "12.3.1",
3
+ "version": "12.4.0",
4
4
  "type": "commonjs"
5
5
  }
@@ -43,7 +43,7 @@ async function request (url, options) {
43
43
  }
44
44
 
45
45
  options.headers = options.headers || {};
46
- options.headers['User-Agent'] = `locize-cli/v12.3.1 (node/${process.version}; ${process.platform} ${process.arch})`; // This string is replaced with the actual version at build time by rollup
46
+ options.headers['User-Agent'] = `locize-cli/v12.4.0 (node/${process.version}; ${process.platform} ${process.arch})`; // This string is replaced with the actual version at build time by rollup
47
47
  options.headers['X-User-Agent'] = options.headers['User-Agent'];
48
48
  if (options.body || options.method !== 'get') options.headers['Content-Type'] = 'application/json';
49
49
  if (options.body) {
package/dist/esm/cli.js CHANGED
@@ -48,7 +48,7 @@ const program = new Command();
48
48
 
49
49
  program
50
50
  .description('The official locize CLI.')
51
- .version('12.3.1'); // This string is replaced with the actual version at build time by rollup
51
+ .version('12.4.0'); // This string is replaced with the actual version at build time by rollup
52
52
  // .option('-a, --api-endpoint <url>', `Specify the api-endpoint url that should be used (default: ${defaultApiEndpoint})`)
53
53
  // .option('-C, --config-path <configPath>', `Specify the path to the optional locize config file (default: ${configInWorkingDirectory} or ${configInHome})`);
54
54
 
@@ -261,7 +261,7 @@ program
261
261
  .option('-n, --namespace <ns>', 'The namespace that should be targeted')
262
262
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
263
263
  .option('-k, --api-key <apiKey>', 'The api-key that should be used')
264
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
264
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
265
265
  .option('-s, --skip-empty <true|false>', 'Skips to download empty files (default: true)', 'true')
266
266
  .option('-P, --language-folder-prefix <prefix>', 'This will be added as a local folder name prefix in front of the language.', '')
267
267
  .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}}`)
@@ -410,7 +410,7 @@ program
410
410
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
411
411
  .option('-B, --backup-deleted-path <path>', 'Saves the segments that will be deleted in this path')
412
412
  .option('-A, --auto-create-path <true|false>', 'This will automatically make sure the --path is created. (default: true)', 'true')
413
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
413
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
414
414
  .option('-s, --skip-empty <true|false>', 'Skips to download empty files (default: false)', 'false')
415
415
  .option('-c, --clean <true|false>', 'Removes all local files by removing the whole folder (default: false)', 'false')
416
416
  .option('--cf, --clean-local-files <true|false>', 'Removes all local files without removing any folder (default: false)', 'false')
@@ -538,7 +538,7 @@ program
538
538
  .option('-i, --project-id <projectId>', 'The project-id that should be used')
539
539
  .option('-v, --ver <version>', 'Found namespaces will be matched to this version (default: latest)')
540
540
  .option('-p, --path <path>', `Specify the path that should be used (default: ${process.cwd()})`, process.cwd())
541
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
541
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
542
542
  .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}}`)
543
543
  .option('-P, --language-folder-prefix <prefix>', 'This will be added as a local folder name prefix in front of the language.', '')
544
544
  .option('-d, --dry <true|false>', 'Dry run (default: false)', 'false')
@@ -833,7 +833,7 @@ program
833
833
  .command('format [fileOrDirectory]')
834
834
  .alias('ft')
835
835
  .description('format local files')
836
- .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff12, xlf2, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
836
+ .option('-f, --format <json>', 'File format of namespaces (default: json; [nested, flat, xliff2, xliff21, xliff22, xliff12, xlf2, xlf21, xlf22, xlf12, android, yaml, yaml-rails, yaml-rails-ns, yaml-nested, yml, yml-rails, yml-nested, csv, xlsx, po, strings, resx, fluent, tmx, laravel, properties, xcstrings])', 'json')
837
837
  .option('-l, --reference-language <lng>', 'Some format conversions need to know the reference language.', 'en')
838
838
  .option('-d, --dry <true|false>', 'Dry run (default: false)', 'false')
839
839
  .action((fileOrDirectory, options) => {
@@ -141,19 +141,17 @@ const convertToDesiredFormat = async (
141
141
  });
142
142
  return stringsFile.compile(data)
143
143
  }
144
- if (
145
- opt.format === 'xliff2' ||
146
- opt.format === 'xliff12' ||
147
- opt.format === 'xlf2' ||
148
- opt.format === 'xlf12'
149
- ) {
150
- const fn =
151
- opt.format === 'xliff12' || opt.format === 'xlf12'
152
- ? xliff.createxliff12
153
- : xliff.createxliff;
144
+ if (['xliff2', 'xliff21', 'xliff22', 'xliff12', 'xlf2', 'xlf21', 'xlf22', 'xlf12'].indexOf(opt.format) > -1) {
154
145
  const refNs = await opt.getNamespace(opt, opt.referenceLanguage, namespace);
155
146
  const prepared = prepareExport(refNs, flatten(data));
156
- return await fn(opt.referenceLanguage, lng, prepared.ref, prepared.trg, namespace)
147
+ const js = await xliff.createjs(opt.referenceLanguage, lng, prepared.ref, prepared.trg, namespace);
148
+ if (opt.format === 'xliff12' || opt.format === 'xlf12') {
149
+ return await xliff.jsToXliff12(js, { inlineAsString: true })
150
+ }
151
+ let targetXliffVersion; // default 2.0
152
+ if (opt.format === 'xliff21' || opt.format === 'xlf21') targetXliffVersion = '2.1';
153
+ if (opt.format === 'xliff22' || opt.format === 'xlf22') targetXliffVersion = '2.2';
154
+ return await xliff.js2xliff(js, { targetXliffVersion, inlineAsString: true })
157
155
  }
158
156
  if (opt.format === 'resx') {
159
157
  return await resx.js2resx(flatten(data))
@@ -114,17 +114,13 @@ const convertToFlatFormat = async (opt, data, lng) => {
114
114
  // CRLF => LF
115
115
  return stringsFile.parse(data.toString().replace(/\r\n/g, '\n'), false)
116
116
  }
117
- if (
118
- opt.format === 'xliff2' ||
119
- opt.format === 'xliff12' ||
120
- opt.format === 'xlf2' ||
121
- opt.format === 'xlf12'
122
- ) {
117
+ if (['xliff2', 'xliff21', 'xliff22', 'xliff12', 'xlf2', 'xlf21', 'xlf22', 'xlf12'].indexOf(opt.format) > -1) {
118
+ // xliff2js parses 2.0, 2.1 and 2.2
123
119
  const fn =
124
120
  opt.format === 'xliff12' || opt.format === 'xlf12'
125
121
  ? xliff.xliff12ToJs
126
122
  : xliff.xliff2js;
127
- const res = await fn(data.toString());
123
+ const res = await fn(data.toString(), { inlineAsString: true });
128
124
  res.resources = res.resources || {};
129
125
  const ns = Object.keys(res.resources)[0];
130
126
  const orgRes = res.resources[ns] || res.resources;
@@ -8,8 +8,8 @@ const fileExtensionsMap = {
8
8
  '.yaml': ['yaml', 'yaml-rails', 'yaml-rails-ns', 'yaml-nested'],
9
9
  '.yml': ['yml', 'yml-rails', 'yml-rails-ns', 'yml-nested'],
10
10
  '.xlsx': ['xlsx'],
11
- '.xliff': ['xliff2', 'xliff12'],
12
- '.xlf': ['xlf2', 'xlf12'],
11
+ '.xliff': ['xliff2', 'xliff21', 'xliff22', 'xliff12'],
12
+ '.xlf': ['xlf2', 'xlf21', 'xlf22', 'xlf12'],
13
13
  '.ftl': ['fluent'],
14
14
  '.tmx': ['tmx'],
15
15
  '.php': ['laravel'],
@@ -41,7 +41,7 @@ async function request (url, options) {
41
41
  }
42
42
 
43
43
  options.headers = options.headers || {};
44
- options.headers['User-Agent'] = `locize-cli/v12.3.1 (node/${process.version}; ${process.platform} ${process.arch})`; // This string is replaced with the actual version at build time by rollup
44
+ options.headers['User-Agent'] = `locize-cli/v12.4.0 (node/${process.version}; ${process.platform} ${process.arch})`; // This string is replaced with the actual version at build time by rollup
45
45
  options.headers['X-User-Agent'] = options.headers['User-Agent'];
46
46
  if (options.body || options.method !== 'get') options.headers['Content-Type'] = 'application/json';
47
47
  if (options.body) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locize-cli",
3
- "version": "12.3.1",
3
+ "version": "12.4.0",
4
4
  "description": "locize cli to import locales",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -32,10 +32,10 @@
32
32
  "commander": "14.0.3",
33
33
  "diff": "8.0.4",
34
34
  "dotenv": "17.4.2",
35
- "fast-csv": "5.0.5",
35
+ "fast-csv": "5.0.7",
36
36
  "flat": "5.0.2",
37
37
  "fluent_conv": "3.3.0",
38
- "gettext-converter": "1.3.1",
38
+ "gettext-converter": "1.3.3",
39
39
  "https-proxy-agent": "7.0.6",
40
40
  "ini": "6.0.0",
41
41
  "laravelphp": "2.0.4",
@@ -46,20 +46,20 @@
46
46
  "rimraf": "6.1.3",
47
47
  "strings-file": "0.0.5",
48
48
  "tmexchange": "2.0.6",
49
- "xliff": "6.3.0",
49
+ "xliff": "6.4.0",
50
50
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
51
- "yaml": "2.8.3"
51
+ "yaml": "2.9.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@rollup/plugin-replace": "6.0.3",
55
- "@rollup/plugin-terser": "0.4.4",
56
- "@yao-pkg/pkg": "6.14.2",
55
+ "@rollup/plugin-terser": "1.0.0",
56
+ "@yao-pkg/pkg": "6.21.0",
57
57
  "eslint": "9.39.2",
58
58
  "eslint-plugin-import": "2.32.0",
59
- "gh-release": "7.0.2",
59
+ "gh-release": "8.1.0",
60
60
  "neostandard": "0.13.0",
61
- "rollup": "4.60.1",
62
- "vitest": "4.1.4"
61
+ "rollup": "4.62.2",
62
+ "vitest": "4.1.10"
63
63
  },
64
64
  "scripts": {
65
65
  "lint": "eslint .",
@@ -67,10 +67,10 @@
67
67
  "test:watch": "vitest",
68
68
  "test": "npm run lint && vitest run",
69
69
  "pkg": "mkdir -p ./bins && pkg ./dist/cjs/cli.js --output ./bins/locize --targets node24-linux-x64,node24-macos-x64,node24-win-x64,node24-alpine-x64",
70
- "release": "gh-release --assets ./bins/locize-linux,./bins/locize-macos,./bins/locize-win.exe,./bins/locize-alpine",
70
+ "release": "GH_RELEASE_GITHUB_API_TOKEN=$(gh auth token) gh-release --assets ./bins/locize-linux,./bins/locize-macos,./bins/locize-win.exe,./bins/locize-alpine",
71
71
  "preversion": "npm run test",
72
72
  "version": "npm run build && npm run pkg",
73
- "postversion": "git push && npm run release"
73
+ "postversion": "git push --follow-tags && npm run release"
74
74
  },
75
75
  "keywords": [
76
76
  "cli",