Skip to content

Commit

Permalink
adds formatter for interpolation
Browse files Browse the repository at this point in the history
  • Loading branch information
jamuhl committed Jul 13, 2016
1 parent 0334b92 commit d3cc9ba
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 16 deletions.
33 changes: 28 additions & 5 deletions i18next.js
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@
// interpolate
var data = options.replace && typeof options.replace !== 'string' ? options.replace : options;
if (this.options.interpolation.defaultVariables) data = _extends({}, this.options.interpolation.defaultVariables, data);
res = this.interpolator.interpolate(res, data);
res = this.interpolator.interpolate(res, data, this.language);

// nesting
res = this.interpolator.nest(res, function () {
Expand Down Expand Up @@ -1177,7 +1177,12 @@
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var reset = arguments[1];

if (reset) this.options = options;
if (reset) {
this.options = options;
this.format = options.interpolation && options.interpolation.format || function (value) {
return value;
};
}
if (!options.interpolation) options.interpolation = { escapeValue: true };

var iOpts = options.interpolation;
Expand All @@ -1186,6 +1191,7 @@

this.prefix = iOpts.prefix ? regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{';
this.suffix = iOpts.suffix ? regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}';
this.formatSeparator = iOpts.formatSeparator ? regexEscape(iOpts.formatSeparator) : iOpts.formatSeparator || ',';

this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-';
this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || '';
Expand All @@ -1208,24 +1214,37 @@
if (this.options) this.init(this.options);
};

Interpolator.prototype.interpolate = function interpolate(str, data) {
Interpolator.prototype.interpolate = function interpolate(str, data, lng) {
var _this = this;

var match = void 0,
value = void 0;

function regexSafe(val) {
return val.replace(/\$/g, '$$$$');
}

var handleFormat = function handleFormat(key) {
if (key.indexOf(_this.formatSeparator) < 0) return getPath(data, key);

var p = key.split(_this.formatSeparator);

This comment has been minimized.

Copy link
@LodewijkSioen

LodewijkSioen Jul 14, 2016

There's a bug here: if your format contains the formatSeparator, everything after it is ignored.

This comment has been minimized.

Copy link
@jamuhl

jamuhl Jul 14, 2016

Author Member

should the format contain the separator? can provide a fix for this...np...but still wonder


var k = p[0].trim();
var f = p[1].trim();

return _this.format(getPath(data, k), f, lng);
};

// unescape if has unescapePrefix/Suffix
while (match = this.regexpUnescape.exec(str)) {
var _value = getPath(data, match[1].trim());
var _value = handleFormat(match[1].trim());
str = str.replace(match[0], _value);
this.regexpUnescape.lastIndex = 0;
}

// regular escape on demand
while (match = this.regexp.exec(str)) {
value = getPath(data, match[1].trim());
value = handleFormat(match[1].trim());
if (typeof value !== 'string') value = makeString(value);
if (!value) {
this.logger.warn('missed to pass in variable ' + match[1] + ' for interpolating ' + str);
Expand Down Expand Up @@ -1672,8 +1691,12 @@

interpolation: {
escapeValue: true,
format: function format(value, _format, lng) {
return value;
},
prefix: '{{',
suffix: '}}',
formatSeparator: ',',
// prefixEscaped: '{{',
// suffixEscaped: '}}',
// unescapeSuffix: '',
Expand Down
4 changes: 2 additions & 2 deletions i18next.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"rollup-plugin-node-resolve": "1.7.1",
"rollup-plugin-uglify": "1.0.1",
"sinon": "1.17.4",
"watchify": "3.7.0",
"yargs": "4.8.0"
},
"scripts": {
Expand Down
31 changes: 23 additions & 8 deletions src/Interpolator.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ class Interpolator {
}

init(options = {}, reset) {
if (reset) this.options = options;
if (reset) {
this.options = options;
this.format = (options.interpolation && options.interpolation.format) || function(value) {return value};
}
if (!options.interpolation) options.interpolation = { escapeValue: true };

let iOpts = options.interpolation;
const iOpts = options.interpolation;

this.escapeValue = iOpts.escapeValue;

this.prefix = iOpts.prefix ? utils.regexEscape(iOpts.prefix) : iOpts.prefixEscaped || '{{';
this.suffix = iOpts.suffix ? utils.regexEscape(iOpts.suffix) : iOpts.suffixEscaped || '}}';
this.formatSeparator = iOpts.formatSeparator ? utils.regexEscape(iOpts.formatSeparator) : iOpts.formatSeparator || ',';

this.unescapePrefix = iOpts.unescapeSuffix ? '' : iOpts.unescapePrefix || '-';
this.unescapeSuffix = this.unescapePrefix ? '' : iOpts.unescapeSuffix || '';
Expand All @@ -26,37 +30,48 @@ class Interpolator {
this.nestingSuffix = iOpts.nestingSuffix ? utils.regexEscape(iOpts.nestingSuffix) : iOpts.nestingSuffixEscaped || utils.regexEscape(')');

// the regexp
let regexpStr = this.prefix + '(.+?)' + this.suffix;
const regexpStr = this.prefix + '(.+?)' + this.suffix;
this.regexp = new RegExp(regexpStr, 'g');

let regexpUnescapeStr = this.prefix + this.unescapePrefix + '(.+?)' + this.unescapeSuffix + this.suffix;
const regexpUnescapeStr = this.prefix + this.unescapePrefix + '(.+?)' + this.unescapeSuffix + this.suffix;
this.regexpUnescape = new RegExp(regexpUnescapeStr, 'g');

let nestingRegexpStr = this.nestingPrefix + '(.+?)' + this.nestingSuffix;
const nestingRegexpStr = this.nestingPrefix + '(.+?)' + this.nestingSuffix;
this.nestingRegexp = new RegExp(nestingRegexpStr, 'g');
}

reset() {
if (this.options) this.init(this.options);
}

interpolate(str, data) {
interpolate(str, data, lng) {
let match, value;

function regexSafe(val) {
return val.replace(/\$/g, '$$$$');
}

const handleFormat = (key) => {
if (key.indexOf(this.formatSeparator) < 0) return utils.getPath(data, key);

const p = key.split(this.formatSeparator);

const k = p[0].trim();
const f = p[1].trim();

return this.format(utils.getPath(data, k), f, lng);
}

// unescape if has unescapePrefix/Suffix
while(match = this.regexpUnescape.exec(str)) {
let value = utils.getPath(data, match[1].trim());
let value = handleFormat(match[1].trim());
str = str.replace(match[0], value);
this.regexpUnescape.lastIndex = 0;
}

// regular escape on demand
while(match = this.regexp.exec(str)) {
value = utils.getPath(data, match[1].trim());
value = handleFormat(match[1].trim());
if (typeof value !== 'string') value = utils.makeString(value);
if (!value) {
this.logger.warn(`missed to pass in variable ${match[1]} for interpolating ${str}`);
Expand Down
2 changes: 1 addition & 1 deletion src/Translator.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class Translator extends EventEmitter {
// interpolate
let data = options.replace && typeof options.replace !== 'string' ? options.replaceoptions;
if (this.options.interpolation.defaultVariables) data = {...this.options.interpolation.defaultVariables, ...data};
res = this.interpolator.interpolate(res, data);
res = this.interpolator.interpolate(res, data, this.language);

// nesting
res = this.interpolator.nest(res, (...args) => { return this.translate.apply(this, args); }, options);
Expand Down
2 changes: 2 additions & 0 deletions src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ export function get() {

interpolation: {
escapeValue: true,
format: function(value, format, lng) { return value },
prefix: '{{',
suffix: '}}',
formatSeparator: ',',
// prefixEscaped: '{{',
// suffixEscaped: '}}',
// unescapeSuffix: '',
Expand Down
29 changes: 29 additions & 0 deletions test/interpolation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,35 @@ describe('Interpolator', () => {
});
});

describe('interpolate() - with formatter', () => {
var ip;

before(() => {
ip = new Interpolator({
interpolation: {
escapeValue: false,
format: function(value, format, lng) {
if (format === 'uppercase') return value.toUpperCase();
if (format === 'lowercase') return value.toLowerCase();
return value;
}
}
});
});

var tests = [
{args: ['test {{test, uppercase}}', {test: 'up'}], expected: 'test UP'},
{args: ['test {{test, lowercase}}', {test: 'DOWN'}], expected: 'test down'}
];

tests.forEach((test) => {
it('correctly interpolates for ' + JSON.stringify(test.args) + ' args', () => {
expect(ip.interpolate.apply(ip, test.args)).to.eql(test.expected);
});
});
});


describe('interpolate() - unescape', () => {
var ip;

Expand Down

0 comments on commit d3cc9ba

Please sign in to comment.