membermatters / MemberMatters

An open source membership, access and payments portal for makerspaces and community groups.
https://membermatters.org
MIT License
40 stars 23 forks source link

[WIP] Currency Localisation #188

Closed proffalken closed 1 year ago

proffalken commented 1 year ago

In order to use Member Matters here in the UK, we need to be able to switch to GBP/£.

Given that we also don't want to maintain a UK-specific fork of the project, this PR should allow us to set a currency in the backend via Constance and have it cascade through the various screens automatically.

At present, the code has been updated and the currency variable is available within the Django Admin pages, however making a change to it does not appear to make a difference to the values displayed on screen.

jabelone commented 1 year ago

Heya, thanks for taking the time to do up that PR!

Looks like you've found one of the few spots I haven't made internationalisation friendly yet (we're sending a hardcoded English message straight from the backend!). That being aside (which we can ignore for now), there's a few more places you'll likely have to make changes.

The frontend is what does most of the UI rendering. We use vue-i18n for internationalisation support on the frontend. Whilst we currently only support Australian English, most of the work is already done to support other locales (languages and number/date formatting etc.). An example of the frontend rendering a currency using vue-i18n is frontend/src/components/Billing/PlanCard.vue.

The proper way to do this is to implement it with the vue-i18n library as some currencies have more complex formats than a simple {{config.CURRENCY_SYMBOL}}{{amount}} can handle. I'm evidently guilty of doing this too, but generally string interpolation is a bad way of doing stuff like this.

After a quick look through that and other components, it looks like I had the foresight to use $n() from vue-i18n to render the front-end currencies. This means all it should take is for the frontend to update the current locale config and the currency should be rendered with the correct symbol and format. The documentation for the $n() method is here for reference and may be worth a read. This function basically takes your number and outputs it in the correct format depending on the locale that's set.

In essence, to properly support other currencies (and languages too) you'd have to: 1) add a way to auto detect the user's locale (seems pretty simple - and less work than having a user configurable option). 2) tell vue-i18n to use the user's locale (also seems reasonably simple). 3) that's it I think, although there may be a couple spots that need updating to use the $n() method.

Let me know how you go, and I may have a go at this if I find some time this week.

jabelone commented 1 year ago

Forgot to mention, the reason you're not seeing it update with your current change is because the views.py file you changed is only responsible for returning a handful of error messages to the front end. It's not actually responsible for rendering any of the frontend components responsible for showing the currency amounts. Hope that makes sense!

jabelone commented 1 year ago

I couldn't help myself and jumped in there just now. Looks like it was only slightly more complex than I thought. Take a look at the most recent commit to the dev branch (link), but that should implement support for detecting the browser's locale and rendering the correct language/number format. Give it a go and let me know how it goes for you!

All that needs to happen for new languages now is a new translation definition (+ translations) and the number format needs to be added.

Screen Shot 2022-08-29 at 9 37 26 pm
proffalken commented 1 year ago

This looks great, I'll find time to test in the next few days.

I'm more than happy at home with Python but I've not used Vue before so it might take me a bit to get my head around it at first!

jabelone commented 1 year ago

No problem. I'll close this in favour of #185 as that issue is the best place to track this discussion I think. Hopefully this should be enough to get you folks up and running.