Skip to content

Commit 27a9074

Browse files
authored
import command feature (#57)
1 parent f63da57 commit 27a9074

File tree

7 files changed

+446
-24
lines changed

7 files changed

+446
-24
lines changed

src/commands/import.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { Arguments, Argv } from 'yargs'
2+
3+
import {
4+
resolveProviderConf,
5+
loadProvider,
6+
loadProviderConf,
7+
DEFUALT_CONF,
8+
getRawLocaleMessages,
9+
PushableOptions
10+
} from '../utils'
11+
12+
type ImportOptions = {
13+
provider: string
14+
conf?: string
15+
dryRun: boolean
16+
} & PushableOptions
17+
18+
export const command = 'import'
19+
export const aliases = 'imp'
20+
export const describe = 'import locale messages to localization service'
21+
22+
export const builder = (args: Argv): Argv<ImportOptions> => {
23+
return args
24+
.option('provider', {
25+
type: 'string',
26+
alias: 'p',
27+
describe: 'the target localization service provider',
28+
demandOption: true
29+
})
30+
.option('conf', {
31+
type: 'string',
32+
alias: 'c',
33+
describe: 'the json file configration of localization service provider. If omitted, use the suffix file name with `-conf` for provider name of --provider (e.g. <provider>-conf.json).'
34+
})
35+
.option('target', {
36+
type: 'string',
37+
alias: 't',
38+
describe: 'target path that locale messages file is stored, default import with the filename of target path as locale'
39+
})
40+
.option('locale', {
41+
type: 'string',
42+
alias: 'l',
43+
describe: `option for the locale of locale messages file specified with --target, if it's specified single-file`
44+
})
45+
.option('targetPaths', {
46+
type: 'string',
47+
alias: 'T',
48+
describe: 'target directory paths that locale messages files is stored, Can also be specified multi paths with comma delimiter'
49+
})
50+
.option('filenameMatch', {
51+
type: 'string',
52+
alias: 'm',
53+
describe: `option should be accepted a regex filenames, must be specified together --targets if it's directory path of locale messages`
54+
})
55+
.option('dryRun', {
56+
type: 'boolean',
57+
alias: 'd',
58+
default: false,
59+
describe: `run the import command, but do not apply to locale messages of localization service`
60+
})
61+
}
62+
63+
export const handler = async (args: Arguments<ImportOptions>): Promise<unknown> => {
64+
const { dryRun } = args
65+
const ProviderFactory = loadProvider(args.provider)
66+
67+
if (ProviderFactory === null) {
68+
// TODO: should refactor console message
69+
console.log(`Not found ${args.provider} provider`)
70+
return
71+
}
72+
73+
if (!args.target && !args.targetPaths) {
74+
// TODO: should refactor console message
75+
console.log('You need to specify either --target or --target-paths')
76+
return
77+
}
78+
79+
const confPath = resolveProviderConf(args.provider, args.conf)
80+
const conf = loadProviderConf(confPath) || DEFUALT_CONF
81+
82+
try {
83+
const messages = getRawLocaleMessages(args)
84+
const provider = ProviderFactory(conf)
85+
await provider.import({ messages, dryRun })
86+
// TODO: should refactor console message
87+
console.log('import success')
88+
} catch (e) {
89+
// TODO: should refactor console message
90+
console.error('import fail:', e.message)
91+
}
92+
}
93+
94+
export default {
95+
command,
96+
aliases,
97+
describe,
98+
builder,
99+
handler
100+
}

src/commands/push.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,15 @@ export const handler = async (args: Arguments<PushOptions>): Promise<unknown> =>
8585
const confPath = resolveProviderConf(args.provider, args.conf)
8686
const conf = loadProviderConf(confPath) || DEFUALT_CONF
8787

88-
let messages
89-
try {
90-
messages = getLocaleMessages(args)
91-
} catch (e) {
92-
console.log(e.message)
93-
return
94-
}
95-
9688
try {
89+
const messages = getLocaleMessages(args)
9790
const provider = ProviderFactory(conf)
9891
await provider.push({ messages, dryRun, normalize })
9992
// TODO: should refactor console message
10093
console.log('push success')
10194
} catch (e) {
10295
// TODO: should refactor console message
103-
console.error('push fail', e)
96+
console.error('push fail:', e.message)
10497
}
10598
}
10699

