locize-cli 11.0.0 → 12.0.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.
Files changed (108) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +1 -1
  3. package/README.md +1 -0
  4. package/dist/cjs/add.js +90 -0
  5. package/{bin/locize → dist/cjs/cli.js} +390 -670
  6. package/dist/cjs/combineSubkeyPreprocessor.js +155 -0
  7. package/dist/cjs/convertToDesiredFormat.js +205 -0
  8. package/dist/cjs/convertToFlatFormat.js +231 -0
  9. package/dist/cjs/copyVersion.js +60 -0
  10. package/dist/cjs/createBranch.js +59 -0
  11. package/dist/cjs/deleteBranch.js +89 -0
  12. package/dist/cjs/deleteNamespace.js +37 -0
  13. package/dist/cjs/download.js +376 -0
  14. package/dist/cjs/filterNamespaces.js +13 -0
  15. package/dist/cjs/format.js +156 -0
  16. package/dist/cjs/formats.js +33 -0
  17. package/dist/cjs/get.js +66 -0
  18. package/dist/cjs/getBranches.js +37 -0
  19. package/dist/cjs/getJob.js +37 -0
  20. package/dist/cjs/getProjectStats.js +37 -0
  21. package/dist/cjs/getRemoteLanguages.js +38 -0
  22. package/dist/cjs/getRemoteNamespace.js +125 -0
  23. package/dist/cjs/index.js +37 -0
  24. package/dist/cjs/isValidUuid.js +6 -0
  25. package/dist/cjs/lngs.js +215 -0
  26. package/dist/cjs/mapLimit.js +22 -0
  27. package/dist/cjs/mergeBranch.js +80 -0
  28. package/dist/cjs/migrate.js +239 -0
  29. package/dist/cjs/missing.js +162 -0
  30. package/dist/cjs/package.json +5 -0
  31. package/{parseLocalLanguage.js → dist/cjs/parseLocalLanguage.js} +135 -142
  32. package/dist/cjs/parseLocalLanguages.js +18 -0
  33. package/dist/cjs/parseLocalReference.js +11 -0
  34. package/dist/cjs/publishVersion.js +42 -0
  35. package/dist/cjs/removeUndefinedFromArrays.js +19 -0
  36. package/dist/cjs/removeVersion.js +42 -0
  37. package/dist/cjs/request.js +66 -0
  38. package/dist/cjs/shouldUnflatten.js +21 -0
  39. package/dist/cjs/sortFlatResources.js +13 -0
  40. package/dist/cjs/sync.js +772 -0
  41. package/dist/cjs/unflatten.js +81 -0
  42. package/dist/esm/add.js +88 -0
  43. package/dist/esm/cli.js +1020 -0
  44. package/{combineSubkeyPreprocessor.js → dist/esm/combineSubkeyPreprocessor.js} +70 -73
  45. package/dist/esm/convertToDesiredFormat.js +203 -0
  46. package/dist/esm/convertToFlatFormat.js +229 -0
  47. package/dist/esm/copyVersion.js +58 -0
  48. package/dist/esm/createBranch.js +57 -0
  49. package/dist/esm/deleteBranch.js +87 -0
  50. package/dist/esm/deleteNamespace.js +35 -0
  51. package/dist/esm/download.js +374 -0
  52. package/{filterNamespaces.js → dist/esm/filterNamespaces.js} +4 -4
  53. package/dist/esm/format.js +154 -0
  54. package/{formats.js → dist/esm/formats.js} +7 -11
  55. package/dist/esm/get.js +64 -0
  56. package/dist/esm/getBranches.js +35 -0
  57. package/dist/esm/getJob.js +35 -0
  58. package/dist/esm/getProjectStats.js +35 -0
  59. package/dist/esm/getRemoteLanguages.js +36 -0
  60. package/dist/esm/getRemoteNamespace.js +123 -0
  61. package/dist/esm/index.js +16 -0
  62. package/dist/esm/isValidUuid.js +4 -0
  63. package/dist/esm/lngs.js +213 -0
  64. package/dist/esm/mapLimit.js +20 -0
  65. package/dist/esm/mergeBranch.js +78 -0
  66. package/dist/esm/migrate.js +237 -0
  67. package/dist/esm/missing.js +160 -0
  68. package/dist/esm/parseLocalLanguage.js +194 -0
  69. package/dist/esm/parseLocalLanguages.js +16 -0
  70. package/dist/esm/parseLocalReference.js +9 -0
  71. package/dist/esm/publishVersion.js +40 -0
  72. package/{removeUndefinedFromArrays.js → dist/esm/removeUndefinedFromArrays.js} +5 -5
  73. package/dist/esm/removeVersion.js +40 -0
  74. package/dist/esm/request.js +64 -0
  75. package/{shouldUnflatten.js → dist/esm/shouldUnflatten.js} +7 -7
  76. package/dist/esm/sortFlatResources.js +11 -0
  77. package/dist/esm/sync.js +770 -0
  78. package/{unflatten.js → dist/esm/unflatten.js} +36 -34
  79. package/package.json +39 -18
  80. package/rollup.config.js +57 -0
  81. package/add.js +0 -105
  82. package/convertToDesiredFormat.js +0 -268
  83. package/convertToFlatFormat.js +0 -322
  84. package/copyVersion.js +0 -69
  85. package/createBranch.js +0 -61
  86. package/deleteBranch.js +0 -97
  87. package/deleteNamespace.js +0 -39
  88. package/download.js +0 -516
  89. package/format.js +0 -206
  90. package/get.js +0 -81
  91. package/getBranches.js +0 -40
  92. package/getJob.js +0 -40
  93. package/getProjectStats.js +0 -40
  94. package/getRemoteLanguages.js +0 -40
  95. package/getRemoteNamespace.js +0 -122
  96. package/index.js +0 -9
  97. package/isValidUuid.js +0 -2
  98. package/lngs.json +0 -211
  99. package/mergeBranch.js +0 -102
  100. package/migrate.js +0 -314
  101. package/missing.js +0 -169
  102. package/parseLocalLanguages.js +0 -22
  103. package/parseLocalReference.js +0 -10
  104. package/publishVersion.js +0 -64
  105. package/removeVersion.js +0 -64
  106. package/request.js +0 -64
  107. package/sortFlatResources.js +0 -9
  108. package/sync.js +0 -786
