Saturday, August 11, 2012

How to deal with inconsistent display of characters with diacritics on the web

A friend asked me to build a web site, targeted to Romanian visitors. Romanian language has some characters with diacritics, as documented in Wikipedia:
Romanian uses a breve on the letter a (ă) to indicate the sound schwa /ə/, as well as a circumflex over the letters a (â) and i (î) for the sound /ɨ/. Romanian also writes a comma below the letters s (ș) and t (ț) to represent the sounds /ʃ/ and /t͡s/, respectively.
 So I thought I'd use a UTF-8 encoding for the HTML, together with some fonts that support those characters and this should be easy enough. To my surprise the results were pretty bad:


Here I have 5 paragraphs, showing the same text, each with a different font. First 2 are fonts downloaded on demand from Google ('Arvo' and 'Noticia Text'). The following 3 are stock fonts ('serif', 'sans-serif' and 'Verdana'). You can see that the stock fonts are failing badly, as marked with red. Those characters are either over or under-sized, relative to the others (they should have the same x-hight). The first 2 fonts aren't much better, since they fail in other contexts, depending on the size of the font chosen. So this yields the first insight - changing the font size may smooth out such issues. To check this I focus on the paragraph in the blue box and I tinker with the 'font-size' CSS selector. Seems to work:


The 4th paragraph looks better now. Applying the same trick in another context fails miserably:



That's using the 'serif' font, and on Mozilla it would fail regardless of the chosen size (at least on Windows XP). Incidentally, the same combination works perfectly on Safari on OS X, at any size:


Going back to Mozilla, if I change the 'font-family' to 'Arvo' it works fine (while that same combination would break in Safari):


To make matter worse, the initial set-up that would fail on Mozilla on Windows XP works fine on Mozilla on OS X:


Yet the same change in font-family that made it work on Mozilla on Windows XP brakes it on Mozilla on OS X (you can't make this up):



To get this right you need to test different combinations of 'font-family', 'font-size', browser and OS. I guess the biggest surprise for me was that for the 2nd paragraph, even if I used 'Noticia Text', included though @font-face from Google web fonts, which contains all glyphs with diacritics that I was looking for, it still failed to display properly on Windows. Doesn't that defeat the whole purpose of @font-face ?

So there you have it, another type of cross-browser inconsistencies that we must be aware of, together with the usual workarounds involving serving browser-specific CSS, consolidated in included files that can be applied to the whole site.

Saturday, August 04, 2012

Spare your users the high cost of data roaming

You may have heard reports from the media, regarding the high cost of roaming charges that some people incurred. It's really no surprise, as some network carriers are practicing predatory pricing every time you leave the borders of their home country.



Although the end users are ultimately responsible for those charges, we, as developers, should strive to warn them when they're about to do some data transfers while using the apps we developed, if they're likely to be roaming at the time.  That would help people that haven't turned off data roaming, through the settings provided by iOS.



The problem is that AFAIK there's no API exposed by iOS to determine if the user is roaming. So we'll need to get creative. First off, we have the SystemConfiguration.framework, which allows us to determine whether a Wi-Fi or cellular connection is in use. If it's the former, we have a non-issue. There won't be any roaming charges for Wi-Fi connections. If it's the latter we need to dig deeper. We could use the CoreLocation.framework to determine the current location of the device.



Then we could use NSLocale and its ability to determine the county code of the current locale (likely established when the device is first set up).



If the country of the locale differs from the country of the current location, there's a high probability that the user is roaming, so we could warn them about potential charges before any data transfer is initiated by the app.

This heuristic is not fool-proof, but it's better than nothing, and it can go a long way towards preventing some unwanted charges. An alternative is to track changes in the country reported by the core location framework and use that as a hint of possible roaming. A possible complication may be caused by the user not authorizing the app for location lookups. There's a way around that, which I'll explore in a future blog post.

The best approach would be to have an API to tell precisely when a user is roaming, and better yet, the data rates for that particular destination, but that will be the topic for another blog post.