Material-ui: [DatePicker] multi language support

Created on 15 Apr 2015  路  22Comments  路  Source: mui-org/material-ui

Hi!
It will be extremely useful to set Days of the Week and Months in different languages (spanish in my case).
I dont think that it should be that hard, the interface should be something like this:

<DatePicker
  hintText="Portrait Dialog"
  daysName={['Sunday', 'Monday', ...]}
  monthsName={['January', 'February', ...]}
  />

I believe that the value outstands the complexity of implementing this :smile:

Thanks!

v0.x

Most helpful comment

Example usage:

<DatePicker
    hintText="Fecha final"
    container="inline"
    DateTimeFormat={ Intl.DateTimeFormat }
    locale='es-ES'
    mode="landscape" />

All 22 comments

+1
I think it would be more extensible an object of culture, like

var cultureInfo = {
    day: {
        name: ['Sunday', 'Monday', ...],
        abbr: ['Sun', 'Mon', ...]
    },
    month: {
        name: ['January', 'February', ...],
        abbr: ['Jan', 'Feb', ...]
    }
};

<DatePicker
  hintText="Portrait Dialog"
  cultureInfo={cultureInfo}
  />

+1

@mmrtnz @hai-cea How do you guys feel about utilizing http://momentjs.com/ for material-ui's date/time needs? We would be able to extract almost all of the datetime utils and have il8n for 'free'.

@jkruder +1

+1

I see this closed but where's the implementation? I not found any help from docs

@rkmax It's still an open issue.

+1
I can help fixing if needed
Thanks

Thanks @Griffosx. I need get solve some problems with my local dev folder to starting to contribute to mterial-ui

@hai-cea In April I proposed using momentjs to enhance the date picker. It has i8l support so we could lean on their implementation and just expose some props. What do you think?

I did something very quickly

// src/utils/date-time.js
let moment = require('moment');
moment.locale('es');

module.exports = {

  addDays(d, days) {
    let newDate = this.clone(d);
    newDate.add(days, 'days');
    return newDate.toDate();
  },

  addMonths(d, months) {
    let newDate = this.clone(d);
    newDate.add(months, 'months');
    return newDate.toDate();
  },

  addYears(d, years) {
    let newDate = this.clone(d);
    newDate.add(years, 'years');
    return newDate.toDate();
  },

  clone(d) {
    return moment(d);
  },

  cloneAsDate(d) {
    let clonedDate = this.clone(d);
    return clonedDate.toDate();
  },

  getDaysInMonth(d) {
    let resultDate = this.clone(d);

    return resultDate.daysInMonth();
  },

  getFirstDayOfMonth(d) {
    let clonedDate = this.clone(d);
    clonedDate.startOf('month');
    return clonedDate.toDate();
  },

  getFullMonth(d) {
    let clonedDate = this.clone(d);
    return clonedDate.format('MMMM');
  },

  getShortMonth(d) {
    let clonedDate = this.clone(d);
    return clonedDate.format('MMM');
  },

  getDayOfWeek(d) {
    let clonedDate = this.clone(d);
    return clonedDate.format('dddd');
  },

  getWeekArray(d) {
    let dayArray = [];
    let daysInMonth = this.getDaysInMonth(d);
    let daysInWeek;
    let emptyDays;
    let firstDayOfWeek;
    let week;
    let weekArray = [];

    for (let i = 1; i <= daysInMonth; i++) {
      dayArray.push(new Date(d.getFullYear(), d.getMonth(), i));
    }

    while (dayArray.length) {
      firstDayOfWeek = dayArray[0].getDay();
      daysInWeek = 7 - firstDayOfWeek;
      emptyDays = 7 - daysInWeek;
      week = dayArray.splice(0, daysInWeek);

      for (let i = 0; i < emptyDays; i++) {
        week.unshift(null);
      }

      weekArray.push(week);
    }

    return weekArray;
  },

  format(date) {
    let m = date.getMonth() + 1;
    let d = date.getDate();
    let y = date.getFullYear();
    return m + '/' + d + '/' + y;
  },

  isEqualDate(d1, d2) {
    return d1 && d2 &&
      (d1.getFullYear() === d2.getFullYear()) &&
      (d1.getMonth() === d2.getMonth()) &&
      (d1.getDate() === d2.getDate());
  },

  isBeforeDate(d1, d2) {
    let date1 = this.cloneAsDate(d1);
    let date2 = this.cloneAsDate(d2);

    return (date1.getTime() < date2.getTime());
  },

  isAfterDate(d1, d2) {
    let date1 = this.cloneAsDate(d1);
    let date2 = this.cloneAsDate(d2);

    return (date1.getTime() > date2.getTime());
  },

  isBetweenDates(dateToCheck, startDate, endDate) {
    return (!(this.isBeforeDate(dateToCheck, startDate)) &&
            !(this.isAfterDate(dateToCheck, endDate)));
  },

  monthDiff(d1, d2) {
    let m;
    m = (d1.getFullYear() - d2.getFullYear()) * 12;
    m += d1.getMonth();
    m -= d2.getMonth();
    return m;
  },

  yearDiff(d1, d2) {
    return ~~(this.monthDiff(d1, d2) / 12);
  }

};

