A proper way to translate drop-down constants


#1

I used ember-i18n and translated the text values to be displayed in a drop-down by creating a service constants.js as follows:

#services/constants.js

import Service from '@ember/service';
import { inject as service } from '@ember/service';

export default Service.extend({
   intl: service(),

    init() {
      this._super(...arguments);
      this.set('states',
      [
        {id: 'open', name: this.intl.t('states.open')},
        {id: 'closed', name: this.intl.t('states.closed')},
        {id: 'divided', name: this.intl.t('states.divided')}
      ]
    );
    this.set('days',
      [
        {day: 'monday', name: this.intl.t('weekdays.monday')},
        {day: 'tuesday', name: this.intl.t('weekdays.tuesday')},
        {day: 'wednesday', name: this.intl.t('weekdays.wednesday')},
        {day: 'thursday', name: this.intl.t('weekdays.thursday')},
        {day: 'friday', name: this.intl.t('weekdays.friday')},
        {day: 'saturday', name: this.intl.t('weekdays.saturday')},
        {day: 'sunday', name: this.intl.t('weekdays.sunday')}
      ]
    );
});

The purpose is to display working hours for every weekday with the corresponding shop status by day (open, closed, with a break):

I set up every weekday row in weekday-row component:

#components/weekday-row.js
export default Component.extend({
  intl:      service('intl'),
  constants: service(),
  weekday:   null,
  state:     null,
  states:    [],
  tagName:   '',

init() {
    this._super(...arguments);
    this.set('states', this.get('constants.states'));
  },
...

After migrating to ember-intl, there is a problem with setting the default locale. Now I do that in beforeModel hook in application.js route:

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

  calculateLocale(locales) {
    // whatever you do to pick a locale for the user:
    const language = navigator.languages[0] || navigator.language || navigator.userLanguage;

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

As a service is a Singleton, when initializing it, there is no default local set yet and ember-intl uses its own default one set to en-US.

How can I fix that? How to get states values translated? Thank you!


#2

Thanks to the help I got from Discord (special thanks to @Lux and @Windivs), I got it working by using a computed property:

import Service from '@ember/service';
import { computed } from '@ember/object';
import { inject as service } from '@ember/service';

export default Service.extend({
  intl: service(),

...
  
  states: computed('intl.locale', function(){
    return  [
      {id: 'open', name: this.intl.t('states.open')},
      {id: 'closed', name: this.intl.t('states.closed')},
      {id: 'divided', name: this.intl.t('states.divided')}
    ];
  }),
  
  days: computed('intl.locale', function(){
    return [
      {day: 'monday', name: this.get('intl').t('weekdays.monday')},
      {day: 'tuesday', name: this.get('intl').t('weekdays.tuesday')},
      {day: 'wednesday', name: this.get('intl').t('weekdays.wednesday')},
      {day: 'thursday', name: this.get('intl').t('weekdays.thursday')},
      {day: 'friday', name: this.get('intl').t('weekdays.friday')},
      {day: 'saturday', name: this.get('intl').t('weekdays.saturday')},
      {day: 'sunday', name: this.get('intl').t('weekdays.sunday')}
    ];
  })

Really awesome !