Moment.js released version 2.12.0 a couple weeks ago, and with that came a major new feature – locale inheritance.
Defining custom locale data has been possible in Moment.js for a very long time, and it is one of the coolest features of the library.
Suppose I wanted create a locale that was specifically for mobile use, which was in French, but had shorter strings for Moment’s relative time feature. Previous to 2.12, I might have tried something like this:
moment.locale('fr-mobile', { relativeTime : { future : 'dans %s', past : 'il y a %s', s : 's', m : 'une m', mm : '%d m', h : 'une h', hh : '%d h', d : 'un j', dd : '%d j', M : 'un mo', MM : '%d mo', y : 'un an', yy : '%d ans' } });
With 2.11.2 and previous, the result would have been great when I called .fromNow():
moment.locale('fr-mobile'); moment().subtract(2, 'minute').fromNow() il y a 2 m
But I would have gotten a surprise when I called .calendar():
moment.locale('fr-mobile'); moment().calendar(); Today at 10:27 PM
English! Whoops. This is because there was no locale inheritance in Moment.js. Locales always fell back to English if data was not defined. To create this fr-mobile locale, I would have had to define every locale property available in Moment.
Enter locale inheritance.
Now I can just define a parent locale for my mobile locale:
moment.locale('fr-mobile', { parentLocale:'fr', relativeTime : { future : 'dans %s', past : 'il y a %s', s : 's', m : 'une m', mm : '%d m', h : 'une h', hh : '%d h', d : 'un j', dd : '%d j', M : 'un mo', MM : '%d mo', y : 'un an', yy : '%d ans' } }); moment.locale('fr-mobile'); moment().subtract(2, 'minute').fromNow() //il y a 2 m moment().calendar() //Aujourd'hui à 22:33
Much Better!
Previously, there was also an issue with partial object definitions. Suppose I wanted to change just a couple things about relative time in the French locale. I would have tried this:
moment.locale('fr', { relativeTime : { future : 'dans %s', past : 'il y a %s', s : 's', m : 'une m', mm : '%d m', } }); moment.locale('fr'); moment().subtract(2, 'minute').fromNow() //il y a 2 m moment().subtract(1, 'year').fromNow() //Uncaught TypeError: Cannot read property 'replace' of undefined
That didn’t go well did it?
Enter updateLocale in 2.12.
moment.updateLocale('fr', { relativeTime : { future : 'dans %s', past : 'il y a %s', s : 's', m : 'une m', mm : '%d m', } }); moment.locale('fr'); moment().subtract(2, 'minute').fromNow(); //il y a 2 m moment().subtract(1, 'year').fromNow(); //il y a un an
Big thanks to Iskren for getting this in.
Save effort, save file size, be happy!