typescriptlocalizationaureliai18nextcustom-attribute

How to use i18n in a custom attribute on Aurelia?


I have the following custom attribute in Aurelia:

import { fireEvent } from '_utils/events'
import { autoinject, customAttribute, inject } from 'aurelia-framework'
import $ from 'jquery'
import { I18N } from 'aurelia-i18n'
import 'Modernizr'
import 'pickadate/lib/compressed/picker'
import 'pickadate/lib/compressed/picker.date'

@customAttribute('datepicker')
@inject(Element)
@autoinject
export class DatePicker {
  // public i18N: I18N
  private usePickADate: boolean

  constructor (private element: Element, private i18n: I18N) {
    this.i18n = i18n
    this.usePickADate = !Modernizr.inputtypes.date
    $(this.element).pickadate({
      weekdaysShort: ['Ss', 'Mm', 'Tt', 'Ww', 'Th', 'Ff', 'Ss'],
      showMonthsShort: true,
      format: i18n.tr('general.date-format')
    })
  }

  public attached () {
    if (this.usePickADate) {
      $(this.element).pickadate()
        .on('change', (e: any) => {
          fireEvent(e.target, 'input')
        })
    }
  }

  public detached () {
    if (this.usePickADate) {
      $(this.element).pickadate('picker')
        .off('change')
        .stop()
    }
  }
}

Here I cannot use i18n to translate and localize. I get this error:

Inner Error: Message: Cannot read property 'tr' of undefined

What is the problem? How can I fix it?


Solution

  • You can inject dependencies in two ways in Aurelia, either by using @autoinject() or by using @inject().

    A simple case using @autoinject() would be:

    import { I18N } from "aurelia-i18n";
    import { autoinject } from "aurelia-framework";
    
    @autoinject()
    export class DatePicker {
    
      constructor (private element: Element, private i18n: I18N) { }
    
    }
    

    If you do wish to use @inject() over @autoinject() for any reason at all, be sure to inject all dependencies, like so:

    import { I18N } from "aurelia-i18n";
    import { inject } from "aurelia-framework";
    
    @inject(Element, I18N)
    export class DatePicker {
    
      constructor (private element: Element, private i18n: I18N) { }
    
    }
    

    You're using both in your question, which seems to mess things up.