diff --git a/README.md b/README.md index da82c2b..9e5de74 100644 --- a/README.md +++ b/README.md @@ -313,7 +313,12 @@ var message = "Welcome, $1"; $.i18n(message, 'Alice'); // This gives "Welcome, Alice" ``` - +To escape the $ sign, use double blackslash in json file. Example: +```javascript +{ + "messageKey": "Price of {{PLURAL:$1|an item|$1 items}} is $2, you get \\$2 discount." +} +``` ## Plurals 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|...}}` diff --git a/src/jquery.i18n.js b/src/jquery.i18n.js index 7ac8ba8..4633c4f 100644 --- a/src/jquery.i18n.js +++ b/src/jquery.i18n.js @@ -142,7 +142,7 @@ source = 'i18n/' + $.i18n().locale + '.json'; locale = $.i18n().locale; } - if ( typeof source === 'string' && + if ( typeof source === 'string' && source.split( '.' ).pop() !== 'json' ) { // Load specified locale then check for fallbacks when directory is specified in load() @@ -260,16 +260,22 @@ $.i18n.parser = { // The default parser only handles variable substitution parse: function ( message, parameters ) { - return message.replace( /\$(\d+)/g, function ( str, match ) { - var index = parseInt( match, 10 ) - 1; - return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match; + return message.replace( /(\\?\$\d+)/g, function ( str, match ) { + var index; + + if ( match[ 0 ] === '\\' ) { + // Escaped. + return match.slice( 1 ); + } + index = parseInt( match.slice( 1 ), 10 ) - 1; + return parameters[ index ] !== undefined ? parameters[ index ] : match; } ); }, emitter: {} }; $.i18n.fallbacks = {}; $.i18n.debug = false; - $.i18n.log = function ( /* arguments */ ) { + $.i18n.log = function () { if ( window.console && $.i18n.debug ) { window.console.log.apply( window.console, arguments ); } diff --git a/src/jquery.i18n.parser.js b/src/jquery.i18n.parser.js index 8a9ca19..0619500 100644 --- a/src/jquery.i18n.parser.js +++ b/src/jquery.i18n.parser.js @@ -27,10 +27,15 @@ constructor: MessageParser, simpleParse: function ( message, parameters ) { - return message.replace( /\$(\d+)/g, function ( str, match ) { - var index = parseInt( match, 10 ) - 1; + return message.replace( /(\\?\$\d+)/g, function ( str, match ) { + var index; - return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match; + if ( match[ 0 ] === '\\' ) { + // Escaped. + return match.slice( 1 ); + } + index = parseInt( match.slice( 1 ), 10 ) - 1; + return parameters[ index ] !== undefined ? parameters[ index ] : match; } ); }, diff --git a/test/i18n/test-en.json b/test/i18n/test-en.json index 0f65888..cf6844d 100644 --- a/test/i18n/test-en.json +++ b/test/i18n/test-en.json @@ -1,5 +1,6 @@ { "message_1": "ONE", "message_2": "TWO", - "message_3": "THREE" + "message_3": "THREE", + "message_4": "Total \\$1 of \\$1500" } diff --git a/test/jquery.i18n.test.js b/test/jquery.i18n.test.js index fe32b72..fa9284b 100644 --- a/test/jquery.i18n.test.js +++ b/test/jquery.i18n.test.js @@ -34,7 +34,7 @@ } } ); - QUnit.test( 'Message parse tests (en)', 14, function ( assert ) { + QUnit.test( 'Message parse tests (en)', 16, function ( assert ) { var pluralAndGenderMessage, pluralAndGenderMessageWithLessParaMS, pluralAndGenderMessageWithCase, @@ -49,6 +49,7 @@ QUnit.start(); assert.strictEqual( i18n.locale, 'en', 'Locale is English' ); assert.strictEqual( $.i18n( 'message_1' ), 'ONE', 'Simple message' ); + assert.strictEqual( $.i18n( 'message_4', 5 ), 'Total $1 of $1500', 'Parameter replacement escaped' ); } ); assert.strictEqual( $.i18n( 'This message key does not exist' ), @@ -56,6 +57,10 @@ 'This message key does not exist' ); assert.strictEqual( $.i18n( 'Hello $1', 'Bob' ), 'Hello Bob', 'Parameter replacement' ); + assert.strictEqual( + $.i18n( 'Price of {{PLURAL:$1|an item|$1 items}} is $2, you get \\$2 discount', 5, 2000 ), + 'Price of 5 items is 2000, you get $2 discount', 'Parameter replacement with dollar sign escaped, not parsed using simplePaser' + ); pluralAndGenderMessage = '$1 has $2 {{plural:$2|kitten|kittens}}. ' + '{{gender:$3|He|She}} loves to play with {{plural:$2|it|them}}.'; pluralAndGenderMessageWithLessParaMS = '$1 has $2 {{plural:$2|kitten}}. ' +