Git Product home page Git Product logo

ember-intl's Introduction

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 injected into views, routes, models, controllers, and components. The service, and helpers, provide a way to format dates, numbers, strings messages, including pluralization.

Ember-Intl 2.0

This README is targetting and explaining the 2.0 API which differs from previous versions and the latest stable release. If you are looking for the 1.3.x documentation, please check 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
  • HTMLBars (Glimmer supported)

Installation

  • ember install ember-intl@beta (or ember install:addon ember-intl@beta for ember-cli < v0.2.3)
  • 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 added into your asset distribution folder, so you need to add the following to your index.html:
<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 are defined in /translations, outside of app in either JSON or YAML format. Example of /translations/en-us.yaml:

product:
  info: '{product} will cost {price, number, EUR} if ordered by {deadline, date, time}'
  title: 'Hello world!'
  html:
    info: '<strong>{product}</strong> will cost <em>{price, number, EUR}</em> if ordered by {deadline, date, time}'
  • Configure which locale you want to use at runtime:
    • Open (or create) app/routes/application.js
  // 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
      Ember.set(this, '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
ENV: {
  ...
  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'));
    })
});

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());
    })
});

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());
    })
});

Format Relative

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

{{format-relative yesterday}}

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 now = new Date();
        return this.get('intl').formatRelative(now.setDate(now.getDate() - 1));
    })
});

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}'

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

If using the intl helpers within a components or views that is unit tested, needs the service, helper, and formatter into the unit test.

In the setup hook of moduleFor/moduleForComponent you'll want to also invoke registerIntl(container); -- which is a utility function to setup the injection logic on the unit test container.

NOTE: Add the following above all script tags in tests/index.html

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

This is to shim your test runner if running within phantomjs, or any browser which does not natiely support the Intl API.

=======

Example unit test

/**
 * unit test for testing index view which contains the helpers: `format-message` and `intl-get`
 *
 * unit/views/index-test.js
 */
import Ember from 'ember';

import { registerIntl } from '../../../initializers/ember-intl';

import {
  moduleFor,
  test
} from 'ember-qunit';

moduleFor('view:index', 'IndexView', {
  needs: [
    'template:index',
    'adapter:-intl-adapter',
    'service:intl',
    'helper:intl-get',
    'ember-intl@formatter:format-message',
    'translation:en',
    'translation:es'
  ],
  setup: function () {
    // depending on your test library, container will be hanging off `this`
    // or otherwise passed in as the first argument
    var container = this.container || arguments[0];
    // injects the service on to all logical factory types
    registerIntl(container);

    // set the initial intl service locale to `en-us`
    var intl = container.lookup('service:intl');
    intl.set('locale', 'en');
  }
});

test('index renders', function () {
  expect(2);

  var view = this.subject({
    context: Ember.Object.create({
      firstName: 'Tom'
    })
  });

  var intl = view.get('intl');

  // render view
  Ember.run(view, 'appendTo', '#qunit-fixture');

  equal(view.$().text().trim(), "hello Tom");

  Ember.run(function () {
    intl.set('locale', 'es');
  });

  equal(view.$().text().trim(), "hola Tom");

  // destroy view
  Ember.run(view, 'destroy');
});

Known Gotchas

date value is not finite in DateTimeFormat.format()

Browser vendors implement datetime 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.

Running

Running Tests

  • ember test
  • ember test --server

ember-intl's People

Contributors

jasonmit avatar zeppelin avatar elwayman02 avatar jlecomte avatar gdelbos avatar thoov avatar michelle avatar rlivsey avatar sjmueller avatar gitter-badger avatar gtimti avatar ember-tomster avatar

Watchers

Alexander avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.