ember-intl / ember-intl Goto Github PK
View Code? Open in Web Editor NEWInternationalization for Ember projects
Home Page: https://ember-intl.github.io
License: MIT License
Internationalization for Ember projects
Home Page: https://ember-intl.github.io
License: MIT License
Once we remove support for < 1.10 we can remove the Ember initializer which handles injecting intl
instance into all popular types (view, controllers, models, components, routes).
Instead, consumers can opt for Ember.inject.service
to optionally inject it:
export default Ember.Component.extend({
intl: Ember.inject.service()
});
This would obviously be a breaking change.
See: formatjs/formatjs@016eafb
/cc @ericf
Likely a bug in ember-cli, but I need to do some investigating and send a PR to fix the issue.
Opening in an issue for tracking.
I know this won't be possible in 1.9 due to the SimpleView being returned but could likely be possible in 1.10 since 1.10 returns streams from all helpers.
This issue is to verify and track and issues.
/cc @mutewinter
Hi,
When formatting message, we are forced to specify the full path: {{format-message (intl-get 'messages.foo.bar')}}.
Can't this actually always assume that messages is the root, so that it allows us to simply refer to message using "foo.bar" instead of "messages.foo.bar" ? :)
I've been following @caridy's discussions on this topic in another thread where he makes the case that subscribing to locale changes to trigger a rerender of the component/helper is not a common pattern.
For example, if the users changes their locale at runtime, any helpers rendered after the change will receive the new locale change. Anything rendered previously will stay rendered on the previous locale. Handling this really complicates the helper logic and there is overhead in subscribing to those changes for each and every helper.
The workaround would be recommending users to reload the view explicitly using a rerender
where they need to immediately reflect the change.
Unfortunately, we cannot begin removing this yet because the application view is not able to rerender. This is demonstrated here http://jsbin.com/ruzuho/1/edit?html,js,console,output (click rerender twice, observe the console while doing so). So, until that bug is fixed within Ember we cannot resolve this issue.
/cc @caridy
format-time: it should return a formatted string
Expected: "1/23/2014"
Result: "1/24/2014"
Both dateStr
and timeStamp
versions of the tests are affected. Replacing GMT-0500 (EST)
with GMT+0100 (CET)
(my local time) fixes for me - doing the reverse in an EST timezone demonstrates the issue.
Both could be fixed by adding timeZone="UTC"
to the template, like:
view = this.intlBlock('{{format-time "' + dateStr + '" timeZone="UTC"}}', {locales: 'en-US'});`
Do you still need Bower for Ember CLI add ons?
support time-zone
which normalize to timeZone
because passing to the underlying Intl API
Is there any way to format number with SI prefix?
As an example how can I format value 12345 to 12.3k.
Hi,
After integrating ember-intl on our application, I rerun our tests and found out that all the integration tests could not initialize the app when using PhantomJS.
The error was always the same: "Can't find variable: Intl".
After some search, I found out that the problem was on the initialization of the Intl service:
setupMemoizers: on('init', function () {
this.setProperties({
getDateTimeFormat: createFormatCache(Intl.DateTimeFormat),
getRelativeFormat: createFormatCache(IntlRelativeFormat),
getNumberFormat: createFormatCache(Intl.NumberFormat),
getMessageFormat: createFormatCache(IntlMessageFormat)
});
}),
In this init function, we use a global variable Intl.
Where does this variable is initialized? Why does it work correctly on Chrome but not on PhantomJS?
Do I miss some imports in my tests ?
Thanks for your help 😄
Changing the application locale in Handlebars does not rerender the views
At the moment I'm unable to write unit tests for components that use of the format-message
and intl-get
helpers in the component template.
Initially, this is what I've tried when just setting the test up:
needs: [
'locale:en-GB', 'helper:format-message', 'helper:intl-get'
]
This results in an exception when calling this.render()
in the actual tests:
TypeError: Cannot read property 'on' of undefined
, the stacktrace points to this line. Which makes sense as 'intl:main'
is missing from the needs block.
I tried adding 'intl:main'
to the needs block:
needs: [
'intl:main', 'locale:en-GB',
'helper:format-message', 'helper:intl-get'
]
Which also resulted in an exception:
TypeError: Attempting to register an unknown factory:
intl:main``.
After digging through the ember-intl source I noticed that the ember-intl initializer sets up the intl service as intl:main
instead of service:intl
. Trying to inject service:intl
in the needs block doesn't work either.
My best guess is that initializers don't run in a (module) unit test, resulting in intl:main
never being registered on the container/app. Because the intl-get
helper injects intl:main
rather than service:intl
, adding service:intl
to the test's need block won't do anything.
At the moment, I don't even care what format-message/intl-get renders, stubbing out whatever format-message
and/or intl-get
needs would work just fine for me as well, I just want to be able to render the component's template without exceptions. (I just don't know how to do this)
My actual question(s):
intl
on intl-get
)?Any answers or pointers in the right direction would be greatly appreciated!
For example, 1.10.0 is the stable we should version this to 1.10.0. When 1.11.0 is released, we make the changes to bring it up to compat. and release 1.11.0.
This eliminates confusion around Ember version requirements.
We were using intl-get in templates like so:
{{intl-get 'messages.key.otherKey'}}
and it would return the message string.
It appears that this no longer works and intl-get returns an object. We now have to change all our code from above to something like this:
{{format-message (intl-get 'messages.key.otherKey')}}
Was the first example above an intended use of intl-get? Or was it always supposed to be used with format-message?
Hi,
I use Ember-CLI 0.2.1 and Ember 1.13.0-Canary.
I need the translation in a Controller.
How can I translate my strings with parameters?
I have read this:
#60
this.intl.getTranslation(key)
But:
{{format-message (intl-get "messages.photos") name=name numPhotos=numPhotos takenDate=takenDate}}
Is there anyway? Or have I still use Ember.String.loc
for my translation?
Regards
Basically no Ember-related i18n library does allow dots in message keys, but I've found relying solely to Ember.get
a bit counter-intuitive. Granted, the implementation is simpler, since it's a core Ember tool to fetch key paths and is working pretty well, but most of the i18n backeds use a key-value store like Redis. Therefore, when fetching the translations from the server, these messages must be un-flattened first to build up a hierarchical JS object structure, something Ember i18n libraries can deal with.
Instead, just serializing a KV table into
{
"product.info": "{product} will cost {price, number, EUR} if ordered by {deadline, date, time}",
"product.html.info": "<strong>{product}</strong> will cost <em>{price, number, EUR}</em> if ordered by {deadline, date, time}"
}
is much more straightforward on the server then the currently required
{
"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}"
}
}
}
While the filesize is somewhat bigger by default, it is negligible when gzipped. Also, the former speeds up message lookups as a byproduct.
As these two semantics are not mutually exclusive (exact key lookup first, then fall back to Ember.get
), I see no disadvantage in supporting both.
In the docs http://formatjs.io/ember/, section "Locale and Format Data", you should be able to define the custom formats per locale using:
I've added a custom date formatter to simply display the short form of a week-day, but that doesn't seem to be being used in a message. It's working with format-date
but not with format-message
.
Here's an example repo containing an Ember app with the code below:
Eg:
export default {
date: {
shortWeekDay: {
weekday: "short"
}
}
};
This is then used in a message:
import Locale from 'ember-intl/models/locale';
export default Locale.extend({
locale: 'en',
messages: {
test: "should be a week-day initial: {day, date, shortWeekDay}"
}
});
When displaying this in a template I'd expect the same date format to be shown:
But instead I get the following:
So the end user's locale is pt-MZ
. The app has strings for pt-PT
and the default en
. So what I think could happen at request/init time the user's locale is resolved into one which the app supports, in this case the process would be:
pt-MZ
? No.pt-PT
.pt-PT
? Yes!So now the app executes with pt-PT
as the resolved locale, and always with en
as the fallback. So if someNewMessage
string hasn't been translated to pt-PT
yet, the default one, en
is used instead.
this.intl.set('locales', ['pt-MZ', 'en']);
will result in a resolvedLocales
computed property (readOnly and private) to become ['pt-PT', 'en']
This will require the CLDR extracter to pull out the parent locale information for all the locales that are not targeted from the application.
Copy/pasting from a conversation I had with @ericf
The end goal, we can support this.intl.set('locales', [navigator.language, defaultLocale])
in its various fallback scenarios based on the information the CLDR data provides.
It's common to render the changes in time as they happen, but infrequent enough to where it isn't disruptive to the user. I propose an option, disabled by default, for intl-relative to periodically re-render itself to display the change in time.
{{format-relative '2/2/2015' interval=5000}}
(milliseconds)
Back fill it to 1.0.0
I just saw this comment by @caridy: formatjs/formatjs#76 (comment) and it spurred a thought that Ember Intl could simply iterate over the locales
array to find the default/fallback locale. This would make defaultLocale
config/prop not needed.
Keeping this opened for tracking.
/cc @ericf
CLDR modules should be generated on build time instead of using generators which make them static and make it difficult to upgrade.
/cc @ericf
@jasonmit whenever we merge a dev branch, delete them :)
I don't have admin access in order to do it. @jlecomte
When displaying currencies in our app, we more or less always want to show 2 decimal points, for cents on all numbers. We can do this with formatNumber by modifying the minimumFractionDigits
attribute. This works well, but there are certain currencies that we don't want decimal points on. Namely, currencies whose base unit is also its smallest unit, like the Yen (and about 13 other currencies).
I actually think this might be a bad "feature" to add to the helper, but maybe some good advice/documentation on how to achieve this would be helpful to others.
My gut says there's a way to "reopen" the helper somewhere in my app, and force defaults for minimumFractionDigits
if they aren't explicitly set. Then I can do the work to know when to set and what to set those defaults to.
Make sense? Can you think of any pretty way to do this?
Here's my relevant code from my programmatic wrapper of NumberFormat, just to give perspective on what I'm doing.
// some setup
const non100UnitDenominators = {
bif: 1, // Burundian Franc
clp: 1, // Chilean Peso
djf: 1, // Djiboutian Franc
gnf: 1, // Guinean Franc
jpy: 1, // Japanese Yen
kmf: 1, // Comorian Franc
krw: 1, // South Korean Won
mga: 1, // Malagasy Ariary
pyg: 1, // Paraguayan Guaraní
rwf: 1, // Rwandan Franc
vnd: 1, // Vietnamese Đồng
vuv: 1, // Vanuatu Vatu
xaf: 1, // Central African Cfa Franc
xof: 1, // West African Cfa Franc
xpf: 1, // Cfp Franc
};
function getUnitDenominator(currency) {
currency = currency.toLowerCase();
return non100UnitDenominators[currency] || 100;
}
And in the actual file.
if (options.style === 'currency') {
// If we have a 'common' currency, which comes in 'cents', force 2 decimal points
if (getUnitDenominator(options.currency) === 100) {
if (typeof options.minimumFractionDigits === 'undefined') {
options.minimumFractionDigits = 2;
}
if (typeof options.maximumFractionDigits === 'undefined') {
options.maximumFractionDigits = 2;
}
}
}
Would love your opinions!
It's complicating the design to support both Handlebars/HTMLBars. Since the features for ember-intl 1 is more or less complete, now is a good time to deprecate 1.9.
I can't figure out how to translate a string passed from the model in a dynamic template that could have various titles.
model.title = 'mytasks'
messages.mytasks 'My Tasks'
I've tried:
{{ format-message (intl-get model.title) }}
and
{{ format-message model.title }}
and
{{ format-message messages[model.title] }}
I think maybe boundProperty might do something, but I can't find any documentation on how it works.
A satisfactory solution would be to translate the property in the model, but i can't figure out how to do translations in JavaScript (outside of a template)
Handlebars - Intl helpers used on the application template breaks on route change.
Error while processing route: *.index 'undefined' is not an object (evaluating 'parentView.connectOutlet'
Ember 1.10.0, ember-intl 1.1.1
Console output
$E.intl.get('messages.phone')
undefined
$E.intl.get
ember.debug.js:32014 function (keyName) {
return get(this, keyName);
}
The above message key "messages.phone" does exist and is output correctly via template code. Trying to use intl.get() in a component or from the browser console (the above example used the ApplicationControler as $E) always returns 'undefined'.
There is an example with boundProperty is the readme for formatMessage but I've been unable to get it to work. Currently have a desire to change text within a couple buttons / headings. I could do it with {{if}}
statements but just saw this and it's just as easy for me to change the message value to look up inside the controller. Just looking for clarification on it's use. Looks like it needs the actual translation object, but I can't seem to track down the way to pull translations using this.intl
(injected).
This is largely for formatjs.io but can be used for any non-ember-cli consumers of the addon.
Hi,
I have a component that generate keys, and I want to use those as bound properties in my template, but it seems it does not work. Here is my template:
the "range.label" is a valid key that exists in my locale config, but I have a Uncaught ReferenceError: Could not find Intl object: range.label error
Thanks!
Has to do with parsing parsing numbers as a currency
Expected:
"$40,000.00"
Result:
"$40,000"
Diff:
"$40,000.00" "$40,000"
While lazy loading is possible today, it takes some implementing on the consumers part to get right. You can read more about the general implementation: #18 (comment)
This proposal is to bake the most likely use case, where you want to lazy load from the asset tree your locales.
This should not be part of ember-intl directly, and instead be an addon which wraps ember-intl. This is because it makes a really bold assumption as to how people store & load their messages and would only overcomplicate ember-intl if implemented directly.
ember-intl/models/locale
but not concatted into app.js and instead written to /assets/locales/<locale-name>.js
addLocaleData
https://github.com/yahoo/ember-intl/blob/e28f857b6ea897216cac0bd2aa803fa42c181606/addon/utils/data.js#L10/cc @bakura10
My current project is using AMD w/ Ember. Thus during dev, we have no build step. Without the ability to load the CLDR data on-demand, I am unable to implement ember-intl
.
Apart from my specific issue though, it would be good to have an option to create Locales and register them as needed during runtime. Say our backend were to have language management, with the ability to add new languages or remove languages. Currently this isn't possible as the full list of languages needs to be included when building the JS.
The following API should be supported.
this.intl.addMessage('en', 'greeting', 'hello');
this.intl.addMessage('fr-FR', 'greeting', 'bonjour');
Push multiple messages. Note: this should do a merge and should not replace the entire locale's message object and should support nested objects.
this.intl.addMessages('en', {
greeting: 'hello',
bye: 'goodbye'
});
Ideally these would be used on ready
, initialize
, or a route hook to push messages to a locale but can happen at any point at runtime.
Inspired from the feedback on https://twitter.com/xeppelin/status/563319454193291264
It would be very helpful to have some documentation showing how to use ember-intl in ember-cli tests. I currently get messages like this when running my tests:
Handlebars error: Could not find component or helper named 'format-relative'
Handlebars error: Could not find component or helper named 'intl-get'
In order to get past these, I stubbed out these methods in my setup method like this:
component = this.subject();
// stubs for ember-intl
component.intl = {};
component['format-relative'] = component.intl.get = function (str) {
return str;
};
But I would rather know how to include the library in the test suite.
Thanks.
TR
{{format-message 'path.to.foo.bar'}}
{{format-message (icu '{{population, number, integer} as of {census_date, date, long}}')}}
format
computed prop out of service (mostly complete, format-message is last one)defaultLocale
. Instead, declared in env configuration (the same config evaluated at build time)registry
in the container. Will require changes to moduleForIntl
translations
(root folder) instead of app/locales
config/environment
messages
object. All translations hang off the exported parent object by defaultEmber.inject.service
, no longer automatic as it's seldom needed and Ember now makes it convenient to inject servicesDue 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:
ember-intl
's semantics to be usable on the clientRelated to #18
ember -v
version: 0.1.15
node: 0.10.35
npm: 2.1.8
Console Output
$E.intl.formatNumber(1000)
intl.js:132 Uncaught TypeError: Cannot read property 'locales' of undefined
intl.js:132 exports.default.ServiceKlass.extend._format
intl.js:123 exports.default.ServiceKlass.extend.formatNumber
VM6635:2 (anonymous function)
VM6491:777 InjectedScript._evaluateOn
VM6491:710 InjectedScript._evaluateAndWrap
VM6491:626 InjectedScript.evaluate
I used the Application Controller for $E above. Not sure if use of this function is supported in controllers, but it looks to me like it is.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.