@gctools-components/i18n-translation-webpack-plugin
Version:
Complete i18n translation solution for webpack, including code-splitting and automatic generation of translation files
226 lines (182 loc) • 14.2 kB
JavaScript
;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
* Author: National Research Council Canada
* Website: http://www.nrc-cnrc.gc.ca/eng/rd/ict/
*
* License: MIT
* Copyright: Her Majesty the Queen in Right of Canada, as represented by
* the Minister of National Research Council, 2017
*/
var _ConstDependency = require('webpack/lib/dependencies/ConstDependency');
var _ConstDependency2 = _interopRequireDefault(_ConstDependency);
var _NullFactory = require('webpack/lib/NullFactory');
var _NullFactory2 = _interopRequireDefault(_NullFactory);
var _ParserHelpers = require('webpack/lib/ParserHelpers');
var _ParserHelpers2 = _interopRequireDefault(_ParserHelpers);
var _I18nNormalModuleFactory = require('./I18nNormalModuleFactory');
var _I18nNormalModuleFactory2 = _interopRequireDefault(_I18nNormalModuleFactory);
var _I18nDependency = require('./I18nDependency');
var _I18nDependency2 = _interopRequireDefault(_I18nDependency);
var _I18nInterpolatedDependency = require('./I18nInterpolatedDependency');
var _I18nInterpolatedDependency2 = _interopRequireDefault(_I18nInterpolatedDependency);
var _poBuilder = require('./po-builder');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var path = require('path');
/**
* I18N Translation Webpack plugin
*
* Provides automatic creation of familiar gettext based translation files,
* while automatically injecting the translation strings into your application
* bundle. Various levels of code splitting are supported.
*
*/
var I18nTranslationWebpackPlugin = function () {
function I18nTranslationWebpackPlugin(options) {
_classCallCheck(this, I18nTranslationWebpackPlugin);
this.pot_files = {};
this.options = Object.assign({
languages: ['en_CA', 'fr_CA'],
i18n_dir: 'i18n',
extract_text_test: /\.(js|jsx)$/,
extract_text_exclude: /node_modules/,
codeSplitting: 'language',
translate_global: '__',
interpolate_global: '___',
localizer_global: 'localizer',
localizer_window: false
}, options);
}
_createClass(I18nTranslationWebpackPlugin, [{
key: 'apply',
value: function apply(compiler) {
var _this = this;
var context = compiler.context || process.cwd();
var i18nDir = path.join(context, this.options.i18n_dir);
(0, _poBuilder.ensureDirExists)(i18nDir);
this.pot_files = (0, _poBuilder.buildPotHash)(i18nDir);
this.gtc_config = (0, _poBuilder.createGettextConfig)(context, this.options.i18n_dir);
if (!compiler.options.module.rules) {
// eslint-disable-next-line no-param-reassign
compiler.options.module.rules = [];
}
compiler.options.module.rules.push({
test: this.options.extract_text_test,
use: { loader: 'gettext-loader' },
exclude: this.options.extract_text_exclude
});
compiler.hooks.done.tap('i18n_plugin', function () {
if (_this.gtc_config) {
_this.gtc_config.remove();
delete _this.gtc_config;
}
});
compiler.hooks.compilation.tap('i18n-plugin', function (compilation, _ref) {
var normalModuleFactory = _ref.normalModuleFactory;
var i18nFactory = new _I18nNormalModuleFactory2.default(normalModuleFactory);
compilation.dependencyFactories.set(_I18nDependency2.default, i18nFactory);
compilation.dependencyFactories.set(_I18nInterpolatedDependency2.default, i18nFactory);
compilation.dependencyFactories.set(_ConstDependency2.default, new _NullFactory2.default());
compilation.dependencyTemplates.set(_I18nDependency2.default, new _I18nDependency2.default.Template());
compilation.dependencyTemplates.set(_I18nInterpolatedDependency2.default, new _I18nInterpolatedDependency2.default.Template());
compilation.dependencyTemplates.set(_ConstDependency2.default, new _ConstDependency2.default.Template());
var handler = function handler(parser) {
var _options = _this.options,
name = _options.translate_global,
interpolate = _options.interpolate_global,
loc = _options.localizer_global,
availableLanguages = _options.languages;
var interpolateReplaces = [];
parser.hooks.call.for(name).tap('i18n-plugin', function (expr) {
var ikey = interpolateReplaces.indexOf(expr.range[0]) >= 0;
var resource = parser.state.module.resource;
var dep = false;
if (expr.arguments.length === 1) {
var _expr$arguments = _slicedToArray(expr.arguments, 1),
arg = _expr$arguments[0];
var key = parser.evaluateExpression(arg).string;
var domain = path.relative(context, resource);
dep = new _I18nDependency2.default(expr, key, domain, undefined, ikey, _this.options);
dep.loc = expr.loc;
} else if (expr.arguments.length === 2) {
var _expr$arguments2 = _slicedToArray(expr.arguments, 2),
arg1 = _expr$arguments2[0],
arg2 = _expr$arguments2[1];
var _key = parser.evaluateExpression(arg1).string;
var value = parser.evaluateExpression(arg2).number;
var _domain = path.relative(context, resource);
dep = new _I18nDependency2.default(expr, _key, _domain, value, ikey, _this.options);
dep.loc = expr.loc;
}
if (dep) {
parser.state.current.addDependency(dep);
}
return true;
});
parser.hooks.call.for(interpolate).tap('i18n-plugin', function (expr) {
var resource = parser.state.module.resource;
if (expr.arguments.length > 1) {
var domain = path.relative(context, resource);
var dep = new _I18nInterpolatedDependency2.default(expr, name, domain, _this.options);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
// Interpolate takes a literal as it's first parameter, but
// only key's prefixed by the `translate_global` are processed.
// To solve this, if the first argument to the interpolate
// function is `translate_global`, it is marked and later removed
var findLocalizedKey = function findLocalizedKey(node) {
if (node.type === 'CallExpression') {
if (node.callee.name === dep.tglobal) {
interpolateReplaces.push(node.callee.range[0]);
}
if (node.arguments) {
for (var x = 0; x < node.arguments.length; x += 1) {
findLocalizedKey(node.arguments[x]);
}
}
}
};
findLocalizedKey(dep.expr.arguments[0]);
}
// must return false to continue parsing inside function
return false;
});
parser.hooks.expression.for(loc).tap('i18n-plugin', function (expr) {
var pathToLocalizer = path.join(__dirname, 'localizer.js');
var config = { availableLanguages: availableLanguages };
var ex = '\n require(' + JSON.stringify(pathToLocalizer) + ').default(\n ' + JSON.stringify(config) + '\n )\n ';
if (!_ParserHelpers2.default.addParsedVariableToModule(parser, loc, ex)) {
return false;
}
_ParserHelpers2.default.toConstantDependency(parser, loc).bind(parser)(expr);
return true;
});
};
normalModuleFactory.hooks.parser.for('javascript/auto').tap('i18n-plugin', handler);
normalModuleFactory.hooks.parser.for('javascript/dynamic').tap('i18n-plugin', handler);
});
compiler.hooks.afterResolvers.tap('i18n-plugin-ar', function () {
compiler.resolverFactory.hooks.resolver.for('normal').tap('i18n', function (resolver) {
resolver.hooks.resolve.tapAsync('i18n', function (params, _, callback) {
if (params.request === './<I18nWebpackPlugin>') {
_this.pot_files = (0, _poBuilder.buildPoFiles)(path.join(context, _this.options.i18n_dir), _this.pot_files, _this.options.languages);
var filename = path.join(__dirname, 'localizer.js');
callback(null, {
path: filename,
module: true,
file: false,
resolved: true,
query: '?options=' + encodeURIComponent(JSON.stringify(_this.options))
});
} else {
callback();
}
});
});
});
}
}]);
return I18nTranslationWebpackPlugin;
}();
module.exports = I18nTranslationWebpackPlugin;