@jkruder Instead of using momentjs, what do you think about adding a DateTimeFormat and a locale as optionals prop to the DatePicker?

The DateTimeFormat would follow this spec.
We can update https://github.com/callemall/material-ui/blob/master/src/utils/date-time.js to provide the default interface (locale=en-US obviously).
Then if someone wants to change the locale, he can provide:

  • Intl.DateTimeFormat if it's available in the browser
  • or this polyfill.
  • or a custom one

@oliviertassinari I like the idea of using Intl.DateTimeFormat, lighter than depending on momentjs. However, I do not think we should be recreating the wheel. If Intl.DateTimeFormat can provide all of the formatting that we need then we may not need a library like momentjs. I took a look at the polyfill but did not see anything that indicated Safari webkit support. Maybe I missed it? If we can confirm the polyfill works for Safari I see no reason why we could not move forward with Intl.DateTimeFormat over momentjs.

I think that the intl polyfill support every browser since they use the data of http://cldr.unicode.org/ then do some massage to produce the output.

However, I do not think we should be recreating the wheel

I was proposing to update date-time.js to not introduce breaking changes (adding a polyfill of Intl for browsers that don't support it and that you want to support).

I read through the readme of the polyfill more closely and I believe that it does support Safari (although I did not see anything that explicitly confirms that).

In regards to recreating the wheel, there may be some functionality in date-time.js that already exists in momentjs. For locale support if we only need to consume the Intl.DateTimeFormat API then I have no issue with it. Folks should not be consuming date-time.js directly so any changes we make (or replace it with something else) should be hidden from the consumer of material-ui.

Example usage:

<DatePicker
    hintText="Fecha final"
    container="inline"
    DateTimeFormat={ Intl.DateTimeFormat }
    locale='es-ES'
    mode="landscape" />

Hey, I'm using Material UI date picker for reactjs 4 years after this thread, is there multi language support now?

What is the simplest way to change language of the calendar to french?

<MuiPickersUtilsProvider utils={DateFnsUtils}> <Grid container justify="space-around"> <KeyboardDatePicker margin="normal" id="date-picker-dialog" //label="Date picker dialog" format="dd/MM/yyyy" placeholder="Jours/Mois/Ann茅e" locale='fr-FR' value={this.state.startDate} onChange={this.handleChange} KeyboardButtonProps={{ 'aria-label': 'change date', }} /> </Grid> </MuiPickersUtilsProvider>

I tried locale, didn't work

this seems a bit over complicated for what I wanna do, isn't there a simpler way? https://material-ui-pickers.dev/localization/moment

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iamzhouyi picture iamzhouyi  路  3Comments

revskill10 picture revskill10  路  3Comments

anthony-dandrea picture anthony-dandrea  路  3Comments

TimoRuetten picture TimoRuetten  路  3Comments

activatedgeek picture activatedgeek  路  3Comments