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

Implement Spree.formatMoney using accounting.js #1745

Merged
merged 5 commits into from
Feb 28, 2017

Conversation

jhawthorn
Copy link
Contributor

@jhawthorn jhawthorn commented Feb 24, 2017

This adds a Spree.formatMoney(amount, currency) helper for our JS components to use. The goal is for it to format money identically to how ::Money#format does server-side.

We dump information about all supported currencies from Money::Currency.all to a JSON hash. This JSON stores the symbol, number of decimal places, and format (symbol first or last) for each currency.

This information is used to call accounting.js's formatMoney with appropriate arguments for the currency.

Spree.formatMoney(10, 'USD')
"$10.00"
Spree.formatMoney(10, 'EUR')
"€10.00"
Spree.formatMoney(10, 'JPY')
"¥10"
Spree.formatMoney(10000, 'USD')
"$10,000.00"

Why not Intl.NumberFormat ?

Originally I had wanted to implement this using the ECMAScript Internationalization API, but that had a few issues:

  • Formatting was inconsistent between ruby ::Money#format and JS Intl.NumberFormat ($10.00 vs CA$ 10.00). If we want to be able to use this to replace or enhance existing non-interactive components, they need to be identical.
  • PhantomJS (even 2.1.1) doesn't support the ECMAScript Internationalization API at all.
  • The full polyfill, https://github.com/andyearnshaw/Intl.js/, is huge, about 600k. It's much smaller if only the current locale is included, but that presents its own challenges.

Copy link
Member

@tvdeyen tvdeyen left a comment

Choose a reason for hiding this comment

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

I like this very much. A great step forward for I18n in this project. Thanks for working on this. And as always a very neat solution without much impact and code to maintain 👌🏻

There is one change needed for the way we store the Money data, but that aside 👍

format
]]
}.to_h.to_json
%>;
Copy link
Member

Choose a reason for hiding this comment

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

We can't store this information like this as Sprockets won't pick up changes to Money settings while compiling new assets. Means, every time you change a Money setting you have to delete the assets on the server and force recompilation.

To avoid this, we need to store this information in a html.erb file, like we already do for the JS translations data (backend/app/views/spree/admin/shared/_translations.html.erb)

Copy link
Contributor Author

@jhawthorn jhawthorn Feb 27, 2017

Choose a reason for hiding this comment

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

A fair point, I hadn't considered them changing often enough to warrant this, but I suppose if they were changed at all the existing method would be a pain to deploy with confidence.

I've pushed up a change which combines this and the existing translations into a _js_locale_data partial

js_result = page.evaluate_script("Spree.formatMoney(#{money.to_d}, '#{currency}')")

expect(js_result).to eq money.to_s
end
Copy link
Member

Choose a reason for hiding this comment

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

I actually find this a very good way to test this. 👍

Copy link
Member

@tvdeyen tvdeyen left a comment

Choose a reason for hiding this comment

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

Thanks. I think we should add a CHANGELOG entry as we moved around files.

@@ -32,7 +32,7 @@

<%= javascript_include_tag 'spree/backend/all' %>

<%= render "spree/admin/shared/translations" %>
<%= render "spree/admin/shared/js_locale_data" %>
Copy link
Member

Choose a reason for hiding this comment

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

Good idea 👌🏻 Much more convenient.

This deserves a CHANGELOG entry though, as people may have modified one of these files. Even deface overrides will not work anymore as the file name changed.

This is going to include currency data as well. This makes the scope and
purpose of the file more clear.
This allows us to pick up configuration changes the RubyMoney
currencies.
@jhawthorn
Copy link
Contributor Author

Thanks. I think we should add a CHANGELOG entry as we moved around files.

Done

Copy link
Member

@tvdeyen tvdeyen left a comment

Choose a reason for hiding this comment

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

👍🏻

@jhawthorn
Copy link
Contributor Author

jhawthorn commented Feb 28, 2017

Can't run test on CircleCI because of AWS issues, but this is passing locally (and was passing before adding CHANGELOG and a rebase)

:shipit: 🔥

@jhawthorn jhawthorn merged commit 757a7fe into solidusio:master Feb 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants