Skip to content

Commit 4f625f2

Browse files
committed
Support backslash based escaping for placeholders
The simpleParse method of parser, which get invoked if message contains only placeholders, was not supporting escaped placeholders(\\$10) The light weight versio of jquery.i18n when parser.js not included also has the same fix now. Add support for that and add tests. Updated the documentation in README.md too Fixes issue #74
1 parent 7daaceb commit 4f625f2

File tree

5 files changed

+33
-11
lines changed

5 files changed

+33
-11
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,12 @@ var message = "Welcome, $1";
313313
$.i18n(message, 'Alice'); // This gives "Welcome, Alice"
314314
```
315315

316-
316+
To escape the $ sign, use double blackslash in json file. Example:
317+
```javascript
318+
{
319+
"messageKey": "Price of {{PLURAL:$1|an item|$1 items}} is $2, you get \\$2 discount."
320+
}
321+
```
317322
## Plurals
318323

319324
To make the syntax of sentence correct, plural forms are required. jquery.i18n support plural forms in the message using the syntax `{{PLURAL:$1|pluralform1|pluralform2|...}}`

src/jquery.i18n.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@
142142
source = 'i18n/' + $.i18n().locale + '.json';
143143
locale = $.i18n().locale;
144144
}
145-
if ( typeof source === 'string' &&
145+
if ( typeof source === 'string' &&
146146
source.split( '.' ).pop() !== 'json'
147147
) {
148148
// Load specified locale then check for fallbacks when directory is specified in load()
@@ -260,16 +260,22 @@
260260
$.i18n.parser = {
261261
// The default parser only handles variable substitution
262262
parse: function ( message, parameters ) {
263-
return message.replace( /\$(\d+)/g, function ( str, match ) {
264-
var index = parseInt( match, 10 ) - 1;
265-
return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
263+
return message.replace( /(\\?\$\d+)/g, function ( str, match ) {
264+
var index;
265+
266+
if ( match[ 0 ] === '\\' ) {
267+
// Escaped.
268+
return match.slice( 1 );
269+
}
270+
index = parseInt( match.slice( 1 ), 10 ) - 1;
271+
return parameters[ index ] !== undefined ? parameters[ index ] : match;
266272
} );
267273
},
268274
emitter: {}
269275
};
270276
$.i18n.fallbacks = {};
271277
$.i18n.debug = false;
272-
$.i18n.log = function ( /* arguments */ ) {
278+
$.i18n.log = function () {
273279
if ( window.console && $.i18n.debug ) {
274280
window.console.log.apply( window.console, arguments );
275281
}

src/jquery.i18n.parser.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@
2727
constructor: MessageParser,
2828

2929
simpleParse: function ( message, parameters ) {
30-
return message.replace( /\$(\d+)/g, function ( str, match ) {
31-
var index = parseInt( match, 10 ) - 1;
30+
return message.replace( /(\\?\$\d+)/g, function ( str, match ) {
31+
var index;
3232

33-
return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
33+
if ( match[ 0 ] === '\\' ) {
34+
// Escaped.
35+
return match.slice( 1 );
36+
}
37+
index = parseInt( match.slice( 1 ), 10 ) - 1;
38+
return parameters[ index ] !== undefined ? parameters[ index ] : match;
3439
} );
3540
},
3641

test/i18n/test-en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"message_1": "ONE",
33
"message_2": "TWO",
4-
"message_3": "THREE"
4+
"message_3": "THREE",
5+
"message_4": "Total \\$1 of \\$1500"
56
}

test/jquery.i18n.test.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
}
3535
} );
3636

37-
QUnit.test( 'Message parse tests (en)', 14, function ( assert ) {
37+
QUnit.test( 'Message parse tests (en)', 16, function ( assert ) {
3838
var pluralAndGenderMessage,
3939
pluralAndGenderMessageWithLessParaMS,
4040
pluralAndGenderMessageWithCase,
@@ -49,13 +49,18 @@
4949
QUnit.start();
5050
assert.strictEqual( i18n.locale, 'en', 'Locale is English' );
5151
assert.strictEqual( $.i18n( 'message_1' ), 'ONE', 'Simple message' );
52+
assert.strictEqual( $.i18n( 'message_4', 5 ), 'Total $1 of $1500', 'Parameter replacement escaped' );
5253
} );
5354
assert.strictEqual(
5455
$.i18n( 'This message key does not exist' ),
5556
'This message key does not exist',
5657
'This message key does not exist'
5758
);
5859
assert.strictEqual( $.i18n( 'Hello $1', 'Bob' ), 'Hello Bob', 'Parameter replacement' );
60+
assert.strictEqual(
61+
$.i18n( 'Price of {{PLURAL:$1|an item|$1 items}} is $2, you get \\$2 discount', 5, 2000 ),
62+
'Price of 5 items is 2000, you get $2 discount', 'Parameter replacement with dollar sign escaped, not parsed using simplePaser'
63+
);
5964
pluralAndGenderMessage = '$1 has $2 {{plural:$2|kitten|kittens}}. ' +
6065
'{{gender:$3|He|She}} loves to play with {{plural:$2|it|them}}.';
6166
pluralAndGenderMessageWithLessParaMS = '$1 has $2 {{plural:$2|kitten}}. ' +

0 commit comments

Comments
 (0)