Skip to content

Commit

Permalink
Merge pull request silverstripe#3180 from colymba/i18n-js-injection-fix
Browse files Browse the repository at this point in the history
API New i18n JS sprintf and inject replacement functions
  • Loading branch information
simonwelsh committed Aug 7, 2014
2 parents 5283700 + 8fb5e9c commit 9b8d07c
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 34 deletions.
23 changes: 21 additions & 2 deletions docs/en/topics/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,16 @@ format which can be processed more easily by external translation providers (see
alert(ss.i18n._t('MYMODULE.MYENTITY'));


### Advanced Usage with sprintf()
### Advanced Use

The `ss.i18n` object contain a couple functions to help and replace dynamic variable from within a string.

#### Legacy sequential replacement with sprintf()

`sprintf()` will substitute occurencies of `%s` in the main string with each of the following arguments passed to the function. The substitution is done sequentially.

:::js
// MYMODULE.MYENTITY contains "Really delete %s articles by %s authors?"
// MYMODULE.MYENTITY contains "Really delete %s articles by %s?"
alert(ss.i18n.sprintf(
ss.i18n._t('MYMODULE.MYENTITY'),
42,
Expand All @@ -387,6 +393,19 @@ format which can be processed more easily by external translation providers (see
// Displays: "Really delete 42 articles by Douglas Adams?"


#### Variable injection with inject()

`inject()` will substitute variables in the main string like `{myVar}` by the keys in the object passed as second argument. Each variable can be in any order and appear multiple times.

:::js
// MYMODULE.MYENTITY contains "Really delete {count} articles by {author}?"
alert(ss.i18n.inject(
ss.i18n._t('MYMODULE.MYENTITY'),
{count: 42, author: 'Douglas Adams'}
));
// Displays: "Really delete 42 articles by Douglas Adams?"


## Limitations

* No detecting/conversion of character encodings (we rely fully on UTF-8)
Expand Down
59 changes: 38 additions & 21 deletions javascript/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,33 +138,50 @@ ss.i18n = {
return stripStr(parts.join(" "));
},

/*
* printf()
* C-printf like function, which substitutes %s with parameters
* given in list. %%s is used to escape %s.
*
* Doesn't work in IE5.0 (splice)
*
* @param string S : string to perform printf on.
* @param string L : Array of arguments for printf()
*/
/**
* Substitutes %s with parameters
* given in list. %%s is used to escape %s.
*
* @param string S : The string to perform the substitutions on.
* @return string The new string with substitutions made
*/
sprintf: function(S) {
if (arguments.length == 1) return S;

var nS = "";
var tS = S.split("%s");

var args = [];
for (var i=1, len = arguments.length; i <len; ++i) {
var args = [],
len = arguments.length,
index = 0,
regx = new RegExp('(.?)(%s)', 'g'),
result;

for (var i=1; i<len; ++i) {
args.push(arguments[i]);
};

for(var i=0; i<args.length; i++) {
if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != args.length-1)
tS[i] += "s"+tS.splice(i+1,1)[0];
nS += tS[i] + args[i];
}
return nS + tS[tS.length-1];
result = S.replace(regx, function(match, subMatch1, subMatch2, offset, string){
if (subMatch1 == '%') return match; // skip %%s
return subMatch1 + args[index++];
});

return result;
},

/**
* Substitutes variables with a list of injections.
*
* @param string S : The string to perform the substitutions on.
* @param object map : An object with the substitions map e.g. {var: value}
* @return string The new string with substitutions made
*/
inject: function(S, map) {
var regx = new RegExp("\{([A-Za-z0-9_]*)\}", "g"),
result;

result = S.replace(regx, function(match, key, offset, string){
return (map[key]) ? map[key] : match;
});

return result;
},

/**
Expand Down
35 changes: 24 additions & 11 deletions javascript/i18nx.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,33 @@ ss.i18n = {
sprintf: function(S) {
if (arguments.length == 1) return S;

var nS = "";
var tS = S.split("%s");

var args = [];
for (var i=1, len = arguments.length; i <len; ++i) {
var args = [],
len = arguments.length,
index = 0,
regx = new RegExp('(.?)(%s)', 'g'),
result;

for (var i=1; i<len; ++i) {
args.push(arguments[i]);
};

for(var i=0; i<args.length; i++) {
if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != args.length-1)
tS[i] += "s"+tS.splice(i+1,1)[0];
nS += tS[i] + args[i];
}
return nS + tS[tS.length-1];
result = S.replace(regx, function(match, subMatch1, subMatch2, offset, string){
if (subMatch1 == '%') return match; // skip %%s
return subMatch1 + args[index++];
});

return result;
},

inject: function(S, map) {
var regx = new RegExp("\{([A-Za-z0-9_]*)\}", "g"),
result;

result = S.replace(regx, function(match, key, offset, string){
return (map[key]) ? map[key] : match;
});

return result;
},

// stub methods
Expand Down

0 comments on commit 9b8d07c

Please sign in to comment.