diff --git a/lib/index.js b/lib/index.js index 1c075a9..847334b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -25,6 +25,10 @@ class Tag { '': this.defaultConfig } + this.translationCache = {} + + this.keyCache = {} + this._localizers = { s /*string*/: (config, v, format) => { let formatted @@ -81,6 +85,8 @@ class Tag { } i18nConfig({locales, translations, group, number, date, standardFormatters}) { + // clear translation cache + this.translationCache = {} const currentConfig = this.configs[group || ''] || this.defaultConfig this.configs[group || ''] = Object.assign({}, currentConfig, { locales: locales || currentConfig.locales, @@ -92,24 +98,34 @@ class Tag { } i18n(group, config, literals, ...values) { - const translationKey = this._buildKey(literals) - const configGroup = this.configs[config || ''] || this.defaultConfig - const translationString = this._getTranslation(group, configGroup, translationKey) + const translationKey = this._buildKey(literals) + const { configGroup, translatedKey } = this._getCachedTranslation(group, config, translationKey) const typeInfoForValues = literals.slice(1).map(this._extractTypeInfo) const localizedValues = values.map((v, i) => this._localize(configGroup, v, typeInfoForValues[i])) - return this._buildMessage(translationString, ...localizedValues) + return this._buildMessage(translatedKey, ...localizedValues) } translate(group, config, key, ...values) { - const configGroup = this.configs[config || ''] || this.defaultConfig - const translationString = this._getTranslation(group, configGroup, key) + const { configGroup, translatedKey } = this._getCachedTranslation(group, config, key) const localizedValues = values.map((v) => { if(v instanceof Object && v.constructor === Object) { return this._localize(configGroup, v.value || '', { type: v.formatter || 's', options: v.format }) } return this._localize(configGroup, v, { type: 's', options: '' }) }) - return this._buildMessage(translationString, ...localizedValues) + return this._buildMessage(translatedKey, ...localizedValues) + } + + _getCachedTranslation(group, config, translationKey) { + const cacheKey = [group || '', config || '', translationKey].join() + const cachedTranslation = this.translationCache[cacheKey] + const configGroup = this.configs[config || ''] || this.defaultConfig + if(cachedTranslation) { + return { configGroup, translatedKey: cachedTranslation } + } + const translationString = this._getTranslation(group, configGroup, translationKey) + this.translationCache[cacheKey] = translationString + return { configGroup, translatedKey: translationString } } _getTranslation(group, configGroup, translationKey) { @@ -291,11 +307,19 @@ class Tag { // e.g. this._buildKey(['', ' has ', ':c in the']) == '{0} has {1} in the bank' _buildKey(literals) { + const cacheKey = literals.join() + const cachedKey = this.keyCache[cacheKey] + if(cachedKey) { + return cachedKey + } + const stripType = (s) => s.replace(typeInfoRegex, '') const lastPartialKey = stripType(literals[literals.length - 1]) const prependPartialKey = (memo, curr, i) => `${stripType(curr)}\${${i}}${memo}` - return literals.slice(0, -1).reduceRight(prependPartialKey, lastPartialKey).replace(/\r\n/g, '\n') + const key = literals.slice(0, -1).reduceRight(prependPartialKey, lastPartialKey).replace(/\r\n/g, '\n') + this.keyCache[cacheKey] = key + return key } // e.g. this._formatStrings('{0} {1}!', 'hello', 'world') == 'hello world!'