A notch above a monkey

News at seven - javascript i18n that almost doesn't suck

Holidays are closer with each day and it’s getting harder and harder to concentrate on work, when your mind is occupied with loot coming your way.

It’s also a time of the year when web sites are filled with various summations of year left behind and always present guesses about the future. I certainly am not above that and I’ll probably add a line or two of my own in next few days, but I also wanted to finish my little javascript i18n library before the year ends. I don’t want it to turn into a pumpkin at midnight like some girl’s ride back home.

You know, sort of a present for everyone as it befits this holiday.

Alas, it’s taking longer then planned. So many things to do and so little time. Since trip to Stockholm is just around the corner, I decided to release what I believe by now to be practically usable piece of localization code. If you’re interested just in the goods, then you can see new javascript file here and demo here .

There have been few changes since last time . The whole thing has been objectified, but I kept few functions ( stripStr , stripStrML and new one printf ) outside of a class, since they’re too general to belong there. Nice thing about new class is that instead of looking for globally defined translation dictionary, it’s initialized with one. This also means you can use more than one translation object or translation dictionary per page, which sounds cool even if not all that useful.

I made a small correction to method toEntity . A bug was pointed out to me by Opera browser , which is a great browser for testing against standards, if not common sense. I might think it’s OK to fetch a character out of a string with their index value, as you would fetch an element from a list or an object, but I would be wrong. That’s why a string method charAt was defined and if working everywhere except in Opera is not good enough for you, then you must use this method. So, I did.

I also renamed the function _ . It’s a nifty name widely used in other languages, but it doesn’t work quite like that when it’s a method in an object. init.js demonstrates how you can still use it by defining an anonymous function.

This is it for now. I think the library is actually usable, but it’s also lacking few things. printf provides now a method of easily stitching stings together and even using parameters in translations. However, it does require that those parameters are listed in same order as in original text. Better than previously, but still often awkward.

What’s missing is also a tool to translate between javascript dictionary/object and a widely used translation format like GNU’s gettext . I’m currently working on this and I hope to have something usable ready in next few days.

Last but not least, it needs a useful documentation on how to use it and work with it. It will get it.

Update: It turns out my code might be usable, but it’s certainly not good. Some issues were listed in later post and some I discovered just recently. For instance it won’t work if you’re trying to translate text on buttons or if text to be translated includes HTML tags (case of tags is not preserved in DOM tree, which wouldn’t be a problem if Firefox and IE defaulted to the same one).

In defense of a regular user

I used to be a part-time system administrator and have a few colleagues who still are. So I’m fairly used to regular complaints about (l)users and a delusional sense of self-importance. Yet, it’s still a rare week in which I’d read a bunch of articles (with comments) like this one and had so many discussions about what and how should our users behave.

I think most comments were simply rubbish. You have no reason to complain as long as they are polite and not intentionally obstructive.

The thing I always admired about Mobitel is the way they treat their customers. It doesn’t matter how little do they know about phones, phone plans or even their own needs and desires, you can be sure that Mobitel’s personnel will take the time and energy necessary to explain, show and resolve whatever is needed. They certainly don’t expect me to come loaded with information and spend more of my time to save theirs.

I know next to nothing about plumbing and I’m sure it’s a fact well known and obvious to every plumber I’ve met. But did they ever treat me like an idiot? No, because it’s understood that they have to know so I don’t have to. I simply can’t know everything and wouldn’t want to, because there are other, more important things that I should be doing. I might help with my answers to their questions, but it’s not really expected of me to do anything more than to show the problem.

I understand frustrations when dealing with too many problems and too little time. I also know that there’s always a small percentage of users who simply are assholes. I don’t believe it’s ever acceptable to be impolite, but I understand it sometimes happens.

Life can be hard, but it doesn’t change the fact that our task is to provide a service, to serve our users and not the other way around. And if we have a problem doing this, it’s us who must resolve it not them. In fact, without them “pests” there’s little need for what we provide. After all a perfectly configured and RFC compliant mail server is just a box of toxic waste without someone sending emails through it.

Some professions get this. As Woody Allen rightly pointed out, it really is a bitch to get a plumber (on Sunday).

Beloved python filter

Is it just me or does anybody else find it easier to write:

elmList = filter( len, elmList )

then

elmList = [ x for x in elmList if len(x) ]

I don’t know why, but if I want to use the second form, I always have to look it up somewhere . I know filter and friends are frowned upon, but I can’t stop liking them.