-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Date and number localization #2207
Conversation
src/core.js
Outdated
exports.register([ | ||
require('./locale-en'), | ||
require('./locale-en-US') | ||
]); |
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.
🎩 bundle_tests/core_test
🌟
Since we're constructing our own d3.locale
now no matter what, locale-en
needs to be part of the core so it can be used as the fallback for missing pieces of other locales. Then for simplicity I moved the default locale-en-US
to the core as well, which has the nice side-effect of keeping these redundant locales out of dist/
.
@etpinard seem reasonable? Are you OK with putting these two in the root src/
directory? At least as long as we're not going to put any other locales into the core it doesn't seem like they warrant their own directory.
Minor downside is the lib/index*
files don't demonstrate how to register locales, but we should be able to to better than documenting it there anyhow - somewhere we will want examples of how to use locales both in the build process and via script tags.
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.
@etpinard seem reasonable?
This is very reasonable 👌
but we should be able to to better than documenting it there anyhow
Yep, we should at least open up an issue on https://github.com/plotly/documentation/issues and / or add a Locale section to dist/README.md
via tasks/stats.js
.
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.
updated dist/README.md
-> 331b2da
will open an issue at https://github.com/plotly/documentation once this is merged.
var yearFormatD3 = '%Y'; | ||
var monthFormatD3 = '%b %Y'; | ||
var dayFormatD3 = '%b %-d'; | ||
var yearMonthDayFormatD3 = '%b %-d, %Y'; |
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.
This is for our default, adaptive date labels. I'm not too worried about it, as these formats are at least unambiguous. But it shouldn't be too hard to allow these to be localized too, essentially as an extension to the d3.locale
format objects, should our international users feel strongly about it (and contribute their own alternative format strings).
src/plot_api/plot_config.js
Outdated
// Unlike d3.locale, every key is optional, we will fall back on English ('en'). | ||
// Currently `grouping` and `currency` are ignored for our automatic number | ||
// formatting, but can be used in custom formats. | ||
formats: {} |
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 suppose we could combine these into one, so context looks more like the register-able locale modules. I didn't do that because I wanted to preserve compatibility with #2195 but that hasn't been released to npm yet so we can change it if we want. Thoughts?
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.
So, dictionaries
+ formats
would become locale
as config argument?
If so, I'd vote 👍 for consistency with what Plotly.register
expects.
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.
... and don't worry about breaking things that haven't been released 😉
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.
combined dictionaries
+ formats
-> locales
in 27037af
src/plots/cartesian/set_convert.js
Outdated
@@ -447,9 +447,19 @@ module.exports = function setConvert(ax, fullLayout) { | |||
ax._min = []; | |||
ax._max = []; | |||
|
|||
// copy ref to fullLayout.separators so that | |||
// Fropagate localization into the axis so that |
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 love to Fropagate whenever I can ;)
src/core.js
Outdated
@@ -68,7 +68,7 @@ exports.register([ | |||
// locales en and en-US are required for default behavior | |||
exports.register([ | |||
require('./locale-en'), | |||
require('./locale-en-US') | |||
require('./locale-en-us') |
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.
how did this not fail for me locally but only on CI?
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 a check for case correctness of all the requires 43b73e0
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.
Looking great. 🎉
Using d3.locale
is definitively the cleanest way to do this. Its v4 module d3-time-format
doesn't look too bloated, so this looks like the right way going forward even when we'll update to d3 v4.
Fixes #1264 - and incidentally
I didn't see a new test case for this specifically, would you mind adding one if you haven't already?
Finally about
Now that we have these localization skeletons we can encourage community members to fill in the rest, and even add more.
I'm thinking we should make a pinned post on https://community.plot.ly/ like @chriddyp did to advertise the Dash workshops to attract potential contributors.
locale = baseLocale; | ||
} | ||
|
||
// lastly pick out defaults from english (non-US, as DMY is so much more common) |
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 strongly agree with picking en
(not en-us
) as our default 👌
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.
picking
en
(noten-us
) as our default
OK, so what we're doing right now is a bit schizophrenic, but it has a certain logic to it: en-US
is the default locale, but if you specify a different locale and it has an incomplete definition (After potentially combining the region and language definitions), it will fill in with non-translated strings (for which we've use US english, en-US
) but en
for the missing formatting fields. But the ONLY difference between en
and en-US
formatting is if you make a custom tickformat
with %x
(and possibly %c
) in it - you get DD/MM/YYYY format from en
vs MM/DD/YYYY from en-US
. Seemed to me that since the US is about the only country in the world that uses the utterly nonsensical MM/DD/YYYY format, if you've already said you're not in the US we shouldn't fall back on that.
For strings, the only place non-translated is different is different is color/colour. I guess I don't care much about that, it currently only shows up in "Click to enter Colo(u)rscale title," and I see no legitimate reason to give an incomplete set of string translations unless you're in another english region (in which case en
is part of the inheritance chain anyway so you'll get your silly extra "u")
Any quibbles with that logic?
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.
Any quibbles with that logic?
None from me 👌
/** | ||
* getFormatter: combine the final separators with the locale formatting object | ||
* we pulled earlier to generate number and time formatters | ||
* TODO: remove separators in v2, only use locale, so we don't need this step? |
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'm in strong agreement here 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.
Don't forget to add it #420 🚬
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.
That said, I just remembered that someone (in #1842) has asked for per-axis separators
settings. I didn't really understand that person's use case though. Personally, I think separators
are better served as locale/context options, but maybe I'm wrong.
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 #420 (comment)
That said, I just remembered that someone (in #1842) has asked for per-axis separators settings.
commented over there #1842 (comment)
@@ -328,23 +329,38 @@ function getTraceType(traceType) { | |||
* the dictionary mapping input strings to localized strings | |||
* generally the keys should be the literal input strings, but | |||
* if default translations are provided you can use any string as a key. | |||
* @param {object} module.format | |||
* a `d3.locale` format specifier for this locale | |||
* any omitted keys we'll fall back on en-US |
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.
Hmm. Isn't the fallback en
?
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.
to be precise, we'll fall back on no translation (which means en-US
) - more detail #2207 (comment)
tasks/pull_date_format.js
Outdated
var argLocale = args[0]; | ||
|
||
var pathToEn = path.join(constants.pathToLib, 'locale-en.js'); | ||
var pathToWCRegions = path.join(__dirname, '../node_modules/world-calendars/dist/regional'); |
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.
path.join(require.resolve('world-calendars'), 'dist', 'regional')
would be a bit more robust
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.
Neat, I didn't know about require.resolve
- took a little fiddling but -> d0e0158
.replace(/'/g, '\\\'') // escape single quotes | ||
.replace(/"([A-Za-z]\w+)":/g, '$1:') // unquote simple identifier keys | ||
.replace(/([^\\])"/g, '$1\'') // replace unescaped doublequotes with singlequotes | ||
.replace(/\\"/g, '"'); // unescape escaped doublequotes |
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.
Nasty. That most have been painful to do. 👏
src/plots/cartesian/set_convert.js
Outdated
@@ -447,7 +447,7 @@ module.exports = function setConvert(ax, fullLayout) { | |||
ax._min = []; | |||
ax._max = []; | |||
|
|||
// Fropagate localization into the axis so that | |||
// Propagate localization into the axis so that |
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.
👍
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', | ||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' | ||
], | ||
periods: ['AM', 'PM'], |
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'm curious here. Do locales w/o periods
set fallback to using a 24-hour clock?
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.
periods
is only relevant if you use %p
(and %I
for 12-hour hours) in a custom format, our standard formatting always uses a 24-hour clock. Locales that don't define periods
will inherit ['AM', 'PM']
from en
. Seems like most places don't care about this, and some that do are still OK with AM/PM (since it's latin anyway).
@@ -29,7 +29,6 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode, hoverLay | |||
zmask = cd0.zmask, | |||
range = [trace.zmin, trace.zmax], | |||
zhoverformat = trace.zhoverformat, | |||
_separators = trace._separators, |
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.
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.
🔪 trace._separators
in 592fc9e
src/plot_api/plot_config.js
Outdated
// Unlike d3.locale, every key is optional, we will fall back on English ('en'). | ||
// Currently `grouping` and `currency` are ignored for our automatic number | ||
// formatting, but can be used in custom formats. | ||
formats: {} |
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.
So, dictionaries
+ formats
would become locale
as config argument?
If so, I'd vote 👍 for consistency with what Plotly.register
expects.
src/plot_api/plot_config.js
Outdated
// Unlike d3.locale, every key is optional, we will fall back on English ('en'). | ||
// Currently `grouping` and `currency` are ignored for our automatic number | ||
// formatting, but can be used in custom formats. | ||
formats: {} |
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.
... and don't worry about breaking things that haven't been released 😉
in both registry (they were already combined in the API just not under the hood) and in config (where you were required to split them out yourself previously)
dist will stay flat, to make script and CDN use consistent
That's a great idea - wait until this is published ( |
Amazing PR 💃 |
Don't forget to either close (or update with remaining open items) #856 after merging. |
d3.locale
formatworld-calendars
lib
and as standalone scripts indist
, as started by Localization #2195.world-calendars
does have a few of these, but mostly these calendars are only in use in one region and are already localized to this region. If there is a need we can address this later.d3.locale
is not available inworld-calendars
: AM/PM translations (theperiod
field),dateTime
andtime
format fields (only relevant for custom formats anyway so this doesn't seem like a big deal) and, most importantly, number formatting (decimal
andthousands
, we only have partial support forgroupings
andcurrency
right now but they should be included too if they're different from English). Now that we have these localization skeletons we can encourage community members to fill in the rest, and even add more.layout.separators
altogether and only using locales.cc @etpinard @VeraZab