Giter Club home page Giter Club logo

handlebars-intl's Introduction

This library provides Handlebars helpers for internationalization. The helpers provide a declarative way to format dates, numbers, and string messages with pluralization support.

npm Version Build Status Dependency Status

Sauce Test Status

This package used to be named handlebars-helper-intl.

Overview

Handlebars Intl is part of FormatJS, the docs can be found on the webiste: http://formatjs.io/handlebars/

Features

  • Display numbers with separators.
  • Display dates and times correctly.
  • Display dates relative to "now".
  • Pluralize labels in strings.
  • Support for 200+ languages.
  • Runs in the browser and Node.js.
  • Built on standards.

Example

There are many examples on the website, but here's a comprehensive one:

{{formatMessage (intlGet "messages.post.meta")
    num=post.comments.length
    ago=(formatRelative post.date)}}
var context = {
    post: {
        date    : 1422046290531,
        comments: [/*...*/]
    }
};

var intlData = {
    locales : ['en-US'],
    messages: {
        post: {
            meta: 'Posted {ago}, {num, plural, one{# comment} other{# comments}}'
        }
    }
};

var template = Handlebars.compile(/* Template source above */);

var html = template(context, {
    data: {intl: intlData}
});

This example would render: "Posted 3 days ago, 1,000 comments" to the html variable. The post.meta message is written in the industry standard ICU Message syntax, which you can also learn about on the FormatJS website.

Contribute

Let's make Handlebars Intl and FormatJS better! If you're interested in helping, all contributions are welcome and appreciated. Handlebars Intl is just one of many packages that make up the FormatJS suite of packages, and you can contribute to any/all of them, including the Format JS website itself.

Check out the Contributing document for the details. Thanks!

License

This software is free to use under the Yahoo! Inc. BSD license. See the LICENSE file for license text and copyright information.

handlebars-intl's People

Contributors

apipkin avatar backflip avatar caridy avatar drewfish avatar ericf avatar jasonmit avatar juandopazo avatar okuryu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

handlebars-intl's Issues

Issue with a plural in 'ru' locale

Hi,

i have an issue with plural in ru locale, example:

