i18next-scanner
Advanced tools
Comparing version 1.6.0 to 1.7.0
@@ -61,5 +61,13 @@ 'use strict'; | ||
nsSeparator: ':', // char to split namespace from key | ||
pluralSeparator: '_', // char to split plural from key | ||
// Context Form | ||
context: true, // whether to add context form key | ||
contextFallback: true, // whether to add a fallback key as well as the context form key | ||
contextSeparator: '_', // char to split context from key | ||
// Plural Form | ||
plural: true, // whether to add plural form key | ||
pluralFallback: true, // whether to add a fallback key as well as the plural form key | ||
pluralSeparator: '_', // char to split plural from key | ||
// interpolation options | ||
@@ -308,20 +316,18 @@ interpolation: { | ||
if (endsWithComma) { | ||
(function () { | ||
var code = matchBalancedParentheses(content.substr(re.lastIndex)); | ||
var syntax = _esprima2.default.parse('(' + code + ')'); | ||
var props = _lodash2.default.get(syntax, 'body[0].expression.properties') || []; | ||
// http://i18next.com/docs/options/ | ||
var supportedOptions = ['defaultValue', 'count', 'context', 'ns']; | ||
var code = matchBalancedParentheses(content.substr(re.lastIndex)); | ||
var syntax = _esprima2.default.parse('(' + code + ')'); | ||
var props = _lodash2.default.get(syntax, 'body[0].expression.properties') || []; | ||
// http://i18next.com/docs/options/ | ||
var supportedOptions = ['defaultValue', 'count', 'context', 'ns']; | ||
props.forEach(function (prop) { | ||
if (_lodash2.default.includes(supportedOptions, prop.key.name)) { | ||
if (prop.value.type === 'Literal') { | ||
options[prop.key.name] = prop.value.value; | ||
} else { | ||
// Unable to get value of the property | ||
options[prop.key.name] = ''; | ||
} | ||
props.forEach(function (prop) { | ||
if (_lodash2.default.includes(supportedOptions, prop.key.name)) { | ||
if (prop.value.type === 'Literal') { | ||
options[prop.key.name] = prop.value.value; | ||
} else { | ||
// Unable to get value of the property | ||
options[prop.key.name] = ''; | ||
} | ||
}); | ||
})(); | ||
} | ||
}); | ||
} | ||
@@ -502,6 +508,6 @@ | ||
if (_lodash2.default.isString(options)) { | ||
var defaultValue = options; | ||
var _defaultValue = options; | ||
options = {}; | ||
options.defaultValue = defaultValue; | ||
options.defaultValue = _defaultValue; | ||
} | ||
@@ -531,5 +537,15 @@ | ||
var _options = this.options, | ||
lngs = _options.lngs, | ||
context = _options.context, | ||
contextFallback = _options.contextFallback, | ||
contextSeparator = _options.contextSeparator, | ||
plural = _options.plural, | ||
pluralFallback = _options.pluralFallback, | ||
pluralSeparator = _options.pluralSeparator, | ||
defaultValue = _options.defaultValue; | ||
var keys = _lodash2.default.isString(keySeparator) ? key.split(keySeparator) : [key]; | ||
this.options.lngs.forEach(function (lng) { | ||
lngs.forEach(function (lng) { | ||
var resLoad = _this4.resStore[lng] && _this4.resStore[lng][ns]; | ||
@@ -573,45 +589,45 @@ var resScan = _this4.resScan[lng] && _this4.resScan[lng][ns]; | ||
// } | ||
var formattedKey = key; | ||
var resKeys = []; | ||
// http://i18next.com/translate/context/ | ||
// Note. The parser only supports string type for "context" | ||
var needsContextHandling = options.context !== undefined && typeof options.context === 'string' && options.context !== ''; | ||
if (needsContextHandling) { | ||
formattedKey = formattedKey + _this4.options.contextSeparator + options.context; | ||
} | ||
var containsContext = context && options.context !== undefined && typeof options.context === 'string' && options.context !== ''; | ||
// http://i18next.com/translate/pluralSimple/ | ||
var needsPluralHandling = options.count !== undefined; | ||
if (needsPluralHandling) { | ||
// TODO: multiple plural forms | ||
formattedKey = formattedKey + _this4.options.pluralSeparator + 'plural'; | ||
var containsPlural = plural && options.count !== undefined; | ||
if (!containsContext && !containsPlural) { | ||
resKeys.push(key); | ||
} | ||
if (options.defaultValue !== undefined) { | ||
// Use `options.defaultValue` if specified | ||
if (resLoad[key] === undefined) { | ||
resLoad[key] = options.defaultValue; | ||
_this4.debuglog('Added a new translation key { %s: %s } to %s', JSON.stringify(key), JSON.stringify(resLoad[key]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns))); | ||
} | ||
resScan[key] = resLoad[key]; | ||
if (containsContext && contextFallback || containsPlural && pluralFallback) { | ||
resKeys.push(key); | ||
} | ||
if (formattedKey !== key && resLoad[formattedKey] === undefined) { | ||
resLoad[formattedKey] = options.defaultValue; | ||
_this4.debuglog('Added a new translation key { %s: %s } to %s', JSON.stringify(formattedKey), JSON.stringify(resLoad[formattedKey]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns))); | ||
if (containsContext) { | ||
resKeys.push('' + key + contextSeparator + options.context); | ||
} | ||
if (containsPlural) { | ||
resKeys.push('' + key + pluralSeparator + 'plural'); | ||
} | ||
if (containsContext && containsPlural) { | ||
resKeys.push('' + key + contextSeparator + options.context + pluralSeparator + 'plural'); | ||
} | ||
resKeys.forEach(function (resKey) { | ||
if (resLoad[resKey] === undefined) { | ||
if (options.defaultValue !== undefined) { | ||
// Use `options.defaultValue` if specified | ||
resLoad[resKey] = options.defaultValue; | ||
} else { | ||
// Fallback to `defaultValue` | ||
resLoad[resKey] = _lodash2.default.isFunction(defaultValue) ? defaultValue(lng, ns, key, options) : defaultValue; | ||
} | ||
_this4.debuglog('Added a new translation key { %s: %s } to %s', JSON.stringify(resKey), JSON.stringify(resLoad[resKey]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns))); | ||
} | ||
resScan[formattedKey] = resLoad[formattedKey]; | ||
} else { | ||
// Fallback to `this.options.defaultValue` | ||
if (resLoad[key] === undefined) { | ||
resLoad[key] = _lodash2.default.isFunction(_this4.options.defaultValue) ? _this4.options.defaultValue(lng, ns, key, options) : _this4.options.defaultValue; | ||
_this4.debuglog('Added a new translation key { %s: %s } to %s', JSON.stringify(key), JSON.stringify(resLoad[key]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns))); | ||
} | ||
resScan[key] = resLoad[key]; | ||
if (formattedKey !== key && resLoad[formattedKey] === undefined) { | ||
resLoad[formattedKey] = _lodash2.default.isFunction(_this4.options.defaultValue) ? _this4.options.defaultValue(lng, ns, key, options) : _this4.options.defaultValue; | ||
_this4.debuglog('Added a new translation key { %s: %s } to %s', JSON.stringify(formattedKey), JSON.stringify(resLoad[formattedKey]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns))); | ||
} | ||
resScan[formattedKey] = resLoad[formattedKey]; | ||
} | ||
resScan[resKey] = resLoad[resKey]; | ||
}); | ||
}); | ||
@@ -618,0 +634,0 @@ }); |
{ | ||
"name": "i18next-scanner", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"description": "Scan your code, extract translation keys/values, and merge them into i18n resource files.", | ||
@@ -47,5 +47,5 @@ "homepage": "https://github.com/i18next/i18next-scanner", | ||
"dependencies": { | ||
"esprima": "^3.1.2", | ||
"lodash": "^4.17.2", | ||
"through2": "^2.0.2", | ||
"esprima": "^3.1.3", | ||
"lodash": "^4.17.4", | ||
"through2": "^2.0.3", | ||
"vinyl": "^2.0.1", | ||
@@ -55,16 +55,17 @@ "vinyl-fs": "^2.4.4" | ||
"devDependencies": { | ||
"babel-cli": "^6.18.0", | ||
"babel-core": "^6.18.2", | ||
"babel-cli": "^6.24.0", | ||
"babel-core": "^6.24.0", | ||
"babel-eslint": "^7.1.1", | ||
"babel-preset-es2015": "^6.18.0", | ||
"babel-preset-stage-0": "^6.16.0", | ||
"coveralls": "^2.11.15", | ||
"eslint": "^3.11.0", | ||
"babel-preset-es2015": "^6.24.0", | ||
"babel-preset-stage-0": "^6.22.0", | ||
"coveralls": "^2.12.0", | ||
"eslint": "^3.17.1", | ||
"gulp": "^3.9.1", | ||
"gulp-tap": "^0.1.3", | ||
"gulp-util": "^3.0.7", | ||
"gulp-util": "^3.0.8", | ||
"sha1": "^1.1.1", | ||
"tap": "^8.0.1", | ||
"text-table": "^0.2.0" | ||
"tap": "^10.3.0", | ||
"text-table": "^0.2.0", | ||
"which": "~1.2.12" | ||
} | ||
} |
@@ -487,8 +487,14 @@ # i18next-scanner [![build status](https://travis-ci.org/i18next/i18next-scanner.svg?branch=master)](https://travis-ci.org/i18next/i18next-scanner) [![Coverage Status](https://coveralls.io/repos/i18next/i18next-scanner/badge.svg?branch=master&service=github)](https://coveralls.io/github/i18next/i18next-scanner?branch=master) | ||
#### pluralSeparator | ||
#### context | ||
Type: `String` Default: `'_'` | ||
Type: `Boolean` Default: `true` | ||
The character to split plural from key. | ||
Whether to add context form key. | ||
#### contextFallback | ||
Type: `Boolean` Default: `true` | ||
Whether to add a fallback key as well as the context form key. | ||
#### contextSeparator | ||
@@ -500,2 +506,20 @@ | ||
#### plural | ||
Type: `Boolean` Default: `true` | ||
Whether to add plural form key. | ||
#### pluralFallback | ||
Type: `Boolean` Default: `true` | ||
Whether to add a fallback key as well as the plural form key. | ||
#### pluralSeparator | ||
Type: `String` Default: `'_'` | ||
The character to split plural from key. | ||
#### interpolation | ||
@@ -502,0 +526,0 @@ |
@@ -39,5 +39,13 @@ /* eslint no-console: 0 */ | ||
nsSeparator: ':', // char to split namespace from key | ||
pluralSeparator: '_', // char to split plural from key | ||
// Context Form | ||
context: true, // whether to add context form key | ||
contextFallback: true, // whether to add a fallback key as well as the context form key | ||
contextSeparator: '_', // char to split context from key | ||
// Plural Form | ||
plural: true, // whether to add plural form key | ||
pluralFallback: true, // whether to add a fallback key as well as the plural form key | ||
pluralSeparator: '_', // char to split plural from key | ||
// interpolation options | ||
@@ -465,5 +473,15 @@ interpolation: { | ||
const { | ||
lngs, | ||
context, | ||
contextFallback, | ||
contextSeparator, | ||
plural, | ||
pluralFallback, | ||
pluralSeparator, | ||
defaultValue | ||
} = this.options; | ||
const keys = _.isString(keySeparator) ? key.split(keySeparator) : [key]; | ||
this.options.lngs.forEach((lng) => { | ||
lngs.forEach((lng) => { | ||
let resLoad = this.resStore[lng] && this.resStore[lng][ns]; | ||
@@ -506,64 +524,55 @@ let resScan = this.resScan[lng] && this.resScan[lng][ns]; | ||
// } | ||
let formattedKey = key; | ||
const resKeys = []; | ||
// http://i18next.com/translate/context/ | ||
// Note. The parser only supports string type for "context" | ||
const needsContextHandling = (options.context !== undefined) && (typeof options.context === 'string') && (options.context !== ''); | ||
if (needsContextHandling) { | ||
formattedKey = formattedKey + this.options.contextSeparator + options.context; | ||
} | ||
const containsContext = context | ||
&& (options.context !== undefined) | ||
&& (typeof options.context === 'string') | ||
&& (options.context !== ''); | ||
// http://i18next.com/translate/pluralSimple/ | ||
const needsPluralHandling = (options.count !== undefined); | ||
if (needsPluralHandling) { // TODO: multiple plural forms | ||
formattedKey = formattedKey + this.options.pluralSeparator + 'plural'; | ||
const containsPlural = plural | ||
&& (options.count !== undefined); | ||
if (!containsContext && !containsPlural) { | ||
resKeys.push(key); | ||
} | ||
if (options.defaultValue !== undefined) { | ||
// Use `options.defaultValue` if specified | ||
if (resLoad[key] === undefined) { | ||
resLoad[key] = options.defaultValue; | ||
this.debuglog('Added a new translation key { %s: %s } to %s', | ||
JSON.stringify(key), | ||
JSON.stringify(resLoad[key]), | ||
JSON.stringify(this.formatResourceLoadPath(lng, ns)) | ||
); | ||
} | ||
resScan[key] = resLoad[key]; | ||
if ((containsContext && contextFallback) || (containsPlural && pluralFallback)) { | ||
resKeys.push(key); | ||
} | ||
if ((formattedKey !== key) && (resLoad[formattedKey] === undefined)) { | ||
resLoad[formattedKey] = options.defaultValue; | ||
if (containsContext) { | ||
resKeys.push(`${key}${contextSeparator}${options.context}`); | ||
} | ||
if (containsPlural) { | ||
resKeys.push(`${key}${pluralSeparator}plural`); | ||
} | ||
if (containsContext && containsPlural) { | ||
resKeys.push(`${key}${contextSeparator}${options.context}${pluralSeparator}plural`); | ||
} | ||
resKeys.forEach(resKey => { | ||
if (resLoad[resKey] === undefined) { | ||
if (options.defaultValue !== undefined) { | ||
// Use `options.defaultValue` if specified | ||
resLoad[resKey] = options.defaultValue; | ||
} else { | ||
// Fallback to `defaultValue` | ||
resLoad[resKey] = _.isFunction(defaultValue) | ||
? defaultValue(lng, ns, key, options) | ||
: defaultValue; | ||
} | ||
this.debuglog('Added a new translation key { %s: %s } to %s', | ||
JSON.stringify(formattedKey), | ||
JSON.stringify(resLoad[formattedKey]), | ||
JSON.stringify(resKey), | ||
JSON.stringify(resLoad[resKey]), | ||
JSON.stringify(this.formatResourceLoadPath(lng, ns)) | ||
); | ||
} | ||
resScan[formattedKey] = resLoad[formattedKey]; | ||
} else { | ||
// Fallback to `this.options.defaultValue` | ||
if (resLoad[key] === undefined) { | ||
resLoad[key] = _.isFunction(this.options.defaultValue) | ||
? this.options.defaultValue(lng, ns, key, options) | ||
: this.options.defaultValue; | ||
this.debuglog('Added a new translation key { %s: %s } to %s', | ||
JSON.stringify(key), | ||
JSON.stringify(resLoad[key]), | ||
JSON.stringify(this.formatResourceLoadPath(lng, ns)) | ||
); | ||
} | ||
resScan[key] = resLoad[key]; | ||
if ((formattedKey !== key) && (resLoad[formattedKey] === undefined)) { | ||
resLoad[formattedKey] = _.isFunction(this.options.defaultValue) | ||
? this.options.defaultValue(lng, ns, key, options) | ||
: this.options.defaultValue; | ||
this.debuglog('Added a new translation key { %s: %s } to %s', | ||
JSON.stringify(formattedKey), | ||
JSON.stringify(resLoad[formattedKey]), | ||
JSON.stringify(this.formatResourceLoadPath(lng, ns)) | ||
); | ||
} | ||
resScan[formattedKey] = resLoad[formattedKey]; | ||
} | ||
resScan[resKey] = resLoad[resKey]; | ||
}); | ||
}); | ||
@@ -570,0 +579,0 @@ }); |
@@ -1,5 +0,1 @@ | ||
i18next.t('friend', {count: 1}); // output: 'A friend' | ||
i18next.t('friend', {count: 100}); // output: '100 friends' | ||
i18next.t('friend', {context: 'male'}); // output: 'A boyfriend' | ||
i18next.t('friend', {context: 'female'}); // output: 'A girlfriend' | ||
i18next.t('friend', {context: 'male', count: 1}); // output: 'A boyfriend' | ||
@@ -6,0 +2,0 @@ i18next.t('friend', {context: 'female', count: 1}); // output: 'A girlfriend' |
@@ -1,3 +0,2 @@ | ||
i18next.t('friend'); // output: 'A friend' | ||
i18next.t('friend', {context: 'male'}); // output: 'A boyfriend' | ||
i18next.t('friend', {context: 'female'}); // output: 'A girlfriend' |
@@ -365,17 +365,92 @@ import fs from 'fs'; | ||
test('Context with plural combined', (t) => { | ||
const parser = new Parser(); | ||
const content = fs.readFileSync(path.resolve(__dirname, 'fixtures/context-plural.js'), 'utf-8'); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend": "", | ||
"friend_plural": "", | ||
"friend_male": "", | ||
"friend_male_plural": "", | ||
"friend_female": "", | ||
"friend_female_plural": "" | ||
test('Default options', (t) => { | ||
const parser = new Parser(); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend": "", | ||
"friend_plural": "", | ||
"friend_male": "", | ||
"friend_male_plural": "", | ||
"friend_female": "", | ||
"friend_female_plural": "" | ||
} | ||
} | ||
} | ||
}); | ||
t.end(); | ||
}); | ||
test('Context form only', (t) => { | ||
const parser = new Parser({ | ||
context: true, | ||
plural: false | ||
}); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend": "", | ||
"friend_male": "", | ||
"friend_female": "" | ||
} | ||
} | ||
}); | ||
t.end(); | ||
}); | ||
test('No context fallback', (t) => { | ||
const parser = new Parser({ | ||
context: true, | ||
contextFallback: false, | ||
plural: false | ||
}); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend_male": "", | ||
"friend_female": "" | ||
} | ||
} | ||
}); | ||
t.end(); | ||
}); | ||
test('Plural form only', (t) => { | ||
const parser = new Parser({ | ||
context: false, | ||
plural: true | ||
}); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend": "", | ||
"friend_plural": "" | ||
} | ||
} | ||
}); | ||
t.end(); | ||
}); | ||
test('No plural fallback', (t) => { | ||
const parser = new Parser({ | ||
context: false, | ||
plural: true, | ||
pluralFallback: false | ||
}); | ||
parser.parseFuncFromString(content); | ||
t.same(parser.get(), { | ||
en: { | ||
translation: { | ||
"friend_plural": "" | ||
} | ||
} | ||
}); | ||
t.end(); | ||
}); | ||
t.end(); | ||
@@ -382,0 +457,0 @@ }); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
116876
2319
548
14
Updatedesprima@^3.1.3
Updatedlodash@^4.17.4
Updatedthrough2@^2.0.3