ember-intl
Version:
Ember toolbox for internationalization.
177 lines (138 loc) • 5.68 kB
JavaScript
/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
import Ember from 'ember';
import Locale from 'ember-intl/models/locale';
import createFormatCache from 'ember-intl/format-cache/memoizer';
import { IntlRelativeFormat, IntlMessageFormat } from 'ember-intl/utils/data';
var ServiceKlass = Ember.Service || Ember.Controller;
var makeArray = Ember.makeArray;
var get = Ember.get;
var on = Ember.on;
var computed = Ember.computed;
var observer = Ember.observer;
var isEmpty = Ember.isEmpty;
var isPresent = Ember.isPresent;
var run = Ember.run;
function assertIsDate (date, errMsg) {
Ember.assert(errMsg, isFinite(date));
}
export default ServiceKlass.extend(Ember.Evented, {
locales: null,
defaultLocale: null,
getDateTimeFormat: null,
getRelativeFormat: null,
getMessageFormat: null,
getNumberFormat: null,
setupMemoizers: on('init', function () {
this.setProperties({
getDateTimeFormat: createFormatCache(Intl.DateTimeFormat),
getRelativeFormat: createFormatCache(IntlRelativeFormat),
getNumberFormat: createFormatCache(Intl.NumberFormat),
getMessageFormat: createFormatCache(IntlMessageFormat)
});
}),
current: computed('locales', 'defaultLocale', function () {
var locales = makeArray(get(this, 'locales'));
var defaultLocale = get(this, 'defaultLocale');
if (isPresent(defaultLocale) && locales.indexOf(defaultLocale) === -1) {
locales.push(defaultLocale);
}
return locales;
}).readOnly(),
formats: computed(function () {
return this.container.lookup('formats:main', {
instantiate: false
}) || {};
}).readOnly(),
localeChanged: observer('current', function () {
run.once(this, this.notifyLocaleChanged);
}),
addMessage: function (locale, key, value) {
var localeInstance = this._getLocaleInstance(locale);
return localeInstance.addMessage(key, value);
},
addMessages: function (locale, messageObject) {
var localeInstance = this._getLocaleInstance(locale);
return localeInstance.addMessages(messageObject);
},
notifyLocaleChanged: function () {
this.trigger('localesChanged');
},
formatMessage: function (message, values, options) {
// When `message` is a function, assume it's an IntlMessageFormat
// instance's `format()` method passed by reference, and call it. This
// is possible because its `this` will be pre-bound to the instance.
if (typeof message === 'function') {
return message(values);
}
options = options || {};
var locales = makeArray(options.locales);
var formats = options.formats || get(this, 'formats');
if (isEmpty(locales)) {
locales = get(this, 'current');
}
if (typeof message === 'string') {
message = this.getMessageFormat(message, locales, formats);
}
return message.format(values);
},
formatTime: function (date, formatOptions, options) {
date = new Date(date);
assertIsDate(date, 'A date or timestamp must be provided to formatTime()');
return this._format('time', date, formatOptions, options);
},
formatRelative: function (date, formatOptions, options) {
date = new Date(date);
assertIsDate(date, 'A date or timestamp must be provided to formatRelative()');
return this._format('relative', date, formatOptions, options);
},
formatDate: function (date, formatOptions, options) {
date = new Date(date);
assertIsDate(date, 'A date or timestamp must be provided to formatDate()');
return this._format('date', date, formatOptions, options);
},
formatNumber: function (num, formatOptions, options) {
return this._format('number', num, formatOptions, options);
},
_format: function (type, value, formatOptions, helperOptions) {
if (!helperOptions) {
helperOptions = formatOptions || {};
formatOptions = null;
}
var locales = makeArray(helperOptions.locales);
var formats = get(this, 'formats');
if (isEmpty(locales)) {
locales = get(this, 'current');
}
if (formatOptions) {
if (typeof formatOptions === 'string' && formats) {
formatOptions = get(formats, type + '.' + formatOptions);
}
formatOptions = Ember.$.extend({}, formatOptions, helperOptions);
} else {
formatOptions = helperOptions;
}
switch (type) {
case 'date':
case 'time':
return this.getDateTimeFormat(locales, formatOptions).format(value);
case 'number':
return this.getNumberFormat(locales, formatOptions).format(value);
case 'relative':
return this.getRelativeFormat(locales, formatOptions).format(value);
default:
throw new Error('Unrecognized simple format type: ' + type);
}
},
_getLocaleInstance: function (locale) {
if (locale instanceof Locale) {
return locale;
}
if (typeof locale === 'string') {
return this.container.lookup('locale:' + locale.toLowerCase());
}
throw new Error('`locale` must be a string or a locale instance');
}
});