Skip to content

Commit fc86bdb

Browse files
Localize auto-formatted x-axis date ticks
1 parent e341edd commit fc86bdb

File tree

6 files changed

+62
-35
lines changed

6 files changed

+62
-35
lines changed

lib/locales/fr.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ module.exports = {
2323
'Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Jun',
2424
'Jul', 'Aoû', 'Sep', 'Oct', 'Nov', 'Déc'
2525
],
26-
date: '%d/%m/%Y'
26+
date: '%d/%m/%Y',
27+
year: '%Y',
28+
month: '%b %Y',
29+
dayMonth: '%e %b',
30+
dayMonthYear: '%e %b %Y'
2731
}
2832
};

src/lib/dates.js

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -433,17 +433,27 @@ function formatTime(x, tr) {
433433
return timeStr;
434434
}
435435

436-
// TODO: do these strings need to be localized?
437-
// ie this gives "Dec 13, 2017" but some languages may want eg "13-Dec 2017"
438-
var yearFormatD3 = '%Y';
439-
var monthFormatD3 = '%b %Y';
440-
var dayFormatD3 = '%b %-d';
441-
var yearMonthDayFormatD3 = '%b %-d, %Y';
442-
443-
function yearFormatWorld(cDate) { return cDate.formatDate('yyyy'); }
444-
function monthFormatWorld(cDate) { return cDate.formatDate('M yyyy'); }
445-
function dayFormatWorld(cDate) { return cDate.formatDate('M d'); }
446-
function yearMonthDayFormatWorld(cDate) { return cDate.formatDate('M d, yyyy'); }
436+
/*
437+
* formatWorld: format a calendar date using the d3 format syntax.
438+
*
439+
* cDate: the date to format
440+
* d3Format: the d3 format
441+
*
442+
* returns the formatted date
443+
*/
444+
function formatWorld(cDate, d3Format) {
445+
var d3ToC = [
446+
{d3: '%Y', c: 'yyyy'},
447+
{d3: '%b', c: 'M'},
448+
{d3: '%-d', c: 'd'},
449+
{d3: '%e', c: 'd'}
450+
];
451+
var calendarFormat = d3Format;
452+
for (var i = 0; i < d3ToC.length; i++) {
453+
calendarFormat = calendarFormat.replace(new RegExp(d3ToC[i].d3,"g"), d3ToC[i].c);
454+
}
455+
return cDate.formatDate(calendarFormat);
456+
}
447457

448458
/*
449459
* formatDate: turn a date into tick or hover label text.
@@ -462,7 +472,7 @@ function yearMonthDayFormatWorld(cDate) { return cDate.formatDate('M d, yyyy');
462472
* the axis may choose to strip things after it when they don't change from
463473
* one tick to the next (as it does with automatic formatting)
464474
*/
465-
exports.formatDate = function(x, fmt, tr, formatter, calendar) {
475+
exports.formatDate = function(x, fmt, tr, formatter, calendar, extraFormat) {
466476
var headStr,
467477
dateStr;
468478

@@ -476,14 +486,14 @@ exports.formatDate = function(x, fmt, tr, formatter, calendar) {
476486
cDate = Registry.getComponentMethod('calendars', 'getCal')(calendar)
477487
.fromJD(dateJD);
478488

479-
if(tr === 'y') dateStr = yearFormatWorld(cDate);
480-
else if(tr === 'm') dateStr = monthFormatWorld(cDate);
489+
if(tr === 'y') dateStr = formatWorld(cDate, extraFormat.year);
490+
else if(tr === 'm') dateStr = formatWorld(cDate, extraFormat.month);
481491
else if(tr === 'd') {
482-
headStr = yearFormatWorld(cDate);
483-
dateStr = dayFormatWorld(cDate);
492+
headStr = formatWorld(cDate, extraFormat.year);
493+
dateStr = formatWorld(cDate, extraFormat.dayMonth);
484494
}
485495
else {
486-
headStr = yearMonthDayFormatWorld(cDate);
496+
headStr = formatWorld(cDate, extraFormat.dayMonthYear);
487497
dateStr = formatTime(x, tr);
488498
}
489499
}
@@ -492,14 +502,14 @@ exports.formatDate = function(x, fmt, tr, formatter, calendar) {
492502
else {
493503
var d = new Date(Math.floor(x + 0.05));
494504

495-
if(tr === 'y') dateStr = formatter(yearFormatD3)(d);
496-
else if(tr === 'm') dateStr = formatter(monthFormatD3)(d);
505+
if(tr === 'y') dateStr = formatter(extraFormat.year)(d);
506+
else if(tr === 'm') dateStr = formatter(extraFormat.month)(d);
497507
else if(tr === 'd') {
498-
headStr = formatter(yearFormatD3)(d);
499-
dateStr = formatter(dayFormatD3)(d);
508+
headStr = formatter(extraFormat.year)(d);
509+
dateStr = formatter(extraFormat.dayMonth)(d);
500510
}
501511
else {
502-
headStr = formatter(yearMonthDayFormatD3)(d);
512+
headStr = formatter(extraFormat.dayMonthYear)(d);
503513
dateStr = formatTime(x, tr);
504514
}
505515
}

src/locale-en.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/**
2-
* Copyright 2012-2018, Plotly, Inc.
3-
* All rights reserved.
4-
*
5-
* This source code is licensed under the MIT license found in the
6-
* LICENSE file in the root directory of this source tree.
7-
*/
2+
* Copyright 2012-2018, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
88

99
'use strict';
1010

@@ -32,6 +32,10 @@ module.exports = {
3232
decimal: '.',
3333
thousands: ',',
3434
grouping: [3],
35-
currency: ['$', '']
35+
currency: ['$', ''],
36+
year: '%Y',
37+
month: '%b %Y',
38+
dayMonth: '%b %e',
39+
dayMonthYear: '%b %e, %Y'
3640
}
3741
};

src/plots/cartesian/axes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ function formatDate(ax, out, hover, extraPrecision) {
12921292
else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 4}[tr];
12931293
}
12941294

1295-
var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar),
1295+
var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar, ax._extraFormat),
12961296
headStr;
12971297

