@formatjs/cli 5.0.7 → 5.0.8

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 (45) hide show
  1. package/BUILD +22 -0
  2. package/CHANGELOG.md +1098 -0
  3. package/LICENSE.md +0 -0
  4. package/README.md +0 -0
  5. package/integration-tests/BUILD +81 -0
  6. package/integration-tests/compile/__snapshots__/integration.test.ts.snap +1056 -0
  7. package/integration-tests/compile/glob/en.json +14 -0
  8. package/integration-tests/compile/glob/en2.json +14 -0
  9. package/integration-tests/compile/glob-conflict/en.json +14 -0
  10. package/integration-tests/compile/glob-conflict/en2.json +14 -0
  11. package/integration-tests/compile/integration.test.ts +213 -0
  12. package/integration-tests/compile/lang/empty.json +1 -0
  13. package/integration-tests/compile/lang/en-crowdin.json +14 -0
  14. package/integration-tests/compile/lang/en-format.json +14 -0
  15. package/integration-tests/compile/lang/en-lokalise.json +14 -0
  16. package/integration-tests/compile/lang/en-simple.json +5 -0
  17. package/integration-tests/compile/lang/en-smartling.json +24 -0
  18. package/integration-tests/compile/lang/en-transifex.json +14 -0
  19. package/integration-tests/compile/lang/en.json +22 -0
  20. package/integration-tests/compile/lang/malformed-messages.json +14 -0
  21. package/integration-tests/compile_folder/__snapshots__/integration.test.ts.snap +44 -0
  22. package/integration-tests/compile_folder/integration.test.ts +33 -0
  23. package/integration-tests/compile_folder/lang/empty.json +1 -0
  24. package/integration-tests/compile_folder/lang/en.json +14 -0
  25. package/integration-tests/compile_folder/lang/en2.json +14 -0
  26. package/integration-tests/extract/__snapshots__/integration.test.ts.snap +932 -0
  27. package/integration-tests/extract/defineMessages/actual.ignore.js +22 -0
  28. package/integration-tests/extract/defineMessages/actual.js +65 -0
  29. package/integration-tests/extract/defineMessages/bad.json +1 -0
  30. package/integration-tests/extract/duplicated/file1.tsx +10 -0
  31. package/integration-tests/extract/duplicated/file2.tsx +10 -0
  32. package/integration-tests/extract/integration.test.ts +240 -0
  33. package/integration-tests/extract/nonDuplicated/file1.tsx +14 -0
  34. package/integration-tests/extract/nonDuplicated/file2.tsx +14 -0
  35. package/integration-tests/extract/typescript/actual.ignore.tsx +21 -0
  36. package/integration-tests/extract/typescript/actual.tsx +104 -0
  37. package/integration-tests/extract/typescript/err.tsx +1 -0
  38. package/integration-tests/extract/typescript/pragma.tsx +77 -0
  39. package/integration-tests/extract-vue/__snapshots__/integration.test.ts.snap +17 -0
  40. package/integration-tests/extract-vue/comp.vue +22 -0
  41. package/integration-tests/extract-vue/integration.test.ts +14 -0
  42. package/integration-tests/formatter.js +18 -0
  43. package/integration-tests/package.json +5 -0
  44. package/package.json +3 -3
  45. package/bin/formatjs +0 -155104
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "1": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "3": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "1": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many cats}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,213 @@
1
+ import {exec as nodeExec} from 'child_process'
2
+ import {join, resolve} from 'path'
3
+ import _rimraf from 'rimraf'
4
+ import {promisify} from 'util'
5
+ const exec = promisify(nodeExec)
6
+ const BIN_PATH = require.resolve('@formatjs/cli/bin/formatjs')
7
+ const ARTIFACT_PATH = resolve(__dirname, 'test_artifacts')
8
+
9
+ test('basic case: help', async () => {
10
+ await expect(exec(`${BIN_PATH} compile --help`)).resolves.toMatchSnapshot()
11
+ }, 20000)
12
+
13
+ test('basic case: empty json', async () => {
14
+ await expect(
15
+ exec(`${BIN_PATH} compile ${join(__dirname, 'lang/empty.json')}`)
16
+ ).resolves.toMatchSnapshot()
17
+ }, 20000)
18
+
19
+ test('normal json', async () => {
20
+ await expect(
21
+ exec(`${BIN_PATH} compile ${join(__dirname, 'lang/en.json')}`)
22
+ ).resolves.toMatchSnapshot()
23
+ }, 20000)
24
+
25
+ test('xx-LS json', async () => {
26
+ await expect(
27
+ exec(
28
+ `${BIN_PATH} compile --ast --pseudo-locale xx-LS ${join(
29
+ __dirname,
30
+ 'lang/en.json'
31
+ )}`
32
+ )
33
+ ).resolves.toMatchSnapshot()
34
+ }, 20000)
35
+
36
+ test('xx-HA json', async () => {
37
+ await expect(
38
+ exec(
39
+ `${BIN_PATH} compile --ast --pseudo-locale xx-HA ${join(
40
+ __dirname,
41
+ 'lang/en.json'
42
+ )}`
43
+ )
44
+ ).resolves.toMatchSnapshot()
45
+ }, 20000)
46
+
47
+ test('xx-AC json', async () => {
48
+ await expect(
49
+ exec(
50
+ `${BIN_PATH} compile --ast --pseudo-locale xx-AC ${join(
51
+ __dirname,
52
+ 'lang/en.json'
53
+ )}`
54
+ )
55
+ ).resolves.toMatchSnapshot()
56
+ }, 20000)
57
+
58
+ test('en-XA json', async () => {
59
+ await expect(
60
+ exec(
61
+ `${BIN_PATH} compile --ast --pseudo-locale en-XA ${join(
62
+ __dirname,
63
+ 'lang/en.json'
64
+ )}`
65
+ )
66
+ ).resolves.toMatchSnapshot()
67
+ }, 20000)
68
+
69
+ test('en-XB json', async () => {
70
+ await expect(
71
+ exec(
72
+ `${BIN_PATH} compile --ast --pseudo-locale en-XB ${join(
73
+ __dirname,
74
+ 'lang/en.json'
75
+ )}`
76
+ )
77
+ ).resolves.toMatchSnapshot()
78
+ }, 20000)
79
+
80
+ test('normal json with formatter', async () => {
81
+ await expect(
82
+ exec(
83
+ `${BIN_PATH} compile ${join(
84
+ __dirname,
85
+ 'lang/en-format.json'
86
+ )} --format ${join(__dirname, '../formatter.js')}`
87
+ )
88
+ ).resolves.toMatchSnapshot()
89
+ }, 20000)
90
+
91
+ test('normal json with transifex', async () => {
92
+ await expect(
93
+ exec(
94
+ `${BIN_PATH} compile ${join(
95
+ __dirname,
96
+ 'lang/en-transifex.json'
97
+ )} --format transifex`
98
+ )
99
+ ).resolves.toMatchSnapshot()
100
+ }, 20000)
101
+
102
+ test('normal json with smartling', async () => {
103
+ await expect(
104
+ exec(
105
+ `${BIN_PATH} compile ${join(
106
+ __dirname,
107
+ 'lang/en-smartling.json'
108
+ )} --format smartling`
109
+ )
110
+ ).resolves.toMatchSnapshot()
111
+ }, 20000)
112
+
113
+ test('normal json with simple', async () => {
114
+ await expect(
115
+ exec(
116
+ `${BIN_PATH} compile ${join(
117
+ __dirname,
118
+ 'lang/en-simple.json'
119
+ )} --format simple`
120
+ )
121
+ ).resolves.toMatchSnapshot()
122
+ }, 20000)
123
+
124
+ test('normal json with lokalise', async () => {
125
+ await expect(
126
+ exec(
127
+ `${BIN_PATH} compile ${join(
128
+ __dirname,
129
+ 'lang/en-lokalise.json'
130
+ )} --format lokalise`
131
+ )
132
+ ).resolves.toMatchSnapshot()
133
+ }, 20000)
134
+
135
+ test('normal json with crowdin', async () => {
136
+ await expect(
137
+ exec(
138
+ `${BIN_PATH} compile ${join(
139
+ __dirname,
140
+ 'lang/en-crowdin.json'
141
+ )} --format crowdin`
142
+ )
143
+ ).resolves.toMatchSnapshot()
144
+ }, 20000)
145
+
146
+ test('malformed ICU message json', async () => {
147
+ await expect(
148
+ exec(
149
+ `${BIN_PATH} compile ${join(__dirname, 'lang/malformed-messages.json')}`
150
+ )
151
+ ).rejects.toThrowError('SyntaxError: EXPECT_ARGUMENT_CLOSING_BRACE')
152
+ }, 20000)
153
+
154
+ test('skipped malformed ICU message json', async () => {
155
+ await expect(
156
+ exec(
157
+ `${BIN_PATH} compile --skip-errors ${join(
158
+ __dirname,
159
+ 'lang/malformed-messages.json'
160
+ )}`
161
+ )
162
+ ).resolves.toMatchSnapshot({
163
+ stderr: expect.stringMatching(
164
+ /^\[@formatjs\/cli\] \[WARN\] Error validating message "my name is {name" with ID "a1dd2" in file .*\/packages\/cli\/integration-tests\/compile\/lang\/malformed-messages.json/
165
+ ),
166
+ } as Partial<any>)
167
+ }, 20000)
168
+
169
+ test('AST', async () => {
170
+ await expect(
171
+ exec(`${BIN_PATH} compile --ast ${join(__dirname, 'lang/en.json')}`)
172
+ ).resolves.toMatchSnapshot()
173
+ }, 20000)
174
+
175
+ test('out-file', async () => {
176
+ const outFilePath = join(ARTIFACT_PATH, 'en.json')
177
+ await expect(
178
+ exec(
179
+ `${BIN_PATH} compile ${join(
180
+ __dirname,
181
+ 'lang/en.json'
182
+ )} --out-file ${outFilePath}`
183
+ )
184
+ ).resolves.toMatchSnapshot()
185
+ expect(require(outFilePath)).toMatchSnapshot()
186
+ }, 20000)
187
+
188
+ test('out-file --ast', async () => {
189
+ const outFilePath = join(ARTIFACT_PATH, 'ast.json')
190
+ await expect(
191
+ exec(
192
+ `${BIN_PATH} compile --ast ${join(
193
+ __dirname,
194
+ 'lang/en.json'
195
+ )} --out-file ${outFilePath}`
196
+ )
197
+ ).resolves.toMatchSnapshot()
198
+ expect(require(outFilePath)).toMatchSnapshot()
199
+ }, 20000)
200
+
201
+ test('compile glob', async () => {
202
+ await expect(
203
+ exec(`${BIN_PATH} compile "${join(__dirname, 'glob/*.json')}"`)
204
+ ).resolves.toMatchSnapshot()
205
+ })
206
+
207
+ test('compile glob with conflict', async () => {
208
+ await expect(
209
+ exec(`${BIN_PATH} compile "${join(__dirname, 'glob-conflict/*.json')}"`)
210
+ ).rejects.toThrowError(
211
+ 'Conflicting ID "a1d12" with different translation found in these 2 files'
212
+ )
213
+ })
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "message": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "message": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "message": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "string": "a message",
4
+ "comment": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "string": "my name is {name}",
8
+ "comment": "foo"
9
+ },
10
+ "a1d12": {
11
+ "string": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "comment": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "translation": "a message",
4
+ "notes": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "translation": "my name is {name}",
8
+ "notes": "foo"
9
+ },
10
+ "a1d12": {
11
+ "translation": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "notes": "foo"
13
+ }
14
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "ashd2": "a message",
3
+ "a1dd2": "my name is {name}",
4
+ "a1d12": "I have {count, plural, one{a dog} other{many dogs}}"
5
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "smartling": {
3
+ "translate_paths": [
4
+ {
5
+ "path": "*/message",
6
+ "key": "{*}/message",
7
+ "instruction": "*/description"
8
+ }
9
+ ],
10
+ "variants_enabled": true
11
+ },
12
+ "ashd2": {
13
+ "message": "a message",
14
+ "description": "foo"
15
+ },
16
+ "a1dd2": {
17
+ "message": "my name is {name}",
18
+ "description": "foo"
19
+ },
20
+ "a1d12": {
21
+ "message": "I have {count, plural, one{a dog} other{many dogs}}",
22
+ "description": "foo"
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "string": "a message",
4
+ "comment": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "string": "my name is {name}",
8
+ "comment": "foo"
9
+ },
10
+ "a1d12": {
11
+ "string": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "comment": "foo"
13
+ }
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "ashd2": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ },
14
+ "a1d13": {
15
+ "defaultMessage": "I have {count, plural, one{<b>a dog</b>} other{many dogs}}",
16
+ "description": "foo"
17
+ },
18
+ "a1d14": {
19
+ "defaultMessage": "I have {count, plural, one{<b>a <i>dog</i></b>} other{many dogs}}",
20
+ "description": "foo"
21
+ }
22
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "defaultMessage": "my name is {name",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,44 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`basic case 1`] = `
4
+ Array [
5
+ Object {},
6
+ Object {
7
+ "a1d12": "I have {count, plural, one{a dog} other{many dogs}}",
8
+ "a1dd2": "my name is {name}",
9
+ "ashd2": "a message",
10
+ },
11
+ Object {
12
+ "1": "another message",
13
+ "2": "my name is {foo}",
14
+ "3": "I have {count, plural, one{a cat} other{many cats}}",
15
+ },
16
+ ]
17
+ `;
18
+
19
+ exports[`basic case: help 1`] = `
20
+ Object {
21
+ "stderr": "",
22
+ "stdout": "Usage: formatjs compile-folder [options] <folder> <outFolder>
23
+
24
+ Batch compile all extracted translation JSON files in <folder> to <outFolder> containing
25
+ react-intl consumable JSON. We also verify that the messages are
26
+ valid ICU and not malformed.
27
+
28
+ Options:
29
+ --format <path> Path to a formatter file that converts JSON files in \`<folder>\` to \`Record<string, string>\`
30
+ so we can compile. The file must export a function named \`compile\` with the signature:
31
+ \`\`\`
32
+ type CompileFn = <T = Record<string, MessageDescriptor>>(
33
+ msgs: T
34
+ ) => Record<string, string>;
35
+ \`\`\`
36
+ This is especially useful to convert from a TMS-specific format back to react-intl format
37
+
38
+ --ast Whether to compile to AST. See
39
+ https://formatjs.io/docs/guides/advanced-usage#pre-parsing-messages
40
+ for more information
41
+ -h, --help display help for command
42
+ ",
43
+ }
44
+ `;
@@ -0,0 +1,33 @@
1
+ import {exec as nodeExec} from 'child_process'
2
+ import {join} from 'path'
3
+ import _rimraf from 'rimraf'
4
+ import {promisify} from 'util'
5
+ import {sync as globSync} from 'fast-glob'
6
+ import {basename} from 'path'
7
+ import {mkdtempSync} from 'fs'
8
+ import {readJSON} from 'fs-extra'
9
+ const exec = promisify(nodeExec)
10
+ const BIN_PATH = require.resolve('@formatjs/cli/bin/formatjs')
11
+
12
+ test('basic case: help', async () => {
13
+ await expect(
14
+ exec(`${BIN_PATH} compile-folder --help`)
15
+ ).resolves.toMatchSnapshot()
16
+ }, 20000)
17
+
18
+ test('basic case', async () => {
19
+ const inputFiles = globSync(`${__dirname}/lang/*.json`)
20
+ const outFolder = mkdtempSync('formatjs-cli')
21
+ await exec(
22
+ `${BIN_PATH} compile-folder ${join(__dirname, 'lang')} ${outFolder}`
23
+ )
24
+
25
+ const outputFiles = globSync(`${outFolder}/*.json`)
26
+ expect(outputFiles.map(f => basename(f))).toEqual(
27
+ inputFiles.map(f => basename(f))
28
+ )
29
+
30
+ await expect(
31
+ Promise.all(outputFiles.map(f => readJSON(f)))
32
+ ).resolves.toMatchSnapshot()
33
+ }, 20000)
@@ -0,0 +1,14 @@
1
+ {
2
+ "ashd2": {
3
+ "defaultMessage": "a message",
4
+ "description": "foo"
5
+ },
6
+ "a1dd2": {
7
+ "defaultMessage": "my name is {name}",
8
+ "description": "foo"
9
+ },
10
+ "a1d12": {
11
+ "defaultMessage": "I have {count, plural, one{a dog} other{many dogs}}",
12
+ "description": "foo"
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "1": {
3
+ "defaultMessage": "another message",
4
+ "description": "foo"
5
+ },
6
+ "2": {
7
+ "defaultMessage": "my name is {foo}",
8
+ "description": "foo"
9
+ },
10
+ "3": {
11
+ "defaultMessage": "I have {count, plural, one{a cat} other{many cats}}",
12
+ "description": "foo"
13
+ }
14
+ }