-
-
Notifications
You must be signed in to change notification settings - Fork 83
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
Add locale
option
#39
Conversation
index.js
Outdated
@@ -17,7 +17,7 @@ module.exports = num => { | |||
} | |||
|
|||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1); | |||
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3)); | |||
const numStr = (num / Math.pow(1000, exponent)).toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just use argument-less .toLocaleString()
which will automatically format in the user's current locale, which I think is what 99% of users want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, keep the Number()
.
index.js
Outdated
@@ -1,7 +1,7 @@ | |||
'use strict'; | |||
const UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | |||
|
|||
module.exports = num => { | |||
module.exports = (num, locale = undefined) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I imagined a boolean option like localize
which enables .toLocaleString()
. I'd say default it to false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to pass the locale, because I need to enable the user to change the language during runtime in my ionic-app.
What do you think about using your approach (boolean option localize
, default to false
) plus adding an option to set the locale
to use in case of localize
? (This is how moment.js does it)
Example for default locale de
:
> prettybytes(1230000);
1.23 MB
> prettybytes(1230000, true); // Default system locale 'de' is used
1,23 MB
> prettybytes.locale('rn'); // Changes the locale for all subsequent calls with localize = true;
> prettybytes(1230000, true): // Locale 'rn' is used
1.23 MB
Just to make xo linter happy :)
Some tests failed indicating, that no minimumFractionDigits are wanted. E.g.: 10.1 should be 10.1 and not 10.10
Node 4 doesn't support them (Travis CI build failed because of that). Default value isn't needed though, because checking for localize should work nevertheless. E.g.: - undefined == true => false - false == true => false - 0 == true => false - true == true => true - 1 == true => true
index.js
Outdated
@@ -1,7 +1,7 @@ | |||
'use strict'; | |||
const UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | |||
|
|||
module.exports = num => { | |||
module.exports = (num, localize) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to mention this last time, but could you make an option object as the second argument, e.g. {localize: true}
.
LGTM once the option object is in. I think we can also do some unit tests for various locales (have to verify they work on Travis), but I can add those after merging this one. |
Added an options object. In my case I need to pass in the locale-key as I change the language during runtime in an app using Ionic. Any chance to add this in another PR later on? |
index.js
Outdated
@@ -17,7 +17,8 @@ module.exports = num => { | |||
} | |||
|
|||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1); | |||
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3)); | |||
const numTmp = Number((num / Math.pow(1000, exponent)).toPrecision(3)); | |||
const numStr = options && options.localize ? numTmp.toLocaleString() : numTmp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do options = Object.assign({}, options)
after the Number.isFinite(num)
if statement at the start of the function. This ensures that options
is an object too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that Object.assign
required Node.js 5 or greater which breaks compatibilty on the current minimum version 4. I'd just to opts = opts || {}
on the start of the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@silverwind Object.assign
is supported on Node.js 4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, you're right, carry on. (I was misinterpreting http://node.green/)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late reply. You're right. Using object.assign
is way better than checking for undefined on each use. I'll add this.
Then let's change the option name to |
That would be a good solution for me. Thanks. I will add it. |
Don't check options on each use. Check it at the beginning of the method instead.
If locale = true => localize using the default locale If locale = string => the value is expected to be a locale-key-string and is used as parameter for toLocaleString(..)
...and use single quoted string. To pass linter checks
Removed separate check of options.local. typeof has no problems with undefined-arguments
@kevva Are you fine with the changes? |
I'm fine with the change, but it needs docs and tests. See https://github.com/sindresorhus/boxen#api for how to format the docs. |
OK I'll look into that. |
Don't know, how that got into the code :)
This should fix the failing test `localized output`
Added those lines, but it still isn't working (same error during test-execution). |
I assume Travis installed the official Node.js packages, so I checked them in both Ubuntu 14.04 and 16.04 and I discovered that both are actually built with before_install:
- npm install full-icu
env:
- NODE_ICU_DATA=node_modules/full-icu You're still missing a option description in |
Hm.. the environment is set before installing the npm package and with the variable set, installing seems to error out. (https://travis-ci.org/sindresorhus/pretty-bytes/jobs/319039889) |
There's no |
because there is no after_install step :)
Ah, it finally passed. Can you document the new option in the README and add a note that users may need to install the |
You were right.. there is no `after_install. Ouch. Thanks for the hint on this :) |
index.js
Outdated
const neg = num < 0; | ||
|
||
if (neg) { | ||
num = -num; | ||
} | ||
|
||
if (num < 1) { | ||
num = toLocaleString(num, options.locale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very minor, but I'd declare let numStr
earlier and then assign it here, making it clearer that num
is always a number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Also changed line 24, where the result is always a number and not a numStr
readme.md
Outdated
|
||
**Note:** Localization should generally work in browsers. Node-Users have to ensure, there Node version has [full ICU-Support](https://github.com/nodejs/node/wiki/Intl): | ||
- if your using linux, node should be able to link to the installed system-icu automatically | ||
- or you install the [full-icu-package](https://github.com/unicode-org/full-icu-npm) and set the environment variable [NODE-ICU-DATA](https://github.com/nodejs/node/wiki/Intl#using-and-customizing-the-small-icu-build) to `node_modules/full-icu` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not entirely true that all node versions need the module. The Node.js on macOS' homebrew for example comes built with system-icu
. I'd word it like this:
Localization should generally work in browsers. Node.js needs to be built with
full-icu
orsystem-icu
. Alternatively, the full-icu module can be used to provide support at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added your wording.
LGTM, this should be ready to merge, @sindresorhus. |
It would be nice, if you could merge this. If something is missing, I'm happy to add/fix it. |
ping @sindresorhus and @kevva. |
re-ping @sindresorhus and @kevva :) |
index.js
Outdated
if (num < 1) { | ||
return (neg ? '-' : '') + num + ' B'; | ||
numStr = toLocaleString(num, options.locale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const numStr = toLocaleString(num, options.locale);
index.js
Outdated
} | ||
|
||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1); | ||
const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3)); | ||
num = Number((num / Math.pow(1000, exponent)).toPrecision(3)); | ||
numStr = toLocaleString(num, options.locale); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const numStr = toLocaleString(num, options.locale);
index.js
Outdated
/** | ||
* Formats the given number using number.toLocaleString(..). | ||
* If locale is a string, the value is expected to be a locale-key (e.g. 'de'). | ||
* If locale is true or 1, the system default locale is used for translation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If locale is true or 1
Should only be when it's true
.
index.js
Outdated
let result = num; | ||
if (typeof locale === 'string') { | ||
result = num.toLocaleString(locale); | ||
} else if (locale) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else if (locale === true) {
@sindresorhus: Thanks for your feedback. I agree with the requested changes and added them to the PR. |
@sindresorhus and @kevva: Can you merge this please? If something is missing, I'm happy to fix things |
Can this be merged please? I would like to remove my forked version from my project. |
Not sure what the holdup here is. One suggestion for the Oh, and you could make sure that environment variable is set during These two changes should make the adjustments in |
Just time. I have over 300 PRs to review…
I don't want it under |
That is ok.. Just thought, this PR has been forgotten. |
Hmm okay. We should still have it in devDependencies so tests pass unconditionally. On the topic of ICU, I meant to do some research on the binary sizes and propose building Node.js with full ICU by default, so hopefully this dependency won't be required some day. Edit: see nodejs/node#19214 |
This is meant to close #4 (I copied the parameters for .toLocaleString(..) from @silverwind , who opened the issue)
Uses
.toLocaleString(...)
to create the human readable strings for a locale.Specifying the locale is optional.
If ommited, the default language will be used.
Please add your thoughts on this. It was only a first shot.