Skip to content
This repository has been archived by the owner on Jul 2, 2018. It is now read-only.

[MNY-24]: Language localized formatted string #26

Merged
merged 24 commits into from
Nov 23, 2015

Conversation

danthorpe
Copy link
Owner

Representing MoneyType in a suitable locale.

@codecov-io
Copy link

Current coverage is 100.00%

Merging #26 into development will not affect coverage as of 9faba9f

@@            development     #26   diff @@
===========================================
  Files                12      14      +2
  Stmts               676    2109   +1433
  Branches              0       0        
  Methods                                
===========================================
+ Hit                 676    2109   +1433
  Partial               0       0        
  Missed                0       0        

Review entire Coverage Diff as of 9faba9f

Powered by Codecov. Updated on successful CI builds.

@danthorpe
Copy link
Owner Author

This PR adds functionality to get a formatted string for MoneyType using an arbitrary locale identifier. This makes it possible to have say USD money, but get a localized description for a Spanish speaking country for example.

let dollars: USD = 99

// Will use the current locale of the user
print("You have \(dollars)")

// Will use the locale for a Spanish speaking Spaniad
let formatted = dollars.formattedForLocaleId("es_ES")
print("She has \(formatted)")

For an user with English language, in the United Kingdom (en_GB), this will print out:

You have US$99.00
She has 99,00 US$

Changing the device to Spanish language in Spain region (es_ES), it will print out:

You have 99,00 US$
She has 99,00 US$

The problem with this, is that it's a little unsafe to use strings. So, I've added a Locale type. This is an enum and provides type safety and type completion. You can use it like this...

// Will use the locale for a Spanish speaking Spaniard
let formatted = dollars.formattedForLocale(.Spanish(.Spain))
print("She has \(formatted)")

For a device in English language in United Kingdom region (en_GB), it will print out the same as before:

You have US$99.00
She has 99,00 US$

For a device in German language in Switzerland region (de_CH), it will print out:

You have US$ 99.00
She has 99,00 US$

Notice how the en_GB formatted string does not have a space between the $ sign and the first digit, but the de_CH does. The es_ES places the symbol after the digits. And the grouping and decimal strings are different.

Now, I think in most use cases, this is totally unnecessary, as in the vast majority of time you want to display values using the user's current language and region settings. But on the other hand, I think being able to explicitly state what locale you want to use is pretty neat.

Note also, that I am a Brit living in London, and this framework is written in English (en_GB) however, the type names for the Locale (and the nested countries) are generated from the en_US locale.

Anyone got any thoughts on this? /cc @mrdavey.

*/
func formattedWithStyle(style: NSNumberFormatterStyle, forLocale locale: Locale) -> String {
return Currency.formattedWithStyle(style, forLocale: locale)(amount)
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

These changes represent the API for localized string formatting that I'm going with. At the moment, the only thing left to sort out is to update the unit tests.

In usage, this works pretty much as you would expect. For normal circumstances, i.e. current device locale - use .description and formattedWithStyle(_: NSNumberFormatterStyle). Like this:

print("current locale id: \(NSLocale.currentLocale().localeIdentifier)")
let money: Money = 99.99
print("The amount is: \(money)")
print("She has \(money.formattedWithStyle(.CurrencyPluralStyle))")

This will print out whatever the device's local currency is, using the device's current locale.

For an American in Russia:

current locale id: en_RU
The amount is: 99,99 RUB
She has 99,99 Russian roubles

For a Spaniard in Russia you get:

current locale id: es_RU
The amount is: 99,99 RUB
She has 99,99 rublos rusos

Lets say you want to use, whatever the local currency is, but you want to format strings for a specific locale. We can change the description to use code like this:

print("The amount is: \(money.formattedWithStyle(.CurrencyStyle, forLocale: .German(.Switzerland)))")
print("She has \(money.formattedWithStyle(.CurrencyPluralStyle, forLocale: .Chinese(.China)))")

For the American, you get:

current locale id: en_RU
The amount is: RUB 99.99
She has 99.99俄罗斯卢布

Which is the same as for the Spaniard, (as expected):

current locale id: es_RU
The amount is: RUB 99.99
She has 99.99俄罗斯卢布

There are a couple of limitations with this.

Essentially any custom currencies will not get the fantastic localization support here for the .CurrencyPluralStyle. I don't think it's possible to provide NSNumberFormatter with the translations to do this. So, for Bitcoin (BTC) using this style will use whatever the name of the local currency is.

Likewise, if you have your own in-app currency, avoid the .CurrencyPluralStyle style.

The Locale parameter is an auto-generated enum using US English case names. Think of it like .Language(.CountryWhichSpeaksThatLanguage). In some cases, there is only one country which speaks that language, in which case there is no associated value.

@danthorpe danthorpe changed the title [MNY-25]: Language localized formatted string [MNY-24]: Language localized formatted string Nov 23, 2015
@danthorpe
Copy link
Owner Author

Fixes #24

danthorpe added a commit that referenced this pull request Nov 23, 2015
…ption

[MNY-24]: Language localized formatted string
@danthorpe danthorpe merged commit 79d3787 into development Nov 23, 2015
@danthorpe danthorpe deleted the feature/MNY-25_localized_description branch November 24, 2015 00:06
@mrdavey
Copy link

mrdavey commented Nov 24, 2015

This is great @danthorpe . Very flexible and covers all the use cases I have come up with 👍

@danthorpe
Copy link
Owner Author

@mrdavey okay, great. in which case, I'll close #24.

I'm just sorting out some documentation issues, and then I'll release 1.4.0 which will include these changes.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants