Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #949 from LiskHQ/831-i18n-scanner-in-webpack
Browse files Browse the repository at this point in the history
Convert i18n-scanner command into a webpack plugin - Closes #831
  • Loading branch information
slaweet authored Nov 6, 2017
2 parents 8544afd + 629e6e0 commit fd0ebf3
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 32 deletions.
9 changes: 9 additions & 0 deletions config/webpack.config.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { resolve } = require('path');
const webpack = require('webpack');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const I18nScannerPlugin = require('../src/i18n-scanner');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
/* eslint-enable import/no-extraneous-dependencies */

Expand Down Expand Up @@ -38,6 +39,14 @@ module.exports = {
filename: 'styles.css',
allChunks: true,
}),
new I18nScannerPlugin({
translationFunctionNames: ['i18next.t', 'props.t', 'this.props.t', 't'],
outputFilePath: './i18n/locales/en/common.json',
files: [
'./src/**/*.js',
'./app/src/**/*.js',
],
}),
new HardSourceWebpackPlugin(),
],
};
1 change: 0 additions & 1 deletion i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"Failed to connect to node {{address}}": "Failed to connect to node {{address}}",
"Failed to connect: Node {{address}} is not active": "Failed to connect: Node {{address}} is not active",
"Fee": "Fee",
"Fee: LSK": "Fee: LSK",
"Fee: {{amount}} LSK": "Fee: {{amount}} LSK",
"Fee: {{fee}} LSK": "Fee: {{fee}} LSK",
"Forget this account": "Forget this account",
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"pack": "npm install && npm run build && npm run clean-dist && npm run dist",
"pack:win": "cmd /c npm install && npm run clean-build && npm run copy-files && npm run build-prod && npm run build-electron && npm run clean-dist && npm run dist:win",
"storybook": "start-storybook -p 6006 -s ./src/",
"i18n-scanner": "node ./src/i18n-scanner.js",
"build-storybook": "build-storybook"
},
"author": "Lisk Foundation <admin@lisk.io>, lightcurve GmbH <admin@lightcurve.io>",
Expand Down
2 changes: 1 addition & 1 deletion src/components/pricedButton/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('PricedButton', () => {
});

it('renders a span saying "Fee: 5 LSK"', () => {
expect(wrapper.find(`.${styles.fee}`).text()).to.be.equal(i18n.t('Fee: 5 LSK'));
expect(wrapper.find(`.${styles.fee}`).text()).to.be.equal(i18n.t('Fee: {{fee}} LSK', { fee: 5 }));
});

it('allows to click on Button', () => {
Expand Down
80 changes: 51 additions & 29 deletions src/i18n-scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,60 @@ const fs = require('fs');
const glob = require('glob');
const Parser = require('i18next-scanner').Parser;

const translationFunctionNames = ['i18next.t', 'props.t', 'this.props.t', 't'];
const outputFilePath = './src/locales/en/common.json';
function i18nScanner(params) {
const parser = new Parser({
keySeparator: '>',
nsSeparator: '|',
});

const translationsSource = JSON.parse(fs.readFileSync(outputFilePath, 'utf8'));
const sourceJSON = fs.readFileSync(params.outputFilePath, 'utf8');
let translationsSource;
try {
translationsSource = JSON.parse(sourceJSON);
} catch (e) {
process.stderr.write(`i18nScanner: ${e}\n`);
return;
}

const parser = new Parser({
keySeparator: '>',
nsSeparator: '|',
});
const customHandler = function (key, options) {
const value = translationsSource[key] || key;
if (options.context) {
key += `_${options.context}`;
}
parser.set(key, value);
if (options.count !== undefined) {
key = `${key}_plural`;
parser.set(key, translationsSource[key] || '');
}
};

params.files.map(filePattern => glob.sync(filePattern, {}))
.reduce(((accumulator, files) => [...accumulator, ...files]), [])
.forEach((file) => {
const content = fs.readFileSync(file, 'utf-8');
parser.parseFuncFromString(content, { list: params.translationFunctionNames }, customHandler);
});

const customHandler = function (key, options) {
const value = translationsSource[key] || key;
if (options.context) {
key += `_${options.context}`;
const translations = parser.get({ sort: true }).en.translation;
const count = Object.keys(translations).length;
const outputJSON = `${JSON.stringify(translations, null, 2)}\n`;
if (outputJSON !== sourceJSON) {
fs.writeFileSync(params.outputFilePath, outputJSON);
process.stdout.write(`i18nScanner: ${count} translation keys parsed and written to '${params.outputFilePath}'\n`);
}
parser.set(key, value);
if (options.count !== undefined) {
key = `${key}_plural`;
parser.set(key, translationsSource[key] || '');
}

class I18nScannerPlugin {
constructor(options) {
this.options = options;
}
};

const files = glob.sync('./src/**/*.js', {});
const electronFiles = glob.sync('./app/src/**/*.js', {});
[...files, ...electronFiles].forEach((file) => {
const content = fs.readFileSync(file, 'utf-8');
parser.parseFuncFromString(content, { list: translationFunctionNames }, customHandler);
});

const translations = parser.get({ sort: true }).en.translation;
const count = Object.keys(translations).length;
const outputJSON = JSON.stringify(translations, null, 2);
fs.writeFileSync(outputFilePath, `${outputJSON}\n`);
process.stdout.write(`${count} translation keys parsed and written to '${outputFilePath}'`);

apply(compiler) {
compiler.plugin('emit', (compilation, callback) => {
i18nScanner(this.options);
callback();
});
}
}

module.exports = I18nScannerPlugin;

0 comments on commit fd0ebf3

Please sign in to comment.