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
Allow multiple locales. #1652
Allow multiple locales. #1652
Conversation
Mike, thanks for taking a shot at this. I'll haven't played around with the branch yet, but the direction you are going to seems right to me. Can you give a quick example how to register a locale at runtime with this? Statically loading a js file after d3 has been loaded would be fine for us (similar to what moment.js is doing), however it would be interesting to see if we could generate a d3 locale object from a Globalize.js culture. By the way, we noticed that d3_time_scaleLocalFormats is not using localized format strings. For example, formatting times as "%I %p" is rather US-specific. Is this something you'd rather tackle in this branch, or should I create an independent bug report against master? |
Fixes #750. This isn’t the final implementation, but more of a proof of concept demonstrating how to scope any code that requires localization within a closure that has access to locale-specific variables. In the next pass, I can go through this implementation and more cleanly separate locale-dependent from locale- independent code, and only put locale-dependent code within the closure. Also, we may want to use an options object rather than passing a zillion arguments to d3.locale, because a many-argument method is hard to use and may make it harder to extend the API in the future. This commit also breaks the ability to change the default locale during the build process, but this should be easy to restore.
var russian = d3.locale({
decimal: ",",
thousands: " ",
grouping: [3, 3],
currency: ["", " руб."],
dateTime: "%A, %e %B %Y г. %X",
date: "%d.%m.%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"],
shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"],
months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"],
shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]
}); Then: russian.numberFormat("$,.2f")(1234567.89); // "1 234 567,89 руб." Note that this doesn’t affect the behavior of the default d3.format: d3.format("$,.2f")(1234567.89) // "$1,234,567.89" Edit: this also demonstrates that the currency formatter is now smart enough to put the currency symbol after the number when desired. |
@rbu If you are pulling in Globalize.js already, wouldn’t you just use Globalize.js to do the number and time formatting? What would be the benefit of creating a d3.locale object from that, given that Globalize.js already provides number and date formatters? For the U.S.-centric default implementation of locale.timeScaleFormat, I’m not sure what the best solution is here. If you want different behavior, it probably makes more sense to just define your own time format, as in the custom time format example. So by that argument I think I’ll remove the locale.timeScaleFormat, since it’s not properly localized anyway. |
It wasn’t really localized anyway, since the set of format strings weren’t really locale-independent. A better way of localizing this format is to implement a custom time format using locale.timeFormat, as in the custom time format example: http://bl.ocks.org/mbostock/4149176
Given an array of format strings and corresponding predicate functions, returns a time format function that tests the input date against each predicate function, using the first format that returns true.
This commit allows the currency symbol to appear either at the beginning or end (or both, but that should be rare).
Mike, in your russian example you have
I prefer |
Can use |
Folded into #1690. |
(In practice I think it might be preferable to use white-space: nowrap rather than hard-coding this behavior into the locale, but maybe either is okay.) |
|
Works for me, e.g. http://bl.ocks.org/mbostock/4149176. |
@jasondavies cool, I's using the older d3. thanks |
Does anybody have any examples of how to change locales on the fly using the D3 library? Still not clear if this is possible with D3, or if we need a custom solution. |
d3.locale was added in version 3.4. |
@mbostock, sorry for dropping the ball earlier. The reason would be that we can still use the d3 api. I assume the time and number formatters are also used internally when creating an axis, for example. |
I'm tryin to wrap my head around this. Does anyone have an example, say, on how to apply d3.locale to a bar chart to change dot-separated decimals to comma? This would go a long way to help understand how to use it in the most common scenarios. |
Here's how it works e.g. for spanish var ES = d3.locale({
see here for options see it in action here |
Thank you, wahlatlas! It works beautifully. I implemented it today in my app and it saved me a lot of trouble. Thank you Mike for this wonderful functionality. I use more and more D3 now. |
Fixes #750. Code that requires localization is now within a closure that has access to locale-specific strings.
To minimize the degree of isolation required, d3.scale.linear (and other quantitative scales, including d3.time.scale) still default to the en-US locale. However, you can create your own localized formats using locale.numberFormat and locale.timeFormat.
(It would be possible to move these other classes to within d3.locale as well, but that would mean anything that depends on d3.scale.linear would also need to be moved within d3.locale, such as d3.svg.axis. I think it’s cleaner to leave them using a default locale rather and have people localize the formats explicitly, rather than classes that localize anything downstream; you can always reassign d3.format to a different locale if you want to change the default.)
Also introduces locale.timeFormat.multi which can be used to create a multi-scale time format, and improves currency formatting by allowing the currency symbol to appear after the numeric value.