Skip to content

Commit 1d17794

Browse files
committed
Automatically format interpolated numbers, fixes CNVS-34757
On the front-end, automatically localize numbers that are part of a localized string even if the developer has forgotten to do so explicitly. We already did this for the %{count} placeholder, now do it for any interpolated number. Any explicitly localized numbers will be unaffected. This makes localizing numbers in handlebars-land a lot easier, e.g. just do: {{#t}}User count: {{num}}{{/t}} Test plan: * Confirm localization works as per usual * Confirm this new behavior works in places where we don't explicitly localize the number, e.g. set a group's max membership to 1000, and confirm this string has "1,000" in the UI: "%{member_count} members out of maximum of %{max_membership}" Change-Id: I388407fbccb04a26e7da7e3ec82b68ce9f5985f9 Reviewed-on: https://gerrit.instructure.com/101076 Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> Tested-by: Jenkins QA-Review: Cemal Aktas <caktas@instructure.com> Product-Review: Jon Jensen <jon@instructure.com>
1 parent 9fad40e commit 1d17794

2 files changed

Lines changed: 37 additions & 2 deletions

File tree

public/javascripts/i18nObj.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ define([
77
'vendor/date' /* Date.parse, Date.UTC */
88
], function(I18n, $, _, htmlEscape, i18nLolcalize) {
99

10+
/*
11+
* Overridden interpolator that localizes any interpolated numbers.
12+
* Defaults to localizeNumber behavior (precision 9, but strips
13+
* insignificant digits). If you want a different format, do it
14+
* before you interpolate.
15+
*/
16+
var interpolate = I18n.interpolate;
17+
I18n.interpolate = function(message, origOptions) {
18+
var options = $.extend(true, {}, origOptions);
19+
var matches = message.match(this.PLACEHOLDER) || [];
20+
21+
var placeholder, name;
22+
23+
for (var i = 0; placeholder = matches[i]; i++) {
24+
name = placeholder.replace(this.PLACEHOLDER, '$1');
25+
if (typeof options[name] === 'number') {
26+
options[name] = this.localizeNumber(options[name]);
27+
}
28+
}
29+
return interpolate.call(this, message, options);
30+
};
31+
1032
I18n.locale = document.documentElement.getAttribute('lang');
1133

1234
I18n.lookup = function(scope, options) {
@@ -211,6 +233,7 @@ I18n.strftime = function(date, format) {
211233
return f;
212234
};
213235

236+
// like the original, except it formats count
214237
I18n.pluralize = function(count, scope, options) {
215238
var translation;
216239

@@ -229,8 +252,8 @@ I18n.pluralize = function(count, scope, options) {
229252
switch(Math.abs(count)) {
230253
case 0:
231254
message = this.isValidNode(translation, "zero") ? translation.zero :
232-
this.isValidNode(translation, "none") ? translation.none :
233-
this.isValidNode(translation, "other") ? translation.other :
255+
this.isValidNode(translation, "none") ? translation.none :
256+
this.isValidNode(translation, "other") ? translation.other :
234257
this.missingTranslation(scope, "zero");
235258
break;
236259
case 1:

spec/coffeescripts/i18nSpec.coffee

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ define [
1010

1111
scope = I18n.scoped('foo')
1212
t = (args...) -> scope.t(args...)
13+
interpolate = (args...) -> I18n.interpolate(args...)
1314

1415
QUnit.module "I18n",
1516
setup: ->
@@ -77,6 +78,17 @@ define [
7778
equal t('bar', 'you need to *log in*', {wrapper: '<a href="%{url}">$1</a>', url: 'http://foo.bar'}),
7879
'you need to <a href="http://foo.bar">log in</a>'
7980

81+
test "interpolate: should format numbers", ->
82+
equal interpolate("user count: %{foo}", {foo: 1500}), "user count: 1,500"
83+
84+
test "interpolate: should not format numbery strings", ->
85+
equal interpolate("user count: %{foo}", {foo: "1500"}), "user count: 1500"
86+
87+
test "interpolate: should not mutate the options", ->
88+
options = {foo: 1500}
89+
interpolate("user count: %{foo}", options)
90+
equal options.foo, 1500
91+
8092
test "pluralize: should format the number", ->
8193
equal t({one: "1 thing", other: "%{count} things"}, {count: 1500}), '1,500 things'
8294

0 commit comments

Comments
 (0)