ember-intl / ember-intl

Internationalization for Ember projects
https://ember-intl.github.io
MIT License
437 stars 166 forks source link

Deprecate mandatory `messages.` prefix #23

Closed zeppelin closed 9 years ago

zeppelin commented 9 years ago

Due to the internals of the intl service, it is currently required to prefix key paths with messages. (ex. messages.product.info - instead of just typing product.info).

If intl-get only uses properties on the messages object, I feel this is unnecessary, because:

Related to #18

caridy commented 9 years ago

I don't know all the details about the ember-intl implementation, but in other implementations like handlebars intl we do not lock down the accessor to messages, in fact you can do your own thing:

myTemplate({
    data: {
         mymsgs: { foo: 'hello' }
    }
})
zeppelin commented 9 years ago

The problem is that the intl-get helper is only performing an Ember.get on the intl service: https://github.com/yahoo/ember-intl/blob/master/app/helpers/intl-get.js#L18

Which has a computed property for the messages: https://github.com/yahoo/ember-intl/blob/master/app/services/intl.js#L55-L72

With this implementation there is no way to use intl-get on keys that are not inside the messages hash. In this example foo.bar is not accessible using {{intl-get 'foo.bar'}}:

export default {
  locale: 'en',
  foo: {
    bar: 'baaz'
  },
  messages: {
    product: {
      info: '{product} will cost {price, number, EUR} if ordered by {deadline, date, time}',
      html: {
        info: '<strong>{product}</strong> will cost <em>{price, number, EUR}</em> if ordered by {deadline, date, time}'
      }
    }
  }
};
zeppelin commented 9 years ago

But this is the least of my problem, as I'm happy to throw everything inside the messages hash. The problem is that i18n backends on the server doesn't follow this convention.

caridy commented 9 years ago

intl-get should be flexible, replaceable and non-mandatory, just like it is in all other integrations. it is a convenience method that can be used or not to facilitate message resolution. The real question here is: can ember-intl work without intl-get?

zeppelin commented 9 years ago

How does the other libraries work? Is it common to reach out to foo.bar when fetching a message?

{
  foo: {
    bar: 'baaz'
  },
  messages: {
    product: {
      info: 'info',
      html: {
        info: '<strong>info</strong>'
      }
    }
  }
}
zeppelin commented 9 years ago

What I understand so far is the various roles are neatly organized under data.intl.locales, data.intl.messages and data.intl.formats.

https://github.com/yahoo/handlebars-intl#supplying-i18n-data-to-handlebars

zeppelin commented 9 years ago

The semantics may slightly vary across the implementaions, but I haven't yet found a valid use-case for accessing data.intl.locales (or just foo.bar) when I want to fetch messages.

caridy commented 9 years ago

in hbs, data.intl.locales, data.intl.intl.messages and data.intl.formats are optionals, they are conveniences to propagate app level configuration (locales, messages and formats) to all templates, partials and blocks without having to pass them explicitly into every call to one of our helpers.

as for messages, here is the link with the details: https://github.com/yahoo/handlebars-intl#intlget

essentially: intlGet is equivalent to using hbs data channel, but it adds better error reporting:

{{formatMessage (intlGet "messages.FOO")}}
{{formatMessage @intl.messages.FOO}}

as you can see there, we also use "messages" as part of the namespace, which means you could potentially use:

{{formatMessage (intlGet "foo.bar")}}
{{formatMessage @intl.foo.bar}}

from your example above.

jasonmit commented 9 years ago

I will make adjustments to not expose the internals of the service. But I believe we should keep the APIs similar for intl-get. I can add another sub expression helper specific to messages so you do not need to pass "messages."

Thoughts @caridy @ericf

caridy commented 9 years ago

@jasonmit if you have a allocator to put messages within messages entry, then you should have an accessor for it, but I will argue that we should not enforce the message entry, instead, let them allocate intl messages with the namespace they want to, and therefore they will access them with the exact same namespace, whether that's messages or not.

zeppelin commented 9 years ago

@jasonmit how about making the store pluggable? This way issues like #24 could also be solved, and it wouldn't introduce new helpers just for this particular case.

zeppelin commented 9 years ago

I mean would be happy if I could subclass the current store and use that instead of the default. The only thing needed is deciding on public store methods, because I sense that sticking with Ember.get as an accessor directly on the store only makes our life more complicated since we loose a lot of flexiblity for the custom implementations.

jasonmit commented 9 years ago

@caridy I'm not able to follow what you mean. Can you ping me offline and so we can chat about this idea. The public API is similar between the libraries but the implementation between handlebars-intl and ember-intl is vastly different since we can assume we're dealing with application-wide state versus "needling" the template data through.

how about making the store pluggable

Right now there isn't a concept of a store. They are simply modules which export a POJO and looked up to generate a messages object when locales changes. I do plan to use a store instead, and have begun work on implementing one.

jasonmit commented 9 years ago

Messages is now a convention, but not a requirement. Anything you pass into intl-get is now scoped to the locale model(s) instead of the service.

Important to note, your locale modules must extend ember-intl/models/locale:

import Locale from 'ember-intl/models/locale';

export default Locale.extend({
  // optional, but the default
  messages: {}
});
caridy commented 9 years ago

:cake: