jasonmit / ember-cli-moment-shim

ember-cli shim for momentjs
MIT License
33 stars 59 forks source link

Months translation missing for Russian locale #170

Closed belgoros closed 5 years ago

belgoros commented 5 years ago

I have weird behaviour when displaying a date picker for Russian locale (ru). I'm using ember-pikaday add-on and defined the initializer as it was suggested:

#app/initializers/setup-pikaday-i18n.js

import Ember from 'ember';
import moment from 'moment';

export default {
  name: 'setup-pikaday-i18n',
  initialize: function(application) {
    var i18n = Ember.Object.extend({
      months: moment.localeData()._months,
      weekdays: moment.localeData()._weekdays,
      weekdaysShort: moment.localeData()._weekdaysShort
    });

    application.register('pikaday-i18n:main', i18n, { singleton: true });
    application.inject('component:pikaday-input', 'i18n', 'pikaday-i18n:main');
  }
};

It works fine for all other languages but not for Russian. The line months: moment.localeData()._months returns correctly the months

January,February,March,April,May,June,July,August,September,October,November,December

the same for translated versions of other languages but not for Russian where it sends [Object object].

Here is how the failing display looks like:

Screenshot 2019-04-09 at 16 43 29

I also enabled all the locales in config/environment.js:

...
moment: {
      includeLocales: true
    }

I grab the User locale in application.js route as follows:

#routes/application.js

export default Route.extend(ApplicationRouteMixin, {
  currentUser: service(),
  intl: service(),

  beforeModel() {
    let locale = this.figureOutLocale();
    this.intl.setLocale(locale);
    moment.locale(locale);
    console.log('months: ' + moment.localeData()._months);

    return this._loadCurrentUser();
  },

  sessionAuthenticated() {
    this._super(...arguments);
    this._loadCurrentUser();
  },

  _loadCurrentUser() {
    return this.get('currentUser').loadCurrentUser().catch(() => this.get('session').invalidate());
  },

  figureOutLocale() {
    let locale = this.calculateLocale(this.intl.get('locales'));
    return locale;
  },

  calculateLocale(locales) {
    const userLanguage = navigator.languages[0] || navigator.language || navigator.userLanguage;    
    let matchedLanguage = userLanguage.match(/\w{2}/)[0].toLowerCase();

    return  locales.includes(matchedLanguage) ? matchedLanguage : 'en';
  }
});

What's wrong with that? Thank you.

belgoros commented 5 years ago

It seems like the problem comes from the way the months variable is defined in the corresponding ru.js file:

...
months : {
            format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
            standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
        },
...

it is a Hash and not String as in fr.js translation, for example. It means that we should access it by the standalone key:

months: moment.localeData()._months['standalone'],
// instead of a classic one
months: moment.localeData()._months,

Is it sooner a moment.js issue ?

ashsearle commented 5 years ago

Use moment.localeData().months() instead.

belgoros commented 5 years ago

@ashsearle Thank you for your response. I modified and used month() instead in the pikaday initiaizer:

import Ember from 'ember';
import moment from 'moment';

export default {
  name: 'setup-pikaday-i18n',
  initialize: function(application) {
    var i18n = Ember.Object.extend({
      months: moment.localeData().months(),
      weekdays: moment.localeData()._weekdays,
      weekdaysShort: moment.localeData()._weekdaysShort
    });

    application.register('pikaday-i18n:main', i18n, { singleton: true });
    application.inject('component:pikaday-input', 'i18n', 'pikaday-i18n:main');
  }
};

but it still displays undefined for months in the datepicker popup. Even changing for:

months: moment.localeData()._months['standalone'],

does not solve the problem either. It concerns only the Russian locale, all the others (French, English, Portuguese) work fine 😢

belgoros commented 5 years ago

moment.js seems to manage the case when months are not an Array:

function localeMonths (m, format) {
        if (!m) {
            return isArray(this._months) ? this._months :
                this._months['standalone'];
        }
...
ashsearle commented 5 years ago

@belgoros I can only comment on the moment stuff: use the localeData methods instead of accessing private properties like _months, and you should end up with consistent data structures for every locale (e.g. arrays for months.)

belgoros commented 5 years ago

@ashsearle , ok, I think it is sooner a ember-pikaday issue. I'll close this one and open a new one at ember-pikaday repo. Thank you.