Skip to content

Commit 7cdf3f4

Browse files
authored
⭐ new: push command (#21) by @kazupon
* 📌 upgrade typescript * ⭐ new: add push command * 📦 build: generate dist files * 👕 refactor: change to kebab-case from camel-case * 📝 docs: add push command usage * 🆙 change push passing resource * 🆙 update: tweak provider interface * 🆙 update: fix ci
1 parent abd6d4c commit 7cdf3f4

File tree

17 files changed

+667
-10
lines changed

17 files changed

+667
-10
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ yarn global vue-i18n-locale-message
4444
- CLI
4545
- squeeze the locale messages from `i18n` custom block
4646
- infuse the locale messages to `i18n` custom block
47+
- push the locale messages to localization service
4748

4849
## :rocket: Usages
4950

@@ -101,13 +102,22 @@ vue-i18n-locale-message squeeze --target=./src --output=./messages.json
101102
vue-i18n-locale-message infuse --target=./src --locales=./translated.json
102103
```
103104

105+
#### push
106+
107+
```sh
108+
vue-i18n-locale-message push --provider=l10n-service-provider \
109+
--conf=110n-service-provider-conf.json \
110+
--target-paths=./src/locales/*.json \
111+
--filename-match=^([\\w]*)\\.json
112+
```
113+
104114
## :raising_hand: Motivations
105115

106116
The big motivation is as follows.
107117

108118
- :tired_face: Hard to integrate locale messages for localization services
109119
- :tired_face: Hard to maintain consistency of locale message keys (`eslint-plugin-vue-i18n` need it!)
110-
- :pray: Requested by 3rd vendor tools (`vue-i18n-ally` and etc ...)
120+
- :pray: Requested by 3rd vendor tools (`i18n-ally` and etc ...)
111121

112122
## :book: API: Specifications
113123

lib/commands/push.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
const utils_1 = require("../utils");
7+
const path_1 = __importDefault(require("path"));
8+
const glob_1 = __importDefault(require("glob"));
9+
const debug_1 = require("debug");
10+
const debug = debug_1.debug('vue-i18n-locale-message:commands:push');
11+
const DEFUALT_CONF = { provider: {}, pushMode: 'locale-message' };
12+
exports.command = 'push';
13+
exports.aliases = 'ph';
14+
exports.describe = 'push locale messages to localization service';
15+
exports.builder = (args) => {
16+
return args
17+
.option('provider', {
18+
type: 'string',
19+
alias: 'p',
20+
describe: 'the target localization service provider',
21+
demandOption: true
22+
})
23+
.option('conf', {
24+
type: 'string',
25+
alias: 'c',
26+
describe: 'the json file configration of localization service provider'
27+
})
28+
.option('target', {
29+
type: 'string',
30+
alias: 't',
31+
describe: 'target path that locale messages file is stored, default push with the filename of target path as locale'
32+
})
33+
.option('locale', {
34+
type: 'string',
35+
alias: 'l',
36+
describe: `option for the locale of locale messages file specified with --target, if it's specified single-file`
37+
})
38+
.option('targetPaths', {
39+
type: 'string',
40+
alias: 'T',
41+
describe: 'target directory paths that locale messages files is stored, Can also be specified multi paths with comma delimiter'
42+
})
43+
.option('filenameMatch', {
44+
type: 'string',
45+
alias: 'm',
46+
describe: `option should be accepted a regex filenames, must be specified together --targets if it's directory path of locale messages`
47+
})
48+
.option('dryRun', {
49+
type: 'boolean',
50+
alias: 'd',
51+
default: false,
52+
describe: `run the push command, but do not apply to locale messages of localization service`
53+
});
54+
};
55+
exports.handler = async (args) => {
56+
const ProviderFactory = loadProvider(args.provider);
57+
if (ProviderFactory === null) {
58+
// TODO: should refactor console message
59+
console.log(`Not found ${args.provider} provider`);
60+
return;
61+
}
62+
let conf = DEFUALT_CONF;
63+
if (args.conf) {
64+
conf = loadProviderConf(utils_1.resolve(args.conf));
65+
}
66+
if (!args.target && !args.targetPaths) {
67+
// TODO: should refactor console message
68+
console.log('You need to specify either --target or --target-paths');
69+
return;
70+
}
71+
let resource;
72+
try {
73+
resource = getProviderPushResource(args, conf.pushMode);
74+
}
75+
catch (e) {
76+
console.log(e.message);
77+
return;
78+
}
79+
const provider = ProviderFactory(conf);
80+
const ret = await provider.push(resource, args.dryRun);
81+
if (ret) {
82+
// TODO: should refactor console message
83+
console.log('push success');
84+
}
85+
else {
86+
// TODO: should refactor console message
87+
console.error('push fail');
88+
}
89+
};
90+
function loadProvider(provider) {
91+
let mod = null;
92+
try {
93+
// TODO: should validate I/F checking & dynamic importing
94+
const m = require(require.resolve(provider));
95+
debug('loaderProvider', m);
96+
if ('__esModule' in m) {
97+
mod = m.default;
98+
}
99+
else {
100+
mod = m;
101+
}
102+
}
103+
catch (e) { }
104+
return mod;
105+
}
106+
function loadProviderConf(confPath) {
107+
let conf = DEFUALT_CONF;
108+
try {
109+
// TODO: should validate I/F checking & dynamic importing
110+
conf = require(confPath);
111+
}
112+
catch (e) { }
113+
return conf;
114+
}
115+
function getProviderPushResource(args, mode) {
116+
var _a;
117+
const resource = { mode };
118+
debug(`getProviderPushResource: mode=${mode}`);
119+
if (mode === 'locale-message') {
120+
resource.messages = {};
121+
}
122+
else { // 'file-path'
123+
resource.files = [];
124+
}
125+
if (args.target) {
126+
const targetPath = utils_1.resolve(args.target);
127+
const parsed = path_1.default.parse(targetPath);
128+
const locale = args.locale ? args.locale : parsed.name;
129+
if (mode === 'locale-message') {
130+
resource.messages = Object.assign(resource.messages, { [locale]: require(targetPath) });
131+
}
132+
else { // 'file-path'
133+
(_a = resource.files) === null || _a === void 0 ? void 0 : _a.push({
134+
locale,
135+
path: targetPath
136+
});
137+
}
138+
}
139+
else if (args.targetPaths) {
140+
const filenameMatch = args.filenameMatch;
141+
if (!filenameMatch) {
142+
// TODO: should refactor console message
143+
throw new Error('You need to specify together --filename-match');
144+
}
145+
const targetPaths = args.targetPaths.split(',').filter(p => p);
146+
targetPaths.forEach(targetPath => {
147+
const globedPaths = glob_1.default.sync(targetPath).map(p => utils_1.resolve(p));
148+
globedPaths.forEach(fullPath => {
149+
var _a;
150+
const parsed = path_1.default.parse(fullPath);
151+
const re = new RegExp(filenameMatch, 'ig');
152+
const match = re.exec(parsed.base);
153+
debug('regex match', match, fullPath);
154+
if (match && match[1]) {
155+
const locale = match[1];
156+
if (mode === 'locale-message') {
157+
resource.messages = Object.assign(resource.messages, { [locale]: require(fullPath) });
158+
}
159+
else { // 'file-path'
160+
(_a = resource.files) === null || _a === void 0 ? void 0 : _a.push({
161+
locale,
162+
path: fullPath
163+
});
164+
}
165+
}
166+
else {
167+
// TODO: should refactor console message
168+
console.log(`${fullPath} is not matched with ${filenameMatch}`);
169+
}
170+
});
171+
});
172+
}
173+
return resource;
174+
}
175+
exports.default = {
176+
command: exports.command,
177+
aliases: exports.aliases,
178+
describe: exports.describe,
179+
builder: exports.builder,
180+
handler: exports.handler
181+
};

lib/utils.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,14 @@ function reflectSFCDescriptor(basePath, components) {
4343
filename: target.path,
4444
compiler: compiler
4545
});
46-
return Object.assign(Object.assign({}, parsePath(basePath, target.path)), { raw: target.content, customBlocks,
46+
return {
47+
...parsePath(basePath, target.path),
48+
raw: target.content,
49+
customBlocks,
4750
template,
4851
script,
49-
styles });
52+
styles
53+
};
5054
});
5155
}
5256
exports.reflectSFCDescriptor = reflectSFCDescriptor;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"jest": "^24.8.0",
4242
"opener": "^1.5.1",
4343
"ts-jest": "^24.0.2",
44-
"typescript": "^3.7.0",
44+
"typescript": "^3.7.3",
4545
"typescript-eslint-language-service": "^1.3.0",
4646
"vue": "^2.6.10",
4747
"vue-template-compiler": "^2.6.10"

0 commit comments

Comments
 (0)