Здесь {n,plural,=0{котов нет} =1{есть один кот} one{# кот} few{# кота} many{# котов} other{# кота}}!

if n = 101, should work 'one' and result must be a '101 кот', but work 'other' and result is '101 кота'

I check it on PHP Yii2 Framework, and it's work perfect for 'ru' locale

And i found some helpful links
(http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html#plural)
(http://intl.rmcreative.ru/tables?locale=ru)
(http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html#ru)

Can you help me please ?

P.S. I'm sorry for my awful english :(

How to capitalize month

With the italian locale it-IT, I use {{formatDate date "long"}} to print my dates.
In this way, months are printed with the first letter lowercase but I would like to have them capitalized like in the english locale en-EN (by the way, why this difference?).
So I would like to get 12 Settembre 2016 instead of 12 settembre 2016.
Is that possible?
Thank you.

handlebarsIntl is undefined

Hi all,
I'm experiencing an issue with the implementation of handlebars-intl with some browser. The browser are Internet Explorer 9 (IE 11 works) and Safari.
The problem is that handlebars-intl is not loaded and the console log both for IE and Safari reports that handlebarsIntl is undefined. As declared in the docs, in order to support older browser intl.js must be loaded and this has been done.
This is the way I include the code:

<script src="widget/jquery.js"></script>
<script>
          $.noConflict();
          // Code that uses other library's $ can follow here.   
</script>
<script src="app/semantic.min.js"></script>
<!-- support to Intl for IE and old browsers -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
<script src="app/handlebars.js"></script>
<script src="app/handlebars-intl.min.js"></script>
<script src="app/locale-data/it.js"></script>
<script src="app/locale-data/en.js"></script>
<script src="app/locale-data/fr.js"></script>
<script src="app/locale-data/es.js"></script>
<script src="app/app.js"></script>

Any suggestion would be greatly appreciated.

Why am I getting (US$) and not ($)

I'm using

"email-templates": "^2.5.4",
"handlebars": "^4.0.6",
"handlebars-intl": "^1.1.2",
"handlebars-layouts": "^3.1.4"

This is how I'm formatting

{{formatNumber price style="currency" currency="USD" locales="en-US"}}

And here's my js file

const handlebars = require('handlebars');
const handlebarsIntl = require('handlebars-intl');

handlebarsIntl.registerWith(handlebars);
handlebars.registerHelper(layouts(handlebars));
handlebars.registerPartial('layout', fs.readFileSync(`public/email-template/layout.hbs`, 'utf8'));

var intlData = {
  locales: 'en-US'
  // I also tried to follow this: https://formatjs.io/handlebars/ (Using Named Number Formats)
};

var newsletter = new EmailTemplate(path, {
  data: { intl: intlData }
});
handlebars.registerPartial('data', { intl: intlData });

newsletter.render({ params: { ... }, data: { intl: intlData } }, function (err, result) {
  if(err) { return reject(err); }
  return resolve(result.html);
});

Everything that I tried, or nothing happens or I got this error

ReferenceError: Could not find Intl object: formats.number.USD at intlGet (E:\www\unclehub\v0.2.2\api\node_modules\handlebars-intl\lib\helpers.js:96:23)

TypeError: Cannot read property 'escapeExpression' of undefined

After installing:
julianb-HP-14-Notebook-PC:~/Projects/bigla/shopping-cart$ npm i --save handlebars-intl
[email protected] /home/julianb/Projects/bigla/shopping-cart
└── [email protected]

Crashed app:
julianb@julianb-HP-14-Notebook-PC:~/Projects/bigla/shopping-cart$ npm start

[email protected] start /home/julianb/Projects/bigla/shopping-cart
nodemon ./bin/www

[nodemon] 1.11.0
[nodemon] to restart at any time, enter rs
[nodemon] watching: .
[nodemon] starting node ./bin/www
/**home/julianb/Projects/bigla/shopping-cart/node_modules/handlebars-intl/lib/helpers.js:22
escape = Handlebars.Utils.escapeExpression;
^

TypeError: Cannot read property 'escapeExpression' of undefined
at Object.registerWith (/home/julianb/Projects/bigla/shopping-cart/node_modules/handlebars-intl/lib/helpers.js:22:39)
**
at Object. (/home/julianb/Projects/bigla/shopping-cart/app.js:15:16)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object. (/home/julianb/Projects/bigla/shopping-cart/bin/www:7:11)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:418:7)
at startup (bootstrap_node.js:139:9)
at bootstrap_node.js:533:3
[nodemon] app crashed - waiting for file changes before starting...
^C
julianb@julianb-HP-14-Notebook-PC:~/Projects/bigla/shopping-cart$

intlGet could not find Intl object

Hi
When I tried to use FormatJS with RequireJS, I encounter this problems.
my code is like:
in a.hbs
{{intlGet "a"}}
in a.js
this.$el.html(this.template(this.model.toJSON(),{data:{intl:{"a":"b"}}}));

I got an error : could not find Intl object "a".
And I track the error, I found in handlebars-intl.js intlGet is a function with 2 variables.
function intlGet(path, options){...}

So when I track in it, i found options are empty object.It lead to the error. How should I setting this options if it can't be parse by this.template({},options)?

Expose IntlMessageFormat constructor is dist bundle

The dist bundle for browsers does not provide access to the IntlMessageFormat constructor, which means that people cannot optimize their usage of this package without also including intl-messageformat on the page.

To avoid code duplication, we can expose the intlMessageFormat constructor along side the registerWith() function for the dist bundled version of this package.

Setting the locale of Handlebars Intl using Express

I'm using express, express-handlebars and handlebars-intl and I would like to change the default "en" locale to another (like "it").

I read that this plugin uses Intl.DateTimeFormat to formats. In this specific case how can I edit things like locale, timezone, date formats, etc..

    const hbs = exphbs.create({ extname: '.hbs' });
    app.engine(hbs.extname, hbs.engine);
    HandlebarsIntl.registerWith(hbs.handlebars); // Handlebars Intl Plugin
    app.set('view engine', hbs.extname);
    app.set('views', path.join(__dirname, './views/pages'));

Final goal:

Correctly renders with Handlebars this datetime {{formatDate time}} using my specified locale

Using `formatMessage` in a loop construct

There doesn't appear to be a way to use the formatMessage directive in a loop construct with messages containing variable numbers of arguments. For example, I have an array containing messages, however, each message does not take the same arguments:

{{#messages}}
  {{formatMessage (intlGet messageText)
      num=??
      ago=??}}
{{/messages}}
var messages = [
  { messageText: "Welcome, {user}!" },
  { messageText: "How are you today, {firstName} {lastName}?" }
];

Is it possible to handle dynamic arguments with the formatMessage directive?

bower package

I cant find bower package.

Does that mean it can only be used on a Node.js server?

Rename global to `HandlebarsIntl`

The current global that this package creates in the browser is HandlebarsHelperIntl, I think this should be renamed to: HandlebarsIntl.

How to change value after load ?

Hello guys,

I'm trying to change the value displayed to the user after he changed some inputs. Specifically, a date input is changed, and then the date displayed under it should change as well.

The date under it uses the helper formatTime to set the date to the right format for user, according to his language and everything. But I don't succeed into changing it. If I try to call in my JS :

Handlebars.helpers.formatTime(values.reminderDate + "T" + values.reminderTime + ":00")

it gives me the error

Uncaught TypeError: Cannot read property 'data' of undefined

So I thought about using a partial or even a dedicated template just for it, but it seems overkill... Am I missing something ?

Thanks a lot ahead !

formatNumber: only a number is accepted

formatNumber helper explicitly verifies the type of a value and throws an exception if it's other than number. But Internationalization API Specification doesn't put such a restriction and Intl.NumberFormat().format() function accepts the argument of any type. So the following examples are perfectly legitimate:

const format = new Intl.NumberFormat().format;
format('1234.56'); // ==> 1,234.56
format({valueOf: () => 56789.01}); // ==> 56,789.01
format(new Date()); // ==> 1,476,977,151,388

I would also expect from this helper to accept a value of any type.

Thank you.

formatMessage with intlGet lookup fail on context sub properties

It seems that using dot notation in formatMessageparameters won't work in combinaison with intlGet.

This works: {{formatMessage "Welcome {name}" name=user.name}}
This don't: {{formatMessage (intlGet "messages.welcome") name=user.name}}

Without the dot notation, both work.
This works: {{formatMessage "Welcome {name}" name=name}}
This too: {{formatMessage (intlGet "messages.welcome") name=name}}

Fill in "Usage" section of README

This is looking great, but the "Usage" section of the README is empty! Please help us out and tell us how to use these helpers! In particular, I would like to see covered:

  • The actual intl helper syntax
  • YUI integration
  • How to go about loading language files (on both the server and client)

Thanks!

Translation using the default locale file

Hello guys.

I really like the library, I think is great, but I'm having a bad time trying to get a translation working. For example, I have the following:

In my template I'm using:

 {{formatMessage (intlGet "messages.test")}}

In my locale file I have something like:

HandlebarsIntl.__addLocaleData({"locale":"en", "test":"it works", "messages": { "test": "it works" }, 
...

Is this should work? I don't know if I'm missing something.

ember most recent version support something similar: https://github.com/yahoo/ember-intl/tree/2.0#intl-get

Remove support for `hash.intlName`

The only reason hash.intlName was added was to get around Handlebars subexpression bugs. It should first be determined if these Handlebars bugs have actually been fixed.

Global setup

This may sound stupid, but I cannot find a proper answer in the docs.

Looking at how translations are supposed to be given to templates, I've read this:

Setup one of FormatJS's integrations with the following data (the user's current locale, translated strings for that locale, optionally, any custom formats)

Looking to handlebars integration, I cannot figure out where I have to set the locale, translated strings and so on. In other words, where does intlGet find its lookup messages?

To be crystal clear: does intlData has a messages attribute? I don't find it in the source. And does the engine expects every template call to provide the locale, messages and so on? This seems tough.

Bonus question: when a message has no configuration — Welcome on board — is there a shortcut for the call {{formatMessage (intlGet "messages.welcomeOnBoard")}}? Thanks.

Add release notes

There have been major changes in this package since v0.1.0, we need to add release notes.

Invalid date

Hi,

handlebars-intl.js -> formatDate function and similar. This functions accept "date" as parameter and create new Date object like: date = new Date(date);

If "date" will be 2016-08-18 in FF it will work, but it fail in safari, since safari doesn't support "-" in date. Valid format for safari is 2016/08/18.
So at the moment it works in one browser, depend on date format.

Regards,
Max

Support for padding currency values

Currently if you use the currency helper on a value such as 123.00 it will format it as $123 and 123.30 will be formatted as $123.3. However when displaying currency you almost always want two decimal places. Is there a way to do this?

Missing Variables Raise an Error and Cause the Entire Template to Fail to Render

Normally with Handlebars, a missing variable will result in nothing rendered and no error. For example if there is no variable x, and {{x}} is used in the template, then it will be as if the {{x}} was never included. However, if using an intl helper such as {{formatDate x}} or {{formatNumber x}} and there is no variable x, then an error will be raised, and the entire template will fail to render. Is this intentional? Can the helpers instead just render nothing? Perhaps those functions should start with something like:

if(typeof(arg)=="undefined") return "";

Update unit tests to test helper functions not the Intl APIs

The current unit tests basically test the Intl APIs to death, but the Intl APIs should be mocked and we shouldn't worry about them much at this level. Instead, the unit tests for this package should be focused on the functions it adds, and to make sure it's calling into the Intl APIs correctly.

Programmatic Access

I'm using this for internationalizing my handlebars templates and it works great, but I also have a few strings in javascript that I can't move into a template. I'd like to be able to internationalize these with a programmatic interface. It seems I have to include intl-messageformat by itself in order to do this, even though handlebars-intl includes it already. It seems wasteful to include it twice, why can't I reference intl-messageformat through handlebars-intl?

Problem when setting locale

Hi,

I'm trying to make this library works, but I have a few issue. As of today, I only have "en" locale, however everything is rendered according to my browser locale (French), excepting on Safari where the polyfill is loaded with only "en" locale. I'd like to set the default language application wide, but cannot find anyway to do it. The only way I've found is to surround any helper with the intl block helper, with locales to "en", but this is annoying as it basically requires me to wrap the whole page around this block helper.

I'd prefer to pass the language directly (if it's not possible to modify the used locale glboally) directly to helper, like this:

{{formatNumber 5 locales="en"}}

But this syntax does not seem to work. Any hint?

Thanks!

Break out helpers into individual exports

I was trying to use this library earlier with Ember CLI, but ran into some issues. One of the biggest limitations of this library right now is how all of the helper functions are stuck within registerWith.

For Ember, I need to be able to modify out registerWith to call Ember.Handlebars.registerBoundHelper rather than just registerHelper, or otherwise the data-binding won't cause a re-render when a model changes.

The best way for me to implement this would probably be for HandlebarsIntl to break out the helpers away from the registerWith function, and have them each be exported. Then, it'd be a lot easier for me to import them and create a separate dist package just for Ember in a build step.

Currency formatting incorrect when no 'cents' in value.

I am trying to use the helper in a partial, but if we pass a value such as 100.00 to the helper, we are given a value of $100 when it should be $100.00. How do I fix this? If I have a non-zero value in the decimal places, ie: 100.30 there is no problem, the value is formatted correctly. I have tried setting the locales explicitly and ensured that a float not an integer is being passed to the helper (although, this should probably work with an integer as well.

Please advise.

Dates interval with format long: do non repeat year

I have 2 dates in order to create the following message:

{From {startDate, date, long} to {endDate, date, long}}

That's nice, but is that possible to avoid the year repetition if it is the same for startDate and endDate?
For example now I get From May 19, 2016 to May 23, 2016 and I would like to have From May 19 to May 23, 2016.
If this is possible, how to get it?
Thank you.

Time Zone support

not familiar with the helper but you need to pass the TimeZone to IntlDateTimeFormat always, so either timezone comes from context or in the helper they always pass the timezone.

each site (Mexico, Brazil, USA) use a default timezone, of course if they don't provide it then you can use UTC.

intlMessage with some locales always returns plural

If I have a zh-Hant-HK string like:

"TOTAL_DISCUSSIONS = {count, plural, one {1 個討論於} other {# WRONG}}"

and pass in any value (including 1) I always get "# WRONG" as the result.

This works for other locals, like en-US, fr-FR, es-MX, de-DE, it-IT, pt-BR.

It DOES NOT work for locales like zh-Hant-HK, vi-VN, ko-KR

Handlebars-helper-intl test failures

Looks like there are some stable test failures which may be in the higher level intl-messageformat since there's not been a code change in handlebars-helper-intl.

Investigating:

31 passing (124ms)
  3 failing
  1) Helper `intlMessage` should return a formatted string with formatted numbers and dates:
      + expected - actual
      +"Atlanta has a population of 5,475,213 as of Jan 1, 2010."
      -"Atlanta has a population of 5,475,213 as of January 1, 2010."


  2) Helper `intlMessage` should return a formatted string with formatted numbers and dates in a different locale:
      + expected - actual
      +"Atlanta has a population of 5.475.213 as of 1. Jan. 2010."
      -"Atlanta has a population of 5.475.213 as of 1. Januar 2010."


  3) Helper `intl` should provide formats for intlMessage:
      + expected - actual
      +"oranges cost $40,000.00 (or €40,000.00) if ordered by Jan 23, 2014"
      -"oranges cost $40,000.00 (or €40,000.00) if ordered by January 23, 2014"

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.