@@ -1,77 +1,79 @@
1
- module.exports = (data, testNatural) => {
2
- const result = {}
3
- const shouldConvertArray = {}
1
+ const unflatten = (data, testNatural) => {
2
+ const result = {};
3
+ const shouldConvertArray = {};
4
4
  for (const i in data) {
5
- let keys = []
5
+ let keys = [];
6
6
  if (testNatural && /( |,|\?)/.test(i)) {
7
- keys = [i]
7
+ keys = [i];
8
8
  } else {
9
- keys = i.split('.')
9
+ keys = i.split('.');
10
10
  }
11
11
  keys.reduce((r, e, j) => {
12
- const isNumber = !isNaN(Number(keys[j + 1]))
13
- const hasLeadingZero = isNumber && keys[j + 1].length > 1 && keys[j + 1][0] === '0'
14
- const tooHighNumberToBeAnArrayIndex = isNumber && Number(keys[j + 1]) > 1000
12
+ const isNumber = !isNaN(Number(keys[j + 1]));
13
+ const hasLeadingZero = isNumber && keys[j + 1].length > 1 && keys[j + 1][0] === '0';
14
+ const tooHighNumberToBeAnArrayIndex = isNumber && Number(keys[j + 1]) > 1000;
15
15
  // if assumed to be an array, but now see a key wih non number value => transform to an object
16
16
  if (Array.isArray(r[e]) && (!isNumber || hasLeadingZero || tooHighNumberToBeAnArrayIndex)) {
17
17
  r[e] = r[e].reduce((mem, item, ind) => {
18
- mem[ind] = item
18
+ mem[ind] = item;
19
19
  return mem
20
- }, {})
20
+ }, {});
21
21
  }
22
22
  if (Array.isArray(r[e]) && r[e].length > 50) {
23
- const base = i.substring(0, i.indexOf(e) + e.length)
23
+ const base = i.substring(0, i.indexOf(e) + e.length);
24
24
  if (Object.values(r[e]).length < (r[e].length / 2)) {
25
- shouldConvertArray[base] = true
25
+ shouldConvertArray[base] = true;
26
26
  } else if (shouldConvertArray[base]) {
27
- delete shouldConvertArray[base]
27
+ delete shouldConvertArray[base];
28
28
  }
29
29
  }
30
30
  if (typeof r === 'string') {
31
31
  if (e === '' && keys.length > 2) {
32
- const lastPart = keys[keys.length - 2] + '.'
33
- const firstParts = keys.slice(0, keys.length - 2)
34
- let obj
32
+ const lastPart = keys[keys.length - 2] + '.';
33
+ const firstParts = keys.slice(0, keys.length - 2);
34
+ let obj;
35
35
  try {
36
- obj = firstParts.reduce((acc, p) => acc[p], result)
36
+ obj = firstParts.reduce((acc, p) => acc[p], result);
37
37
  } catch (err) {
38
38
  if (firstParts.indexOf('') < 0) throw err
39
39
 
40
- let navRes = result
40
+ let navRes = result;
41
41
  for (let ind = 0; ind < firstParts.length; ind++) {
42
- const p = firstParts[ind]
42
+ const p = firstParts[ind];
43
43
  if (typeof navRes[p] === 'object') {
44
- navRes = navRes[p]
44
+ navRes = navRes[p];
45
45
  } else {
46
- const rest = firstParts.slice(ind).map((c) => (c === '' ? '.' : c)).join('.')
47
- navRes[rest] = data[i]
46
+ const rest = firstParts.slice(ind).map((c) => (c === '' ? '.' : c)).join('.');
47
+ navRes[rest] = data[i];
48
48
  break
49
49
  }
50
50
  }
51
51
  }
52
52
  if (obj && typeof obj !== 'string' && obj[lastPart] === undefined) {
53
- obj[lastPart] = data[i]
53
+ obj[lastPart] = data[i];
54
54
  }
55
55
  }
56
56
  return r
57
57
  }
58
58
  return r[e] || (r[e] = (!isNumber || hasLeadingZero || tooHighNumberToBeAnArrayIndex) ? (keys.length - 1 === j ? data[i] : {}) : [])
59
- }, result)
59
+ }, result);
60
60
  }
