Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

numberFormat callback to format numbers #122

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,28 @@ polyglot.t("car", 2);
=> "2 cars"
```

If you pass a `numberFormat` _function_ to the constructor, Polyglot will use
it to translate interpolated `Number`s to `String`s. That's useful because
different locales have different rules for formatting numbers: `2,000.56` in
English versus `1 234,56` in French, for instance.

```js
polyglot = new Polyglot({
phrases: { num_cars: '%{smart_count} car |||| %{smart_count} cars' },
numberFormat: new Intl.NumberFormat('en').format // Chrome, Firefox, IE11+, Node 0.12+ with ICU
})
polyglot.t("num_cars", 2000); // internally, calls options.numberFormat.format(2000)
=> "2,000 cars"
```

(A primer on [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat)
in Node: Node 0.12+ comes with Intl as long as it's compiled with ICU (which is
the default). By default, the only locale Node supports is en-US. You can add
[full-icu](https://www.npmjs.com/package/full-icu) to your project to support
other locales. Finally, Polyglot accepts a _function_, not an Intl.NumberFormat
instance: if you have a NumberFormat instance, pass its `.format` property to
Polyglot.

If you like, you can provide a default value in case the phrase is missing.
Use the special option key "_" to specify a default.

Expand Down
13 changes: 10 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ var defaultTokenRegex = /%\{(.*?)\}/g;
//
// You should pass in a third argument, the locale, to specify the correct plural type.
// It defaults to `'en'` with 2 plural forms.
function transformPhrase(phrase, substitutions, locale, tokenRegex) {
function transformPhrase(phrase, substitutions, locale, tokenRegex, numberFormat) {
if (typeof phrase !== 'string') {
throw new TypeError('Polyglot.transformPhrase expects argument #1 to be string');
}
Expand All @@ -197,8 +197,14 @@ function transformPhrase(phrase, substitutions, locale, tokenRegex) {
// Interpolate: Creates a `RegExp` object for each interpolation placeholder.
result = replace.call(result, interpolationRegex, function (expression, argument) {
if (!has(options, argument) || options[argument] == null) { return expression; }

var replacement = options[argument];
if (typeof replacement === 'number' && typeof numberFormat === 'function') {
replacement = numberFormat(replacement);
}

// Ensure replacement value is escaped to prevent special $-prefixed regex replace tokens.
return replace.call(options[argument], dollarRegex, dollarBillsYall);
return replace.call(replacement, dollarRegex, dollarBillsYall);
});

return result;
Expand All @@ -214,6 +220,7 @@ function Polyglot(options) {
this.onMissingKey = typeof opts.onMissingKey === 'function' ? opts.onMissingKey : allowMissing;
this.warn = opts.warn || warn;
this.tokenRegex = constructTokenRegex(opts.interpolation);
this.numberFormat = opts.numberFormat || String;
}

// ### polyglot.locale([locale])
Expand Down Expand Up @@ -370,7 +377,7 @@ Polyglot.prototype.t = function (key, options) {
result = key;
}
if (typeof phrase === 'string') {
result = transformPhrase(phrase, opts, this.currentLocale, this.tokenRegex);
result = transformPhrase(phrase, opts, this.currentLocale, this.tokenRegex, this.numberFormat);
}
return result;
};
Expand Down
13 changes: 12 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ describe('t', function () {
hello: 'Hello',
hi_name_welcome_to_place: 'Hi, %{name}, welcome to %{place}!',
name_your_name_is_name: '%{name}, your name is %{name}!',
empty_string: ''
empty_string: '',
number: '%{number}'
};

var polyglot;
Expand Down Expand Up @@ -156,6 +157,16 @@ describe('t', function () {
instance.t(missingKey);
});
});

it('uses numberFormat', function () {
var instance = new Polyglot({
phrases: phrases,
// prove we're passed a Number by doing math on it and formatting it
numberFormat: function (n) { return 'x' + (n + 2); }
});

expect(instance.t('number', { number: 1234.56 })).to.equal('x1236.56');
});
});

describe('pluralize', function () {
Expand Down