The challenges of international money in Cocoa

I built Billable for my own needs and it eventually became something commercial. When I first started I made a point to store the money as NSDecimalNumbers to keep all the calculations accurate and later I turned on the “Localize” checkbox on the Number Formatter in Interface Builder which basically will do its best to show the money in the local format of the system. This approach kind of works but is incomplete and clunky. One user who is from Norway reported an issue where they were having trouble entering money values above 999. For the record US money compared to Norway money looks like:

US: $ 1,234.56
Norway: kr 1 234,56

Aside: Sometimes I see that “kr” at the end of the amount (like when I NSLog a string using the number formatter), not sure which one is really Norway proper.

Anyways, I was finally able to spend some time tonight and have reproduced the reported bug. In fact during the process I found another Cocoa developer who ran into the same issue and wrote a recipe to recreate it. (At the end of his recipe he has some IB voo-doo that fixes the bug —- such voo-doo has not fixed the bug for me in Billable thus far).

From yet another post Chris Kane of the Cocoa Frameworks at Apple writes:

With 10_0 behavior formatters, there is an ancient bug where it won’t parse input with the formatter’s own thousands separator in it. That’s not a problem when you’re typing a number greater than 999, because you probably aren’t including the thousand separator. But nowdays, for whatever reason, AppKit parsers and formats the user’s input several times through the formatter, and one of these stages passes the formatter’s output back into the formatter, and the formatter can’t parse it’s own output (depends a bit on how it’s set up).

I think this is what is causing the bug. So, ok the NumberFormatters in IB always use the 10_0 behavior and they are buggy; I’ll just create 10_4 formatters in code and attach them. Well I did that and now run into another problem. That is, creating an attaching a formatter like so:

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setGeneratesDecimalNumbers:YES];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[flatFeeTextField setFormatter:numberFormatter];
[numberFormatter release];

Results in a field that requires the user to type in the actually currency symbol, else they are presented with a “Formatting error.” warning sheet. Ugh.

Unrelated to this specific bug (but on my mind) is the fact that in Japan the yen isn’t decimal based and showing it with the “.00” at the end (which the current formatter does) looks stupid.

As it stands right now I don’t think I’ll be able to fix this Norway bug in 1.0.2 and I feel bad. I also need to start trying to figure out how I want to handle global money in the future. As I posted on the new Billable FAQ yesterday:

Q: Will Billable ever support different currencies per client/service?

A: I’d like to support this. It’s an issue people who for example live in the UK but have clients in the UK, US, and Germany face. I do need to look into it a bit since this type of change will effect other features such as reports and summaries (For example, if a table is showing services in three different currencies how do you show a total?).

So, those are my notes so far. If you got this far you might also want to watch me demo a bug (QuickTime movie) I found in Interface Builder that clobbers your localized NSNumberFormatters should you happen to edit the NIB while not in the US format. Yes this happened to me on the eve of the 1.0 release and took me a while to figure out. Fun fun!

Posted on: October 5, 2006 – 12:48 am

5 Comments

  1. ssp wrote:

    Great to see you running into the bug. Perhaps they’ll take an American complaining about these things more seriously than a mere European - i.e. myself

    I filed this problem in spring (#4467178) but haven’t heard back.

    I just gave the Norwegian setting a quick run in my app and it worked all right. Perhaps I didn’t fully understand the problem. In case this helps you, my setup is the following: I have the number formatters set up in my nib file and set them to not be localised. That’s important because I think it’s just the UI in IB which is overzealously localising the currency signs. Then I connect those formatter to IBOutlets. When loading the nib file I run a [formatter setLocalizesFormat:YES]; to manually make sure the formatters do localise.

  2. Jesper wrote:

    Swedish, Danish and Norwegian proper is to stick “kr” (the name of all three separate currencies) at the end. A choice of tacking the currency unit at the front or on the back of the number is essential if you should implement this.

  3. encro wrote:

    Bernard Teo has encountered similar issues with handling currencies in Luca: http://cutedgesystems.com/weblog/index.php?entry=/Technology/decimals.txt http://cutedgesystems.com/weblog/index.php?entry=/Technology/numberTest.txt http://cutedgesystems.com/weblog/index.php?entry=/Technology/BigDecimals.txt

  4. MickeyC wrote:

    Billable is great app. My wife been using it for about 2 months during the beta cycle. The author (Mike) is responsive to requests and bug reports. The only missing feature is data export/.Mac syncing.
    ————
    MickeyC

  5. Mike,

    I just wrote a blog post on customizing that “Formatting error” alert.

    http://initgraf.blogspot.com/2007/11/customizing-errors-generated-by.html

Post a Comment | Comment RSS feed