Skip to content

Commit 7c28f47

Browse files
authored
support --format option for import command (#59)
* support --format option for import command * add test case and refactor
1 parent 8b2afe6 commit 7c28f47

File tree

7 files changed

+96
-23
lines changed

7 files changed

+96
-23
lines changed

src/commands/export.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const handler = async (args: Arguments<ExportOptions>): Promise<unknown>
9292
const locales = args.locales?.split(',').filter(p => p) as Locale[] || []
9393
const provider = ProviderFactory(conf)
9494
const messages = await provider.export({ locales, dryRun, format })
95-
await writeRawLocaleMessages(args.output, format, messages, args.dryRun)
95+
await writeRawLocaleMessages(args.output, messages, args.dryRun)
9696
// TODO: should refactor console message
9797
console.log('export success')
9898
} catch (e) {
@@ -101,7 +101,7 @@ export const handler = async (args: Arguments<ExportOptions>): Promise<unknown>
101101
}
102102
}
103103

104-
async function writeRawLocaleMessages (output: string, format: string, messages: RawLocaleMessage[], dryRun: boolean) {
104+
async function writeRawLocaleMessages (output: string, messages: RawLocaleMessage[], dryRun: boolean) {
105105
debug('writeRawLocaleMessages', messages, dryRun)
106106

107107
// wrap mkdir with dryRun
@@ -112,8 +112,8 @@ async function writeRawLocaleMessages (output: string, format: string, messages:
112112
}
113113

114114
// wrap writeFile with dryRun
115-
const writeFile = async (output: string, format: string, message: RawLocaleMessage) => {
116-
const localePath = path.resolve(output, `${message.locale}.${format}`)
115+
const writeFile = async (output: string, message: RawLocaleMessage) => {
116+
const localePath = path.resolve(output, `${message.locale}.${message.format}`)
117117
console.log(`write '${message.locale}' messages to ${localePath}`)
118118
return !dryRun
119119
? writeFilePromisify(localePath, message.data)
@@ -123,7 +123,7 @@ async function writeRawLocaleMessages (output: string, format: string, messages:
123123
// run!
124124
await mkdir(output)
125125
for (const message of messages) {
126-
await writeFile(output, format, message)
126+
await writeFile(output, message)
127127
}
128128
}
129129

src/commands/import.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ export const builder = (args: Argv): Argv<ImportOptions> => {
5252
alias: 'm',
5353
describe: `option should be accepted a regex filenames, must be specified together --targets if it's directory path of locale messages`
5454
})
55+
.option('format', {
56+
type: 'string',
57+
alias: 'f',
58+
describe: `the locale messages format option when you want to explicitly specify format to locale message files detected with --target or --targetPaths, you need to specify if these locale message files doesn't have format extension`
59+
})
5560
.option('dryRun', {
5661
type: 'boolean',
5762
alias: 'd',

src/utils.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type PushableOptions = {
3232
locale?: string
3333
targetPaths?: string
3434
filenameMatch?: string
35+
format?: string
3536
}
3637

3738
const ESC: { [key in string]: string } = {
@@ -222,10 +223,18 @@ export function getRawLocaleMessages (args: Arguments<PushableOptions>): RawLoca
222223
if (args.target) {
223224
const targetPath = resolve(args.target)
224225
const parsed = path.parse(targetPath)
225-
messages.push({
226-
locale: args.locale ? args.locale : parsed.name,
227-
data: fs.readFileSync(targetPath)
228-
})
226+
const targetFormat = parsed.ext.split('.').pop()
227+
const format = targetFormat || args.format
228+
if (!format) {
229+
// TODO: should refactor console message
230+
console.log(`ignore ${targetPath}, due to be not specified with --format`)
231+
} else {
232+
messages.push({
233+
locale: args.locale ? args.locale : parsed.name,
234+
format,
235+
data: fs.readFileSync(targetPath)
236+
})
237+
}
229238
} else if (args.targetPaths) {
230239
const filenameMatch = args.filenameMatch
231240
if (!filenameMatch) {
@@ -241,10 +250,18 @@ export function getRawLocaleMessages (args: Arguments<PushableOptions>): RawLoca
241250
const match = re.exec(parsed.base)
242251
debug('regex match', match, fullPath)
243252
if (match && match[1]) {
244-
messages.push({
245-
locale: match[1],
246-
data: fs.readFileSync(fullPath)
247-
})
253+
const targetFormat = parsed.ext.split('.').pop()
254+
const format = targetFormat || args.format
255+
if (!format) {
256+
// TODO: should refactor console message
257+
console.log(`ignore ${fullPath}, due to be not specified with --format`)
258+
} else {
259+
messages.push({
260+
locale: match[1],
261+
format,
262+
data: fs.readFileSync(fullPath)
263+
})
264+
}
248265
} else {
249266
// TODO: should refactor console message
250267
console.log(`${fullPath} is not matched with ${filenameMatch}`)

test/commands/export.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ test('--provider: not found', async () => {
9393
test('--conf option', async () => {
9494
// setup mocks
9595
const data = [
96-
{ locale: 'ja', data: Buffer.from(JSON.stringify({})) },
97-
{ locale: 'en', data: Buffer.from(JSON.stringify({})) }
96+
{ locale: 'ja', format: 'json', data: Buffer.from(JSON.stringify({})) },
97+
{ locale: 'en', format: 'json', data: Buffer.from(JSON.stringify({})) }
9898
]
9999
mockExport.mockImplementation(({ locales, format }) => Promise.resolve(data))
100100

@@ -135,8 +135,8 @@ test('--conf option omit', async () => {
135135
test('--locales option', async () => {
136136
// setup mocks
137137
const data = [
138-
{ locale: 'ja', data: Buffer.from(JSON.stringify({})) },
139-
{ locale: 'en', data: Buffer.from(JSON.stringify({})) }
138+
{ locale: 'ja', format: 'json', data: Buffer.from(JSON.stringify({})) },
139+
{ locale: 'en', format: 'json', data: Buffer.from(JSON.stringify({})) }
140140
]
141141
mockExport.mockImplementation(({ locales, format }) => Promise.resolve(data))
142142

@@ -163,8 +163,8 @@ test('--locales option', async () => {
163163
test('--output option', async () => {
164164
// setup mocks
165165
const data = [
166-
{ locale: 'ja', data: Buffer.from(JSON.stringify({ hello: 'hello' })) },
167-
{ locale: 'en', data: Buffer.from(JSON.stringify({ hello: 'こんにちわわわ!' })) }
166+
{ locale: 'ja', format: 'json', data: Buffer.from(JSON.stringify({ hello: 'hello' })) },
167+
{ locale: 'en', format: 'json', data: Buffer.from(JSON.stringify({ hello: 'こんにちわわわ!' })) }
168168
]
169169
mockExport.mockImplementation(({ locales, format }) => Promise.resolve(data))
170170
const mockFS = fs as jest.Mocked<typeof fs>
@@ -190,8 +190,8 @@ test('--output option', async () => {
190190
test('--normalize option', async () => {
191191
// setup mocks
192192
const data = [
193-
{ locale: 'ja', data: Buffer.from(JSON.stringify({})) },
194-
{ locale: 'en', data: Buffer.from(JSON.stringify({})) }
193+
{ locale: 'ja', format: 'json', data: Buffer.from(JSON.stringify({})) },
194+
{ locale: 'en', format: 'json', data: Buffer.from(JSON.stringify({})) }
195195
]
196196
mockExport.mockImplementation(({ locales, format }) => Promise.resolve(data))
197197

@@ -216,8 +216,8 @@ test('--normalize option', async () => {
216216
test('--format option', async () => {
217217
// setup mocks
218218
const data = [
219-
{ locale: 'ja', data: Buffer.from(JSON.stringify({})) },
220-
{ locale: 'en', data: Buffer.from(JSON.stringify({})) }
219+
{ locale: 'ja', format: 'xliff', data: Buffer.from(JSON.stringify({})) },
220+
{ locale: 'en', format: 'xliff', data: Buffer.from(JSON.stringify({})) }
221221
]
222222
mockExport.mockImplementation(({ locales, format }) => Promise.resolve(data))
223223

test/commands/import.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,30 @@ test('require option', async () => {
6060
})
6161

6262
test('--provider: not found', async () => {
63+
// run
6364
const imp = await import('../../src/commands/import')
6465
const cmd = yargs.command(imp)
6566
await new Promise((resolve, reject) => {
6667
cmd.parse(`import --provider=./404-provider.js`, (err, argv, output) => {
6768
err ? reject(err) : resolve(output)
6869
})
6970
})
71+
72+
// verify
7073
expect(spyLog).toHaveBeenCalledWith('Not found ./404-provider.js provider')
7174
})
7275

7376
test('not specified --target and --targetPaths', async () => {
77+
// run
7478
const imp = await import('../../src/commands/import')
7579
const cmd = yargs.command(imp)
7680
await new Promise((resolve, reject) => {
7781
cmd.parse(`import --provider=l10n-service-provider`, (err, argv, output) => {
7882
err ? reject(err) : resolve(output)
7983
})
8084
})
85+
86+
// verify
8187
expect(spyLog).toHaveBeenCalledWith('You need to specify either --target or --target-paths')
8288
})
8389

@@ -95,9 +101,11 @@ test('--target option', async () => {
95101
})
96102
})
97103

104+
// verify
98105
expect(mockImport).toHaveBeenCalledWith({
99106
messages: [{
100107
locale: 'en',
108+
format: 'json',
101109
data: fs.readFileSync('./test/fixtures/locales/en.json')
102110
}],
103111
dryRun: false,
@@ -119,9 +127,11 @@ test('--locale option', async () => {
119127
})
120128
})
121129

130+
// verify
122131
expect(mockImport).toHaveBeenCalledWith({
123132
messages: [{
124133
locale: 'ja',
134+
format: 'json',
125135
data: fs.readFileSync('./test/fixtures/locales/lang.json')
126136
}],
127137
dryRun: false,
@@ -145,12 +155,14 @@ test('--conf option', async () => {
145155
})
146156
})
147157

158+
// verify
148159
expect(L10nServiceProvider).toHaveBeenCalledWith({
149160
provider: { token: 'xxx' }
150161
})
151162
expect(mockImport).toHaveBeenCalledWith({
152163
messages: [{
153164
locale: 'en',
165+
format: 'json',
154166
data: fs.readFileSync('./test/fixtures/locales/en.json')
155167
}],
156168
dryRun: false,
@@ -170,6 +182,7 @@ test('--conf option omit', async () => {
170182
})
171183
})
172184

185+
// verify
173186
expect(L10nOmitServiceProvider).toHaveBeenCalledWith({
174187
provider: { token: 'yyy' }
175188
})
@@ -193,12 +206,15 @@ test('--target-paths option', async () => {
193206
expect(mockImport).toHaveBeenCalledWith({
194207
messages: [{
195208
locale: 'en',
209+
format: 'json',
196210
data: fs.readFileSync('./test/fixtures/locales/en.json')
197211
}, {
198212
locale: 'ja',
213+
format: 'json',
199214
data: fs.readFileSync('./test/fixtures/locales/ja.json')
200215
}, {
201216
locale: 'lang',
217+
format: 'json',
202218
data: fs.readFileSync('./test/fixtures/locales/lang.json')
203219
}],
204220
dryRun: false,
@@ -220,6 +236,7 @@ test('not specified --filename-match', async () => {
220236
})
221237
})
222238

239+
// verify
223240
expect(spyError).toHaveBeenCalledWith('import fail:', 'You need to specify together --filename-match')
224241
})
225242

@@ -237,12 +254,41 @@ test('--dry-run option', async () => {
237254
})
238255
})
239256

257+
// verify
240258
expect(mockImport).toHaveBeenCalledWith({
241259
messages: [{
242260
locale: 'ja',
261+
format: 'json',
243262
data: fs.readFileSync('./test/fixtures/locales/lang.json')
244263
}],
245264
dryRun: true,
246265
normalize: undefined
247266
})
248267
})
268+
269+
test('--format option', async () => {
270+
// setup mocks
271+
mockImport.mockImplementation(({ resource }) => Promise.resolve())
272+
273+
// run
274+
const imp = await import('../../src/commands/import')
275+
const cmd = yargs.command(imp)
276+
await new Promise((resolve, reject) => {
277+
cmd.parse(`import --provider=@scope/l10n-service-provider \
278+
--target=./test/fixtures/locales/ja \
279+
--format=json`, (err, argv, output) => {
280+
err ? reject(err) : resolve(output)
281+
})
282+
})
283+
284+
// verify
285+
expect(mockImport).toHaveBeenCalledWith({
286+
messages: [{
287+
locale: 'ja',
288+
format: 'json',
289+
data: fs.readFileSync('./test/fixtures/locales/ja')
290+
}],
291+
dryRun: false,
292+
normalize: undefined
293+
})
294+
})

test/fixtures/locales/ja

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"hello": "こんにちわわわ!",
3+
"world": "ザ・ワールド"
4+
}

types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export type TranslationStatus = {
169169
*/
170170
export type RawLocaleMessage = {
171171
locale: Locale // target locale
172+
format: string // locale message format
172173
data: Buffer // data of locale message
173174
}
174175

0 commit comments

Comments
 (0)