-
-
Save RavenXce/efe2584779350367dab4851ac15276fa to your computer and use it in GitHub Desktop.
Venuu I18n Webpack integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ConstDependency = require('webpack/lib/dependencies/ConstDependency'); | |
var NullFactory = require('webpack/lib/NullFactory'); | |
var _ = require('lodash'); | |
function I18nRuntimePlugin(options) { | |
options = options || {}; | |
this.functionNames = options.functionNames || ['I18n.t', 'I18n.translate']; | |
this.translationsPlaceholder = options.translationsPlaceholder || 'I18N_RUNTIME_TRANSLATIONS'; | |
this.fullTranslations = options.fullTranslations || {}; | |
} | |
module.exports = I18nRuntimePlugin; | |
/** | |
* Return a single translation from the fullTranslations object using the | |
* normalized keypath string ("a.string.to.translate") | |
*/ | |
function resolveTranslation(keypath, locale, fullTranslations) { | |
return keypath.split('.').reduce(function(previous, current) { | |
if (previous) { | |
return previous[current]; | |
} | |
}, fullTranslations[locale]); | |
} | |
/** | |
* Add a translation to the given object, looking it up from the | |
* fullTranslations object using the given keypath | |
*/ | |
function addTranslation(key, usedTranslationsForAllLocales, fullTranslations) { | |
Object.keys(usedTranslationsForAllLocales).forEach(function (locale) { | |
var usedTranslations = usedTranslationsForAllLocales[locale]; | |
// Find the last possible translation object which can be modified in-place | |
// to set the new translations into. | |
var objToMergeTo = key.split('.').slice(0, -1).reduce(function(previous, current) { | |
previous[current] = previous[current] || {}; | |
return previous[current]; | |
}, usedTranslations); | |
// Find the translation to merge into the existing translations | |
var objToMergeFrom = {}; | |
objToMergeFrom[key.split('.').slice(-1)[0]] = resolveTranslation(key, locale, fullTranslations); | |
_.merge(objToMergeTo, objToMergeFrom); | |
}); | |
} | |
I18nRuntimePlugin.prototype.apply = function(compiler) { | |
var replacementDependency; | |
var keys = []; | |
var fullTranslations = this.fullTranslations; | |
var usedTranslations = {}; | |
// Initialize all locales to empty objects | |
Object.keys(fullTranslations).forEach(function (locale) { usedTranslations[locale] = {}; }); | |
compiler.plugin('compilation', function(compilation) { | |
compilation.dependencyFactories.set(ConstDependency, new NullFactory()); | |
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template()); | |
}); | |
/* | |
* Obtain a reference to the placeholder location. | |
* We will decide the content later on. | |
*/ | |
compiler.parser.plugin('expression ' + this.translationsPlaceholder, function(expr) { | |
replacementDependency = new ConstDependency(null, expr.range); | |
replacementDependency.loc = expr.loc; | |
this.state.current.addDependency(replacementDependency); | |
return true; | |
}); | |
/* | |
* Collects the first argument of each call to `I18n.t` into the `keys` array. | |
*/ | |
var collectKey = function(functionExpression) { | |
if (functionExpression.arguments.length < 1) return; | |
var key = this.evaluateExpression(functionExpression.arguments[0]); | |
if (!key.isString()) return; | |
key = key.string; | |
if (keys.indexOf(key) >= 0) return; | |
keys.push(key); | |
// Add the translation to the usedTranslations object | |
addTranslation(key, usedTranslations, fullTranslations); | |
// We don't know when the last call will occur, so we change the | |
// replacement on every call. | |
replacementDependency.expression = JSON.stringify(usedTranslations); | |
return; | |
}; | |
this.functionNames.forEach(function(functionName) { | |
compiler.parser.plugin('call ' + functionName, collectKey); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment