d3 / d3-format

Format numbers for human consumption.
https://d3js.org/d3-format
ISC License
625 stars 103 forks source link

Adding Numeral system to locales #40

Closed Ashamandi closed 7 years ago

Ashamandi commented 7 years ago

As D3 supports different locales, we need also to add numeral system to these locales

When users select a locale file they also expect to see numbers formated in a numeral system based on the selected locale.

for example: if we talk about users from saudi arabia, when they select ar-SA as their locale file, they expect to see arabic/ indic numerals - ٠١٢٣٤٥٦٧٨٩ - instead of European numerals - 0123456789 - . on the other hand users from Tunisia, when selecting ar-TN, they expect to see European numerals

and to solve this problem, I suggest to

  1. Add numeral parameter at each locale.json file to define which numeral system this locale supports.

numeric1

numeric2

  1. Add the next function to locale.js file to formatNumerals numeric3

  2. then call it immediately before adding padding, valuePrefix @ newFormat function as follows: numeric4

and for now as I am interesting to support Arabic users I will add one of 2 numerals types (European or arabic/indic) at each locale. (ar-*.json) and for the remaining locales I will define numerals as european numerals.

mbostock commented 7 years ago
  1. This will be slow for the common case where it does nothing. If we support this, we should special-case where the local’s numerals definition is null or undefined and have formatNumeral be the identity function.

  2. By defining numerals as a string, you’re limiting them to the basic multilingual plane because JavaScript strings are indexed as UTF-16 (or UCS-2?) characters. See JavaScript has a Unicode problem. You probably want to allow each numeral to be represented as a grapheme cluster instead, or in other words, define numerals as an array of strings rather than a string of characters. Admittedly this might be overkill but I don’t see any harm in adopting the more general representation.

  3. Shouldn’t the padding and valuePrefix also be included in the substitution? I’m not sure if zero-padding is typically used in other locales but I think it’d be weird to mix the ASCII zero (0) with other numerals.

  4. You probably want to optimize your formatNumeral implementation using string.replace like so:

function numeralReplacer(numerals) {
  function replace(i) {
    return numerals[+i];
  }
  return function(string) {
    return string.replace(/[0-9]/g, replace);
  };
}

var numeralIndia = numeralReplacer(["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"]);

numeralIndia("1,234.56"); // "۱,۲۳۴.۵۶"

More generally, I worry that this little library won‘t do enough to support other locales, and it might be better to encourage people to use a different, more full-featured, library such as jQuery Globalize. Globalize appears to support this feature already, for instance.

Ashamandi commented 7 years ago

Ok, I agree with you, we can

  1. Add numerals at needed locale files only.

numeric1

  1. Add a condition before calling numeralReplacer function to check if there is numerals value or not

  2. If numerals not equal null, we can safely call numeralReplacer.

numeric2

And for Arabic locales, zero padding will not be used but I haven`t problem to include it if we take into our consideration the other numeral system.

More generally, I worry that this little library won‘t do enough to support other locales, and it might be better to encourage people to use a different, more full-featured, library such as jQuery Globalize. Globalize appears to support this feature already, for instance.

Supporting Arabic/Indic numerals in D3.format will be very important for us at IBM, as a Globalization team at IBM Egypt one of our tasks is supporting the open source technologies that IBM products use with globalize and bidi features to full fill its gap in Arabic area.

And as D3 is used by tools that IBM products use, we need to support it with the missing bidi features like Arabic locales, Arabic/indic numeral system, hijri calendar for date formatting, which are considered very important for Arabic countries to meet their expectations in visualizing their data with Arabic/Indic numerals and their dates at hijri date format and to achieve that we highly need to support the numeral system here and hijri calendar at D3.time and arabic locales at d3.time.format.

All of these features when compaining with each others will produce understandable and readable data for arabic users.

mbostock commented 7 years ago

And as D3 is used by tools that IBM products use, we need to support it with the missing bidi features like Arabic locales, Arabic/indic numeral system, hijri calendar for date formatting, …

Yes. My point was only that you can use D3 with other number and date formatters. The d3-format and d3-time-format are provided by default, but there’s no reason you can’t also (or instead) use jQuery Globalize, Moment, or another library, passing in the appropriate function to axis.tickFormat or wherever else you need localization.

Anyway, the numeral replacer seems easy enough.

mbostock commented 7 years ago

Fixed in #41; released in 1.1.0. Thank you!