jbrown / ember-intl

Feature rich Internalization addon for your Ember application

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ember-intl

Join the chat at https://gitter.im/yahoo/ember-intl npm Version Build Status Ember Observer Score

This library provides Ember Handlebar helpers and a localization service. The service, and helpers, provide a way to format dates, numbers, strings messages, including pluralization.

demo of ember-intl

Ember-Intl 2.0

This README is targets the 2.0 API which differs from previous and the current stable versions. If you are looking for the <= 1.3.0 documentation, please go here.

Overview

Ember Intl is part of FormatJS, the docs can be found on the website:

http://formatjs.io/ember/

Requirements

  • ember-cli >= 0.2.0
  • ember >= 1.10.x <= 1.13.x

Installation

  • ember install ember-intl@2.0.0-beta.13
  • If you are targeting a browser that doesn't support the native Intl API (such as Safari or PhantomJS), you need to load the shim. The Intl.JS polyfill is automatically included into the /assets folder at build time.
<script src="assets/intl/intl.min.js"></script>
<script src="assets/intl/locales/en-us.js"></script>
<script src="assets/intl/locales/fr-fr.js"></script>
<script src="assets/intl/locales/es-es.js"></script>
<!--
You can view the full list of CLDR locales which can be accessed from the `/assets/intl` folder
of your application.  The CLDRs are automatically placed there at build time.  Typically this folder
on your filesystem is ``<project>/dist/assets/intl`

Full list: https://github.com/yahoo/formatjs-extract-cldr-data/tree/master/data/main
-->

Translations

Translations are defined in /translations, outside of app in either JSON or YAML format. Example of /translations/en-us.yaml:

# en-us
product:
  info: '{product} will cost {price, number, USD} if ordered by {deadline, date, time}'
  title: 'Hello world!'
  html:
    info: '<strong>{product}</strong> will cost <em>{price, number, USD}</em> if ordered by {deadline, date, time}'

Configure application-wide locale

Open, or create, app/routes/application.js and in the beforeModel hook set intl.locale. Example:

  // app/routes/application.js
  export default Ember.Route.extend({
    intl: Ember.inject.service(),
    beforeModel() {
      // define the app's runtime locale
      // For example, here you would maybe do an API lookup to resolver
      // which locale the user should be targeted and perhaps lazily
      // load translations using XHR and calling intl's `addMessage`/`addMessages`
      // method with the results of the XHR request
      this.set('intl.locale', 'en-us');
    }
  });
  • A default locale is required. This is used as the "source of truth" to determine if any translations are missing a translation at build time. It will offer warnings displaying with locale's are missing translations for a particular key. The default locale is configurable within config/environment.js.
// config/environment.js
return {
  intl: {
    defaultLocale: 'en-us' // default value
  }
};

Examples

Format Number

Formats numbers using Intl.NumberFormat, and returns the formatted string value.

{{format-number num}}
{{format-number num format='EUR'}}
{{format-number num style='currency' currency='USD'}}

Or programmatically convert a number within any Ember Object.

// example
export default Ember.Component.extend({
  intl: Ember.inject.service(),
  computedNumber: Ember.computed('cost', function() {
    return this.get('intl').formatNumber(this.get('cost')/*, optional options hash */);
  })
});

Format Number Options

List of supported format number options

Format Date

Formats dates using Intl.DateTimeFormat, and returns the formatted string value.

{{format-date now weekday='long' timeZone='UTC'}}
{{format-date now hour='numeric' minute='numeric' hour12=false}}

Or programmatically convert a date within any Ember Object.

// example
export default Ember.Component.extend({
  intl: Ember.inject.service(),
  computedNow: Ember.computed(function() {
    return this.get('intl').formatDate(new Date()/*, optional options hash */);
  })
});

Format Date Options

List of supported format date options

Format Time

This is just like the {{format-date}} helper, except it will reference any string-named format from formats.time.

{{format-time now format='hhmmss'}}
{{format-time now hour='numeric' minute='numeric' hour12=false}}

Or programmatically convert a time within any Ember Object.

// example
export default Ember.Component.extend({
  intl: Ember.inject.service(),
  computedNow: Ember.computed(function() {
    return this.get('intl').formatTime(new Date()/*, optional options hash */);
  })
});

Format Time Options

List of supported format date options

Format Relative

Formats dates relative to "now" using IntlRelativeFormat, and returns the formatted string value.

export default Ember.Component.extend({
  timestamp: Ember.computed(function() {
    var date = new Date();
    date.setDate(date.getDate() - 3);
    return date;
  })
});
{{format-relative timestamp}} -> 3 days ago

Or programmatically convert a relative time within any Ember Object.

// example
export default Ember.Component.extend({
  intl: Ember.inject.service(),
  yesterday: Ember.computed(function() {
    var date = new Date();
    return this.get('intl').formatRelative(date.setDate(date.getDate() - 1)/*, optional options hash */);
  })
});

Format Relative Options

List of supported format date options

Format Message

Formats ICU Message strings with the given values supplied as the hash arguments.

You have {numPhotos, plural,
	=0 {no photos.}
	=1 {one photo.}
	other {# photos.}}
{{format-message (intl-get 'product.info')
	product='Apple watch'
	price=200
	deadline=yesterday}}

{{format-message boundProperty
	name='Jason'
	numPhotos=num
	takenDate=yesterday}}

Or programmatically convert a message within any Ember Object.

export default Ember.Component.extend({
  intl: Ember.inject.service(),
  yesterday: Ember.computed(function() {
    var now = new Date();
    return this.get('intl').formatMessage('Hello {name}', { name: 'Jason' });
  })
});

Format HTML Message

This delegates to the {{format-message}} helper, but will first HTML-escape all of the hash argument values. This allows the message string to contain HTML and it will be considered safe since it's part of the template and not user-supplied data.

{{format-html-message (intl-get 'product.html.info')
	product='Apple watch'
	price=200
	deadline=yesterday}}

{{format-html-message '<strong>{numPhotos}</strong>'
	numPhotos=(format-number num)}}

Intl-Get

Utility helper for returning the value, or eventual value, based on a translation key. Should only ever be used as a subexpression, never as a standalone helper.

{{format-message (intl-get 'product.info')
	product='Apple watch'
	price=200
	deadline=yesterday}}

Will return the message from the current locale, or locale explicitly passed as an argument, message object.

product:
  info: '{product} will cost {price, number, EUR} if ordered by {deadline, date, time}'

Polyfill

Disabling

// config/environment.js
module.exports = function() {
  return {
    intl: {
      disablePolyfill: true
    }
  };
};

Cherry pick CLDR modules

At build time, we copy roughly 700 files, totaling 18mb, to the asset folder. Don't worry, this does not add weight to your app or vendor files. The only penalty you incur is at build time with the ember-cli build pipeline. Since most applications have a list of locales they target, you can specify the locales in config/environment.js to optimize only copying the files needed.

module.exports = function() {
  return {
    intl: {
      locales: ['en-us', 'fr-fr']
    }
  };
};

In this case, en-us.js and fr-fr.js will be copied to /assets/intl/locales on build.

Change output path

// Brocfile.js
var app = new EmberApp({
  outputPaths: {
    intl: '/assets/intl' // default
  }
});

Known Gotchas

date value is not finite in DateTimeFormat.format()

Browser vendors implement date/time parsing differently. For example, the following will parse correctly in Chrome but fail in Firefox: new Intl.DateTimeFormat().format('2015-04-21 20:47:31 GMT');

The solution is the ensure that the value you are passing in is in a format which is valid for the Date constructor. This library currently does not try and normalize date strings outside of what the browser already implements.

Helper Options

  • All helpers accept optional arguments:
    • locale argument to explicitly pass/override the application locale
    • format argument which you pass in a key corresponding to a format configuration in app/formats.js

Writing Unit Tests

Phantom does support the Intl API, so in order for for you ember-intl to work in a browser which does not support the Intl API, it needs to be polyfilled.

To resolve this, add the following above all script tags in tests/index.html:

<script src="assets/intl/intl.complete.js"></script>

Testing with ember-intl

Running

Running Tests

  • ember test
  • ember test --server

About

Feature rich Internalization addon for your Ember application

License:Other


Languages

Language:JavaScript 97.3%Language:Handlebars 1.4%Language:HTML 1.1%Language:CSS 0.2%