src/utils.ts

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
// import types
12
import { Arguments } from 'yargs'
23
import { SFCDescriptor } from 'vue-template-compiler'
3-
import { SFCFileInfo, FormatOptions } from '../types'
44
import { VueTemplateCompiler } from '@vue/component-compiler-utils/dist/types'
55
import {
6+
SFCFileInfo,
67
Locale,
78
LocaleMessages,
9+
FormatOptions,
810
ProviderFactory,
911
ProviderConfiguration,
1012
TranslationStatusOptions,
11-
TranslationStatus
13+
TranslationStatus,
14+
RawLocaleMessage
1215
} from '../types'
1316

17+
// import modules
1418
import { parse } from '@vue/component-compiler-utils'
1519
import * as compiler from 'vue-template-compiler'
1620
import fs from 'fs'
@@ -22,6 +26,7 @@ import yaml from 'js-yaml'
2226
import { debug as Debug } from 'debug'
2327
const debug = Debug('vue-i18n-locale-message:utils')
2428

29+
// define types
2530
export type PushableOptions = {
2631
target?: string
2732
locale?: string
@@ -36,14 +41,14 @@ const ESC: { [key in string]: string } = {
3641
'&': '&amp;'
3742
}
3843

39-
export function escape (s: string): string {
40-
return s.replace(/[<>"&]/g, escapeChar)
41-
}
42-
4344
function escapeChar (a: string): string {
4445
return ESC[a] || a
4546
}
4647

48+
export function escape (s: string): string {
49+
return s.replace(/[<>"&]/g, escapeChar)
50+
}
51+
4752
export function resolve (...paths: string[]): string {
4853
return path.resolve(...paths)
4954
}
@@ -211,6 +216,46 @@ export function getLocaleMessages (args: Arguments<PushableOptions>): LocaleMess
211216
return messages
212217
}
213218

219+
export function getRawLocaleMessages (args: Arguments<PushableOptions>): RawLocaleMessage[] {
220+
const messages = [] as RawLocaleMessage[]
221+
222+
if (args.target) {
223+
const targetPath = resolve(args.target)
224+
const parsed = path.parse(targetPath)
225+
messages.push({
226+
locale: args.locale ? args.locale : parsed.name,
227+
data: fs.readFileSync(targetPath)
228+
})
229+
} else if (args.targetPaths) {
230+
const filenameMatch = args.filenameMatch
231+
if (!filenameMatch) {
232+
// TODO: should refactor console message
233+
throw new Error('You need to specify together --filename-match')
234+
}
235+
const targetPaths = args.targetPaths.split(',').filter(p => p)
236+
targetPaths.forEach(targetPath => {
237+
const globedPaths = glob.sync(targetPath).map(p => resolve(p))
238+
globedPaths.forEach(fullPath => {
239+
const parsed = path.parse(fullPath)
240+
const re = new RegExp(filenameMatch, 'ig')
241+
const match = re.exec(parsed.base)
242+
debug('regex match', match, fullPath)
243+
if (match && match[1]) {
244+
messages.push({
245+
locale: match[1],
246+
data: fs.readFileSync(fullPath)
247+
})
248+
} else {
249+
// TODO: should refactor console message
250+
console.log(`${fullPath} is not matched with ${filenameMatch}`)
251+
}
252+
})
253+
})
254+
}
255+
256+
return messages
257+
}
258+
214259
export async function getTranslationStatus (options: TranslationStatusOptions): Promise<TranslationStatus[]> {
215260
const ProviderFactory = loadProvider(options.provider)
216261
if (ProviderFactory === null) {

test/commands/__mocks__/l10n-service-provider.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ class L10nServiceProvider {
1717
percentable: 100.0
1818
}])
1919
}
20+
21+
async import (messsages, dryRun) {
22+
return
23+
}
24+
25+
async export (locales, format, dryRun) {
26+
const data = [{
27+
locale: 'ja',
28+
data: Buffer.from(JSON.stringify({}))
29+
}, {
30+
locale: 'en',
31+
data: Buffer.from(JSON.stringify({}))
32+
}]
33+
return Promise.resolve(data)
34+
}
2035
}
2136

2237
module.exports = L10nServiceProvider

0 commit comments

Comments
 (0)