Skip to content

Commit

Permalink
⭐ new: push command (#21) by @kazupon
Browse files Browse the repository at this point in the history
* 📌 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
  • Loading branch information
kazupon committed Dec 18, 2019
1 parent abd6d4c commit 7cdf3f4
Show file tree
Hide file tree
Showing 17 changed files with 667 additions and 10 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ yarn global vue-i18n-locale-message
- CLI
- squeeze the locale messages from `i18n` custom block
- infuse the locale messages to `i18n` custom block
- push the locale messages to localization service

## :rocket: Usages

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

#### push

```sh
vue-i18n-locale-message push --provider=l10n-service-provider \
--conf=110n-service-provider-conf.json \
--target-paths=./src/locales/*.json \
--filename-match=^([\\w]*)\\.json
```

## :raising_hand: Motivations

The big motivation is as follows.

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

## :book: API: Specifications

Expand Down
181 changes: 181 additions & 0 deletions lib/commands/push.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../utils");
const path_1 = __importDefault(require("path"));
const glob_1 = __importDefault(require("glob"));
const debug_1 = require("debug");
const debug = debug_1.debug('vue-i18n-locale-message:commands:push');
const DEFUALT_CONF = { provider: {}, pushMode: 'locale-message' };
exports.command = 'push';
exports.aliases = 'ph';
exports.describe = 'push locale messages to localization service';
exports.builder = (args) => {
return args
.option('provider', {
type: 'string',
alias: 'p',
describe: 'the target localization service provider',
demandOption: true
})
.option('conf', {
type: 'string',
alias: 'c',
describe: 'the json file configration of localization service provider'
})
.option('target', {
type: 'string',
alias: 't',
describe: 'target path that locale messages file is stored, default push with the filename of target path as locale'
})
.option('locale', {
type: 'string',
alias: 'l',
describe: `option for the locale of locale messages file specified with --target, if it's specified single-file`
})
.option('targetPaths', {
type: 'string',
alias: 'T',
describe: 'target directory paths that locale messages files is stored, Can also be specified multi paths with comma delimiter'
})
.option('filenameMatch', {
type: 'string',
alias: 'm',
describe: `option should be accepted a regex filenames, must be specified together --targets if it's directory path of locale messages`
})
.option('dryRun', {
type: 'boolean',
alias: 'd',
default: false,
describe: `run the push command, but do not apply to locale messages of localization service`
});
};
exports.handler = async (args) => {
const ProviderFactory = loadProvider(args.provider);
if (ProviderFactory === null) {
// TODO: should refactor console message
console.log(`Not found ${args.provider} provider`);
return;
}
let conf = DEFUALT_CONF;
if (args.conf) {
conf = loadProviderConf(utils_1.resolve(args.conf));
}
if (!args.target && !args.targetPaths) {
// TODO: should refactor console message
console.log('You need to specify either --target or --target-paths');
return;
}
let resource;
try {
resource = getProviderPushResource(args, conf.pushMode);
}
catch (e) {
console.log(e.message);
return;
}
const provider = ProviderFactory(conf);
const ret = await provider.push(resource, args.dryRun);
if (ret) {
// TODO: should refactor console message
console.log('push success');
}
else {
// TODO: should refactor console message
console.error('push fail');
}
};
function loadProvider(provider) {
let mod = null;
try {
// TODO: should validate I/F checking & dynamic importing
const m = require(require.resolve(provider));
debug('loaderProvider', m);
if ('__esModule' in m) {
mod = m.default;
}
else {
mod = m;
}
}
catch (e) { }
return mod;
}
function loadProviderConf(confPath) {
let conf = DEFUALT_CONF;
try {
// TODO: should validate I/F checking & dynamic importing
conf = require(confPath);
}
catch (e) { }
return conf;
}
function getProviderPushResource(args, mode) {
var _a;
const resource = { mode };
debug(`getProviderPushResource: mode=${mode}`);
if (mode === 'locale-message') {
resource.messages = {};
}
else { // 'file-path'
resource.files = [];
}
if (args.target) {
const targetPath = utils_1.resolve(args.target);
const parsed = path_1.default.parse(targetPath);
const locale = args.locale ? args.locale : parsed.name;
if (mode === 'locale-message') {
resource.messages = Object.assign(resource.messages, { [locale]: require(targetPath) });
}
else { // 'file-path'
(_a = resource.files) === null || _a === void 0 ? void 0 : _a.push({
locale,
path: targetPath
});
}
}
else if (args.targetPaths) {
const filenameMatch = args.filenameMatch;
if (!filenameMatch) {
// TODO: should refactor console message
throw new Error('You need to specify together --filename-match');
}
const targetPaths = args.targetPaths.split(',').filter(p => p);
targetPaths.forEach(targetPath => {
const globedPaths = glob_1.default.sync(targetPath).map(p => utils_1.resolve(p));
globedPaths.forEach(fullPath => {
var _a;
const parsed = path_1.default.parse(fullPath);
const re = new RegExp(filenameMatch, 'ig');
const match = re.exec(parsed.base);
debug('regex match', match, fullPath);
if (match && match[1]) {
const locale = match[1];
if (mode === 'locale-message') {
resource.messages = Object.assign(resource.messages, { [locale]: require(fullPath) });
}
else { // 'file-path'
(_a = resource.files) === null || _a === void 0 ? void 0 : _a.push({
locale,
path: fullPath
});
}
}
else {
// TODO: should refactor console message
console.log(`${fullPath} is not matched with ${filenameMatch}`);
}
});
});
}
return resource;
}
exports.default = {
command: exports.command,
aliases: exports.aliases,
describe: exports.describe,
builder: exports.builder,
handler: exports.handler
};
8 changes: 6 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ function reflectSFCDescriptor(basePath, components) {
filename: target.path,
compiler: compiler
});
return Object.assign(Object.assign({}, parsePath(basePath, target.path)), { raw: target.content, customBlocks,
return {
...parsePath(basePath, target.path),
raw: target.content,
customBlocks,
template,
script,
styles });
styles
};
});
}
exports.reflectSFCDescriptor = reflectSFCDescriptor;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"jest": "^24.8.0",
"opener": "^1.5.1",
"ts-jest": "^24.0.2",
"typescript": "^3.7.0",
"typescript": "^3.7.3",
"typescript-eslint-language-service": "^1.3.0",
"vue": "^2.6.10",
"vue-template-compiler": "^2.6.10"
Expand Down

0 comments on commit 7cdf3f4

Please sign in to comment.