Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing new CLDR extracting #68

Merged
merged 22 commits into from
Mar 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ export default Locale.extend({
```js
var App = Ember.Application.extend({
ready: function () {
// setup default locale to fr but will fallback to en
this.intl.set('locales', ['fr-FR', 'en']);
// read more: http://formatjs.io/guide/#client-side
var language = navigator.language || navigator.browserLanguage;
this.intl.set('locales', [language, 'en']);
}
});
```
Expand Down
10 changes: 10 additions & 0 deletions addon/adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Ember from 'ember';

function notImplemented () {
throw new Error('not implemented');
}

export default Ember.Object.extend({
findLanguage: notImplemented,
findTranslation: notImplemented
});
7 changes: 3 additions & 4 deletions addon/helpers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default function (formatterName) {
var view = env.data.view;
var intl = view.container.lookup('intl:main');
var seenHash = readHash(hash);
var context = view.get('context');
var formatter = view.container.lookup('formatter:' + formatterName);

if (value.isStream) {
Expand All @@ -43,7 +42,7 @@ export default function (formatterName) {
currentValue = read(value);

outStream = new Stream(function () {
return formatter.format.call(formatter, read(currentValue), seenHash, context);
return formatter.format.call(formatter, read(currentValue), seenHash);
});

Ember.keys(hash).forEach(function (key) {
Expand Down Expand Up @@ -82,9 +81,9 @@ export default function (formatterName) {
var view = options.data.view;
var intl = this.container.lookup('intl:main');
var types = options.types;
var context = view.get('context');
var hash = extend({}, options.hash);
var formatter = view.container.lookup('formatter:' + formatterName);

var simpleView, simpleViewStream, currentValue;

if (types[0] === 'ID') {
Expand All @@ -101,7 +100,7 @@ export default function (formatterName) {
currentValue = read(value);

simpleViewStream = new Stream(function () {
return formatter.format.call(formatter, read(currentValue), hash, context);
return formatter.format.call(formatter, read(currentValue), hash);
});

Ember.keys(options.hashTypes).forEach(function (key) {
Expand Down
6 changes: 6 additions & 0 deletions addon/models/intl-get-result.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
function IntlGetResult (translation, locale) {
this.translation = translation;
this.locale = locale;
}

export default IntlGetResult;
40 changes: 40 additions & 0 deletions app/adapters/-intl-adapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Ember from 'ember';
import IntlGetResult from 'ember-intl/models/intl-get-result';
import Locale from 'ember-intl/models/locale';
import IntlAdapter from 'ember-intl/adapter';

function normalize (fullName) {
Ember.assert('Lookup name must be a string', typeof fullName === 'string');

return fullName.toLowerCase();
}

export default IntlAdapter.extend({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not documenting this yet, but it will eventually be exposed for those people who want to specify their own way of loading translations. The CLDR portion of this hasn't been thought out yet, but it will ideally be another hook off this.

See: #69

findLanguage: function (locale) {
if (locale instanceof Locale) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's Locale here, a class? If so can this be simplified since it is just data?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is too much abstraction for data that can be represented as a hash. But this might need to stay for back-compat?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was needed two resolve the following issues:
#46 (getValue)
#24 (getValue)
And #18 (addMessage)

return locale;
}

if (typeof locale === 'string') {
return this.container.lookup('locale:' + normalize(locale));
}
},

findTranslation: function (locales, translationKey) {
var container = this.container;
var locale, translation, key;

for (var i=0, len = locales.length; i < len; i++) {
key = locales[i];
locale = this.findLanguage(key);

if (locale) {
translation = locale.getValue(translationKey);

if (typeof translation !== 'undefined') {
return new IntlGetResult(translation, key);
}
}
}
}
});
35 changes: 13 additions & 22 deletions app/formatters/format-html-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,29 @@

import Ember from 'ember';
import FormatterMessage from './format-message';
import IntlGetResult from 'ember-intl/models/intl-get-result';

var FormatHtmlMessage = FormatterMessage.extend({
escapeProps: function (props) {
return Object.keys(props).reduce(function (escapedProps, name) {
var value = props[name];
escapeProps: function (hash) {
var value;

return Object.keys(hash).reduce(function (result, hashKey) {
value = hash[hashKey];

// TODO: Can we force string coersion here? Or would that not be needed
// and possible mess with IntlMessageFormat?
if (typeof value === 'string') {
value = Ember.Handlebars.Utils.escapeExpression(value);
}

escapedProps[name] = value;
return escapedProps;
result[hashKey] = value;
return result;
}, {});
},

format: function (value, hash, context) {
var icuKeys = this.extractICUKeys(value);
var model = {};

if (icuKeys && icuKeys.length) {
model = Ember.$.extend(Ember.getProperties(context, icuKeys), hash);
}

var formatOptions = {};

if (hash.locales) {
formatOptions.locales = hash.locales;
}

return Ember.String.htmlSafe(this.intl.formatMessage(value, this.escapeProps(model), formatOptions));
format: function (value, hash) {
var locales = hash.locales;
hash = this.escapeProps(hash);
var superResult = this._super(value, hash, locales);
return Ember.String.htmlSafe(superResult);
}
});

Expand Down
54 changes: 12 additions & 42 deletions app/formatters/format-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,28 @@

import Ember from 'ember';
import Formatter from 'ember-intl/formatter-base';
import IntlGetResult from 'ember-intl/models/intl-get-result';

var validKey = /[\w|.]/;

var FormatMessage = Formatter.extend({
extractICUKeys: function (msg) {
var length = msg.length;
var buf = [], out = Ember.A();
var i = 0;
var char, key;

for (; i < length; i++) {
char = msg[i];

if (buf.length && !validKey.test(char)) {
buf.shift();
key = buf.join('');

// do not include empty strings: {}
if (key) { out.addObject(key); }

buf = [];
}
else if (
// does not include escaped curly braces
// and double curly braces does not mistake the first
// as the starting point of the key {{foo}} should return `foo`
(char === '{' && msg[i-1] !== "\\" && msg[i+1] !== '{') ||
buf.length
)
{
buf.push(char);
}
}

return out;
},
format: function (value, hash, optionalLocale) {
var locales = optionalLocale || hash.locales;
var formatOptions = {};

format: function (value, hash, context) {
var icuKeys = this.extractICUKeys(value);
var model;
if (value instanceof IntlGetResult) {
if (typeof locales === 'undefined') {
locales = value.locale;
}

if (icuKeys && icuKeys.length) {
model = Ember.$.extend(Ember.getProperties(context, icuKeys), hash);
value = value.translation;
}

var formatOptions = {};

if (hash.locales) {
formatOptions.locales = hash.locales;
if (locales) {
formatOptions.locales = locales;
}

return this.intl.formatMessage(value, model, formatOptions);
return this.intl.formatMessage(value, hash, formatOptions);
}
});

Expand Down
35 changes: 6 additions & 29 deletions app/helpers/intl-get.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,21 @@
import Ember from 'ember';
import { Stream, read, readHash, destroyStream } from 'ember-intl/utils/streams';

function normalize (fullName) {
Ember.assert('Lookup name must be a string', typeof fullName === 'string');
return fullName.toLowerCase();
}

function intlGet (key, locale, container) {
Ember.assert('You must pass in a message key in the form of a string.', typeof key === 'string');

var intl = container.lookup('intl:main');
var locales = locale ? Ember.makeArray(locale) : intl.get('current');

for (var i=0; i < locales.length; i++) {
var locale = container.lookup('locale:' + normalize(locales[i]));

if (locale) {
var value = locale.getValue(key);

if (typeof value !== 'undefined') {
return value;
}
}
}

throw new ReferenceError('Could not find Intl object: ' + key);
}

export default function (value, options) {
var view = options.data.view;
var types = options.types;
var hash = readHash(options.hash);
var intl = view.container.lookup('intl:main');

var currentValue = value;
var valueStream, outStreamValue;
var outStreamValue = '';
var valueStream;

var outStream = new Stream(function () {
return outStreamValue;
});

outStream.setValue = function(_value) {
outStream.setValue = function (_value) {
outStreamValue = _value;
this.notify();
}
Expand All @@ -56,7 +31,9 @@ export default function (value, options) {
}

function pokeStream () {
outStream.setValue(intlGet(read(currentValue), hash.locales, view.container));
return intl.getTranslation(read(currentValue), hash.locales).then(function (translation) {
outStream.setValue(translation);
});
}

if (types[0] === 'ID') {
Expand Down