12981298
var splitIndex = dateStr.indexOf('\n');

src/plots/cartesian/set_convert.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ module.exports = function setConvert(ax, fullLayout) {
457457
var locale = fullLayout._d3locale;
458458
if(ax.type === 'date') {
459459
ax._dateFormat = locale ? locale.timeFormat.utc : d3.time.format.utc;
460+
ax._extraFormat = fullLayout._extraFormat;
460461
}
461462
// occasionally we need _numFormat to pass through
462463
// even though it won't be needed by this axis

src/plots/plots.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ plots.supplyDefaults = function(gd) {
305305
};
306306
newFullLayout._traceWord = _(gd, 'trace');
307307

308-
var formatObj = getD3FormatObj(gd);
308+
var formatObj = getFormatObj(gd, d3FormatKeys);
309309

310310
// first fill in what we can of layout without looking at data
311311
// because fullData needs a few things from layout
@@ -342,6 +342,7 @@ plots.supplyDefaults = function(gd) {
342342
}
343343

344344
newFullLayout._d3locale = getFormatter(formatObj, newFullLayout.separators);
345+
newFullLayout._extraFormat = getFormatObj(gd, extraFormatKeys);
345346

346347
newFullLayout._initialAutoSizeIsDone = true;
347348

@@ -481,21 +482,28 @@ function remapTransformedArrays(cd0, newTrace) {
481482
}
482483
}
483484

484-
var formatKeys = [
485+
var d3FormatKeys = [
485486
'days', 'shortDays', 'months', 'shortMonths', 'periods',
486487
'dateTime', 'date', 'time',
487488
'decimal', 'thousands', 'grouping', 'currency'
488489
];
489490

491+
var extraFormatKeys = [
492+
'year', 'month', 'dayMonth', 'dayMonthYear'
493+
];
494+
490495
/**
491-
* getD3FormatObj: use _context to get the d3.locale argument object.
496+
* getFormatObj: use _context to get the format object from locale.
497+
* Used to get d3.locale argument object and extraFormat argument object
498+
*
499+
* Regarding d3.locale argument :
492500
* decimal and thousands can be overridden later by layout.separators
493501
* grouping and currency are not presently used by our automatic number
494502
* formatting system but can be used by custom formats.
495503
*
496504
* @returns {object} d3.locale format object
497505
*/
498-
function getD3FormatObj(gd) {
506+
function getFormatObj(gd, formatKeys) {
499507
var locale = gd._context.locale;
500508
if(!locale) locale === 'en-US';
501509

0 commit comments

Comments
 (0)