61
- const arrsToConvert = Object.keys(shouldConvertArray)
61
+ const arrsToConvert = Object.keys(shouldConvertArray);
62
62
  arrsToConvert.forEach((arrToConvert) => {
63
- const parts = arrToConvert.split('.')
64
- let pr = result
63
+ const parts = arrToConvert.split('.');
64
+ let pr = result;
65
65
  parts.forEach((part, ind) => {
66
66
  if (ind === parts.length - 1 && Array.isArray(pr[part])) {
67
67
  pr[part] = pr[part].reduce((mem, item, ind) => {
68
- mem[ind] = item
68
+ mem[ind] = item;
69
69
  return mem
70
- }, {})
70
+ }, {});
71
71
  } else {
72
- pr = pr[part]
72
+ pr = pr[part];
73
73
  }
74
- })
75
- })
74
+ });
75
+ });
76
76
  return result
77
- }
77
+ };
78
+
79
+ export { unflatten as default };
package/package.json CHANGED
@@ -1,52 +1,73 @@
1
1
  {
2
2
  "name": "locize-cli",
3
- "version": "11.0.0",
3
+ "version": "12.0.0",
4
4
  "description": "locize cli to import locales",
5
- "main": "index.js",
5
+ "type": "module",
6
+ "main": "./dist/cjs/index.js",
7
+ "module": "./dist/esm/index.js",
6
8
  "bin": {
7
- "locize": "./bin/locize"
9
+ "locize": "./dist/esm/cli.js"
10
+ },
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
14
+ "exports": {
15
+ "./package.json": "./package.json",
16
+ ".": {
17
+ "require": "./dist/cjs/index.js",
18
+ "default": "./dist/esm/index.js"
19
+ },
20
+ "./cjs": {
21
+ "default": "./dist/cjs/index.js"
22
+ },
23
+ "./esm": {
24
+ "default": "./dist/esm/index.js"
25
+ }
8
26
  },
9
27
  "dependencies": {
10
28
  "@js.properties/properties": "0.5.4",
11
29
  "android-string-resource": "2.3.10",
12
- "async": "3.2.6",
13
30
  "cacheable-lookup": "6.1.0",
14
31
  "colors": "1.4.0",
15
- "commander": "9.5.0",
16
- "csvjson": "5.1.0",
17
- "diff": "7.0.0",
18
- "dotenv": "16.5.0",
32
+ "commander": "14.0.2",
33
+ "diff": "8.0.2",
34
+ "dotenv": "17.2.3",
35
+ "fast-csv": "5.0.5",
19
36
  "flat": "5.0.2",
20
37
  "fluent_conv": "3.3.0",
21
38
  "gettext-converter": "1.3.0",
22
39
  "https-proxy-agent": "7.0.6",
23
- "ini": "4.1.3",
40
+ "ini": "6.0.0",
24
41
  "laravelphp": "2.0.4",
25
42
  "locize-xcstrings": "2.0.0",
26
43
  "lodash.clonedeep": "4.5.0",
27
44
  "mkdirp": "3.0.1",
28
- "node-fetch": "2.7.0",
29
45
  "resx": "2.0.4",
30
- "rimraf": "4.4.1",
46
+ "rimraf": "6.1.2",
31
47
  "strings-file": "0.0.5",
32
- "tmexchange": "2.0.5",
48
+ "tmexchange": "2.0.6",
33
49
  "xliff": "6.2.2",
34
50
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
35
- "yaml": "2.8.0"
51
+ "yaml": "2.8.2"
36
52
  },
37
53
  "devDependencies": {
38
- "@yao-pkg/pkg": "6.4.0",
39
- "eslint": "9.39.1",
54
+ "@rollup/plugin-replace": "6.0.3",
55
+ "@rollup/plugin-terser": "0.4.4",
56
+ "@yao-pkg/pkg": "6.11.0",
57
+ "eslint": "9.39.2",
40
58
  "eslint-plugin-import": "2.32.0",
59
+ "gh-release": "7.0.2",
41
60
  "neostandard": "0.12.2",
42
- "gh-release": "7.0.2"
61
+ "rollup": "4.54.0"
43
62
  },
44
63
  "scripts": {
45
64
  "lint": "eslint .",
65
+ "build": "rm -rf dist && rollup -c",
46
66
  "test": "npm run lint",
47
- "pkg": "mkdir -p ./bins && pkg ./bin/locize --out-path ./bins --targets node20-linux-x64,node20-macos-x64,node20-win-x64,node20-alpine-x64",
67
+ "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",
48
68
  "release": "gh-release --assets ./bins/locize-linux,./bins/locize-macos,./bins/locize-win.exe,./bins/locize-alpine",
49
- "version": "npm run pkg",
69
+ "preversion": "npm run test",
70
+ "version": "npm run build && npm run pkg",
50
71
  "postversion": "git push && npm run release"
51
72
  },
52
73
  "keywords": [
@@ -0,0 +1,57 @@
1
+ import { readFileSync, writeFileSync, chmodSync } from 'node:fs'
2
+ import replace from '@rollup/plugin-replace'
3
+ // import terser from '@rollup/plugin-terser'
4
+
5
+ const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf-8'))
6
+
7
+ export default {
8
+ input: {
9
+ index: 'src/index.js',
10
+ cli: 'src/cli.js'
11
+ },
12
+ output: [
13
+ {
14
+ dir: 'dist/cjs',
15
+ preserveModules: true,
16
+ // file: pkg.main,
17
+ format: 'cjs'
18
+ },
19
+ {
20
+ dir: 'dist/esm',
21
+ preserveModules: true,
22
+ // file: pkg.module,
23
+ format: 'es' // the preferred format
24
+ },
25
+ // {
26
+ // file: pkg.browser,
27
+ // format: 'iife',
28
+ // name: pkg.globalName // the global which can be used in a browser
29
+ // }
30
+ ],
31
+ external: [
32
+ ...Object.keys(pkg.dependencies || {})
33
+ ],
34
+ plugins: [
35
+ replace({
36
+ __packageName: pkg.name,
37
+ __packageVersion__: pkg.version,
38
+ preventAssignment: true
39
+ }),
40
+ // terser(), // minifies generated bundles
41
+ {
42
+ name: 'post-build-steps',
43
+ writeBundle () {
44
+ // Make CLI files executable
45
+ try { chmodSync('dist/esm/cli.js', 0o755) } catch {}
46
+ try { chmodSync('dist/cjs/cli.js', 0o755) } catch {}
47
+ // Write CJS package.json with name, version, and type
48
+ const cjsPkg = {
49
+ name: pkg.name,
50
+ version: pkg.version,
51
+ type: 'commonjs'
52
+ }
53
+ writeFileSync('dist/cjs/package.json', JSON.stringify(cjsPkg, null, 2) + '\n')
54
+ }
55
+ }
56
+ ]
57
+ }
package/add.js DELETED
@@ -1,105 +0,0 @@
1
- const colors = require('colors')
2
- const flatten = require('flat')
3
- const async = require('async')
4
- const getRemoteLanguages = require('./getRemoteLanguages')
5
- const request = require('./request')
6
-
7
- const _add = (opt, cb) => {
8
- const url = `${opt.apiEndpoint}/update/{{projectId}}/{{version}}/{{lng}}/{{ns}}`
9
- .replace('{{projectId}}', opt.projectId)
10
- .replace('{{ver}}', opt.version)
11
- .replace('{{version}}', opt.version)
12
- .replace('{{language}}', opt.language)
13
- .replace('{{lng}}', opt.language)
14
- .replace('{{ns}}', opt.namespace)
15
- .replace('{{namespace}}', opt.namespace)
16
-
17
- if (!cb) {
18
- if (!opt.data && (opt.value === undefined || opt.value === null)) {
19
- console.log(colors.yellow(`removing ${opt.key} from ${opt.version}/${opt.language}/${opt.namespace}...`))
20
- } else {
21
- console.log(colors.yellow(`adding ${opt.key} to ${opt.version}/${opt.language}/${opt.namespace}...`))
22
- }
23
- }
24
-
25
- const data = flatten(opt.data || {})
26
- if (!opt.data) {
27
- data[opt.key] = opt.value || null // null will remove the key
28
- }
29
-
30
- request(url, {
31
- method: 'post',
32
- headers: {
33
- Authorization: opt.apiKey
34
- },
35
- body: data
36
- }, (err, res, obj) => {
37
- if (err) {
38
- if (!opt.data && (opt.value === undefined || opt.value === null)) {
39
- console.log(colors.red(`remove failed for ${opt.key} from ${opt.version}/${opt.language}/${opt.namespace}...`))
40
- } else {
41
- console.log(colors.red(`add failed for ${opt.key} to ${opt.version}/${opt.language}/${opt.namespace}...`))
42
- }
43
- if (!cb) { console.error(colors.red(err.message)); process.exit(1) }
44
- if (cb) cb(err)
45
- return
46
- }
47
- if (res.status >= 300 && res.status !== 412) {
48
- if (!opt.data && (opt.value === undefined || opt.value === null)) {
49
- console.log(colors.red(`remove failed for ${opt.key} from ${opt.version}/${opt.language}/${opt.namespace}...`))
50
- } else {
51
- console.log(colors.red(`add failed for ${opt.key} to ${opt.version}/${opt.language}/${opt.namespace}...`))
52
- }
53
- if (obj && (obj.errorMessage || obj.message)) {
54
- if (!cb) { console.error(colors.red((obj.errorMessage || obj.message))); process.exit(1) }
55
- if (cb) cb(new Error((obj.errorMessage || obj.message)))
56
- return
57
- } else {
58
- if (!cb) { console.error(colors.red(res.statusText + ' (' + res.status + ')')); process.exit(1) }
59
- if (cb) cb(new Error(res.statusText + ' (' + res.status + ')'))
60
- return
61
- }
62
- }
63
- if (!cb) {
64
- if (!opt.data && (opt.value === undefined || opt.value === null)) {
65
- console.log(colors.green(`removed ${opt.key} from ${opt.version}/${opt.language}/${opt.namespace}...`))
66
- } else {
67
- console.log(colors.green(`added ${opt.key} to ${opt.version}/${opt.language}/${opt.namespace}...`))
68
- }
69
- }
70
- if (cb) cb(null)
71
- })
72
- }
73
-
74
- const add = (opt, cb) => {
75
- if (opt.language) return _add(opt, cb)
76
-
77
- getRemoteLanguages(opt, (err, lngs) => {
78
- if (err) {
79
- if (!cb) { console.error(colors.red(err.message)); process.exit(1) }
80
- if (cb) cb(err)
81
- return
82
- }
83
-
84
- async.forEachSeries(lngs, (lng, clb) => {
85
- opt.language = lng
86
- _add(opt, clb)
87
- }, (err) => {
88
- if (err) {
89
- if (!cb) { console.error(colors.red(err.message)); process.exit(1) }
90
- if (cb) cb(err)
91
- return
92
- }
93
- if (!cb) {
94
- if (!opt.data && (opt.value === undefined || opt.value === null)) {
95
- console.log(colors.green(`removed ${opt.namespace}/${opt.key} (${opt.version}) from all languages...`))
96
- } else {
97
- console.log(colors.green(`added ${opt.namespace}/${opt.key} (${opt.version}) in all languages...`))
98
- }
99
- }
100
- if (cb) cb(null)
101
- })
102
- })
103
- }
104
-
105
- module.exports = add
@@ -1,268 +0,0 @@
1
- const flatten = require('flat')
2
- const i18next2po = require('gettext-converter/cjs/i18next2po')
3
- const csvjson = require('csvjson')
4
- const xlsx = require('xlsx')
5
- const yaml = require('yaml')
6
- const js2asr = require('android-string-resource/cjs/js2asr')
7
- const stringsFile = require('strings-file')
8
- const createxliff = require('xliff/cjs/createxliff')
9
- const createxliff12 = require('xliff/cjs/createxliff12')
10
- const js2resx = require('resx/cjs/js2resx')
11
- const js2ftl = require('fluent_conv/cjs/js2ftl')
12
- const js2tmx = require('tmexchange/cjs/js2tmx')
13
- const js2laravel = require('laravelphp/cjs/js2laravel')
14
- const javaProperties = require('@js.properties/properties')
15
- const unflatten = require('./unflatten')
16
- const getRemoteNamespace = require('./getRemoteNamespace')
17
- const removeUndefinedFromArrays = require('./removeUndefinedFromArrays')
18
- const shouldUnflatten = require('./shouldUnflatten')
19
- const prepareCombinedExport = require('./combineSubkeyPreprocessor').prepareExport
20
-
21
- const convertToDesiredFormat = (
22
- opt,
23
- namespace,
24
- lng,
25
- data,
26
- lastModified,
27
- cb
28
- ) => {
29
- opt.getNamespace = opt.getNamespace || getRemoteNamespace
30
- const isEmpty = !data || Object.keys(data).length === 0
31
- try {
32
- if (opt.format === 'json') {
33
- try {
34
- data = unflatten(data, true)
35
- } catch (err) {}
36
- cb(null, JSON.stringify(data, null, 2))
37
- return
38
- }
39
- if (opt.format === 'nested') {
40
- try {
41
- data = unflatten(data)
42
- } catch (err) {}
43
- cb(null, JSON.stringify(data, null, 2))
44
- return
45
- }
46
- if (opt.format === 'flat') {
47
- cb(null, JSON.stringify(flatten(data), null, 2))
48
- return
49
- }
50
- if (opt.format === 'po' || opt.format === 'gettext') {
51
- const flatData = flatten(data)
52
-
53
- const gettextOpt = {
54
- project: 'locize',
55
- language: lng,
56
- potCreationDate: lastModified,
57
- poRevisionDate: lastModified,
58
- ctxSeparator: '_ is default but we set it to something that is never found!!!',
59
- persistMsgIdPlural: true
60
- }
61
- cb(null, i18next2po(lng, flatData, gettextOpt))
62
- return
63
- }
64
- if (opt.format === 'po_i18next' || opt.format === 'gettext_i18next') {
65
- const flatData = flatten(data)
66
- const compatibilityJSON = !!Object.keys(flatData).find((k) => /_(zero|one|two|few|many|other)/.test(k)) && 'v4'
67
- const gettextOpt = {
68
- project: 'locize',
69
- language: lng,
70
- potCreationDate: lastModified,
71
- poRevisionDate: lastModified,
72
- compatibilityJSON
73
- }
74
- cb(null, i18next2po(lng, flatData, gettextOpt))
75
- return
76
- }
77
- if (opt.format === 'csv') {
78
- opt.getNamespace(opt, opt.referenceLanguage, namespace, (err, refNs) => {
79
- if (err) return cb(err)
80
-
81
- const js2CsvData = Object.keys(flatten(data)).reduce((mem, k) => {
82
- const value = data[k] || ''
83
- const line = {
84
- // https://en.wikipedia.org/wiki/Delimiter-separated_values
85
- key: k.replace(/"/g, '""'),
86
- [opt.referenceLanguage]: refNs[k] || '',
87
- [lng]: value.replace(/"/g, '""')
88
- }
89
- line.key = line.key.replace(/\n/g, '\\NeWlInE\\')
90
- line[opt.referenceLanguage] = line[opt.referenceLanguage].replace(
91
- /\n/g,
92
- '\\NeWlInE\\'
93
- )
94
- line[lng] = line[lng].replace(/\n/g, '\\NeWlInE\\')
95
- mem.push(line)
96
-
97
- return mem
98
- }, [])
99
- const options = {
100
- delimiter: ',',
101
- wrap: true,
102
- headers: 'relative'
103
- // objectDenote: '.',
104
- // arrayDenote: '[]'
105
- }
106
- cb(
107
- null,
108
- `\ufeff${csvjson
109
- .toCSV(js2CsvData, options)
110
- .replace(/\\NeWlInE\\/g, '\n')}`
111
- )
112
- })
113
- return
114
- }
115
- if (opt.format === 'xlsx') {
116
- opt.getNamespace(opt, opt.referenceLanguage, namespace, (err, refNs) => {
117
- if (err) return cb(err)
118
-
119
- const js2XlsxData = Object.keys(flatten(data)).reduce((mem, k) => {
120
- const value = data[k] || ''
121
- const line = {
122
- key: k,
123
- [opt.referenceLanguage]: refNs[k] || '',
124
- [lng]: value
125
- }
126
- mem.push(line)
127
-
128
- return mem
129
- }, [])
130
-
131
- const worksheet = xlsx.utils.json_to_sheet(js2XlsxData)
132
- const workbook = xlsx.utils.book_new()
133
- let workSheetName = namespace
134
- if (workSheetName.length > 31) workSheetName = workSheetName.substring(0, 31)
135
- workbook.SheetNames.push(workSheetName)
136
- workbook.Sheets[workSheetName] = worksheet
137
-
138
- const wbout = xlsx.write(workbook, { type: 'buffer' })
139
-
140
- cb(null, wbout)
141
- })
142
- return
143
- }
144
- if (
145
- opt.format === 'yaml' ||
146
- opt.format === 'yml'
147
- ) {
148
- if (isEmpty) return cb(null, '')
149
- cb(null, yaml.stringify(flatten(data)))
150
- return
151
- }
152
- if (
153
- opt.format === 'yaml-nested' ||
154
- opt.format === 'yml-nested'
155
- ) {
156
- if (isEmpty) return cb(null, '')
157
- cb(null, yaml.stringify(shouldUnflatten(data) ? unflatten(data) : data))
158
- return
159
- }
160
- if (
161
- opt.format === 'yaml-rails' ||
162
- opt.format === 'yml-rails'
163
- ) {
164
- if (isEmpty) return cb(null, '')
165
- const newData = {}
166
- newData[lng] = shouldUnflatten(data) ? unflatten(data) : data
167
- cb(null, yaml.stringify(removeUndefinedFromArrays(newData)))
168
- return
169
- }
170
- if (
171
- opt.format === 'yaml-rails-ns' ||
172
- opt.format === 'yml-rails-ns'
173
- ) {
174
- if (isEmpty) return cb(null, '')
175
- const newDataNs = {}
176
- newDataNs[lng] = {}
177
- newDataNs[lng][namespace] = shouldUnflatten(data) ? unflatten(data) : data
178
- cb(null, yaml.stringify(removeUndefinedFromArrays(newDataNs)))
179
- return
180
- }
181
- if (opt.format === 'android') {
182
- js2asr(flatten(data), cb)
183
- return
184
- }
185
- if (opt.format === 'strings') {
186
- Object.keys(data).forEach((k) => {
187
- if (data[k] === null) delete data[k]
188
- })
189
- data = stringsFile.compile(data)
190
- cb(null, data)
191
- return
192
- }
193
- if (
194
- opt.format === 'xliff2' ||
195
- opt.format === 'xliff12' ||
196
- opt.format === 'xlf2' ||
197
- opt.format === 'xlf12'
198
- ) {
199
- const fn =
200
- opt.format === 'xliff12' || opt.format === 'xlf12'
201
- ? createxliff12
202
- : createxliff
203
- opt.getNamespace(opt, opt.referenceLanguage, namespace, (err, refNs) => {
204
- if (err) return cb(err)
205
-
206
- const prepared = prepareCombinedExport(refNs, flatten(data))
207
- fn(opt.referenceLanguage, lng, prepared.ref, prepared.trg, namespace, cb)
208
- })
209
- return
210
- }
211
- if (opt.format === 'resx') {
212
- js2resx(flatten(data), cb)
213
- return
214
- }
215
- if (opt.format === 'fluent') {
216
- Object.keys(data).forEach((k) => {
217
- if (!data[k] || data[k] === '') delete data[k]
218
- data[k] = data[k].replace(
219
- new RegExp(String.fromCharCode(160), 'g'),
220
- String.fromCharCode(32)
221
- )
222
- })
223
- js2ftl(unflatten(data), cb)
224
- return
225
- }
226
- if (opt.format === 'tmx') {
227
- opt.getNamespace(opt, opt.referenceLanguage, namespace, (err, refNs) => {
228
- if (err) return cb(err)
229
-
230
- const js = flatten(data)
231
- const js2TmxData = Object.keys(js).reduce(
232
- (mem, k) => {
233
- const refItem = refNs[k]
234
- if (!refItem) return mem
235
-
236
- const value = js[k] || ''
237
- mem.resources[namespace][k] = {}
238
- mem.resources[namespace][k][opt.referenceLanguage] = refItem
239
- mem.resources[namespace][k][lng] = value
240
-
241
- return mem
242
- },
243
- {
244
- resources: {
245
- [namespace]: {}
246
- },
247
- sourceLanguage: opt.referenceLanguage
248
- }
249
- )
250
- js2tmx(js2TmxData, cb)
251
- })
252
- return
253
- }
254
- if (opt.format === 'laravel') {
255
- js2laravel(unflatten(data), cb)
256
- return
257
- }
258
- if (opt.format === 'properties') {
259
- cb(null, javaProperties.stringifyFromProperties(data, { eol: '\n' }))
260
- return
261
- }
262
- cb(new Error(`${opt.format} is not a valid format!`))
263
- } catch (err) {
264
- cb(err)
265
- }
266
- }
267
-
268
- module.exports = convertToDesiredFormat