Automatic language detection

If you write a website, do not use Geolocation to determine the language to display to your user.

If you write a desktop application, do not use the region setting to determine the language to display to your user.

This is incredibly annoying for some of us, especially for me which is why I’m ranting here.

The moment Google released their (awful) German translation for their RSS reader, I was served the German version just because I have a Swiss IP address.

Here in Switzerland, we actually speak one of three (or four, depending on who you ask) languages, so defaulting to German is probably not of much help for the people in the french speaking part.

Additionally, there are many users fluent in (at least reading) English. We always prefer the original language if at all possible because generally, translations never quite work. Even if you have the best translators at work, translated texts never feel fluid. Especially not when you are used to the original version.

So, Google, what were you thinking to switch me over to the German version of the reader? I have been using the English version for more than a year, so clearly, I understood enough of that language to be able to use it. More than 90% of the RSS feeds I’m subscribed to are, in fact, in English. Can you imagine how pissed I was to see the interface changed?

This is even worse on the iPhone/iPod frontend, because, there, you don’t even provide an option to change the language aside of manually hacking the URL.

Or take desktop applications. I live in the German speaking parts of Switzerland. True. So naturally I have set my locale settings to Swiss German. You know: I want to have the correct number formatting, I want my weeks to start on Mondays. I want the correct currency. I want my 24 hours clock I’m used to.

Actually, I also want the German week and month names, because I will be using these in most of my letters and documents, which are, in fact, German too.

But my OS installation is English. I am used to English. I prefer English. Why do so many programs insist to use the locale setting to determine the display language? Do you developers think it’s funny to have a mish-mash of languages on the screen? Don’t you think that me using an English OS version may be an indication that I do not want to read your crappy German translation alongside the English user interface of my OS?

Don’t you think that it feels really stupid to have a button in a German dialog box open another, English, dialog (the first one is from Chrome, the one that opens once you click “Zertifikate verwalten” (Manage certificates) is from Windows itself)?

In Chrome, I can at least fix the language – once I found the knob to turn. At first, it was easier for me to just delete the German localization file from the chrome installation because, due to being completely unused to German UIs, I was unable to find the right setting.

This is really annoying and I see this particular problem being neglected on an incredibly large scale. I know that I am a minority, but the problem is so terribly easy to fix:

  • All current browsers send an Accept-Language header. In contrast to the earlier times, nowadays, it is actually correctly preset in all the common browsers. Use that. Don’t use my IP-address.
  • Instead of reading the locale setting in my OS, ask the OS for its UI language and use that to determine which localization to load (actually, this is the recommended way of doing things according to Microsoft’s guidelines at least since Windows XP which was 2001).

Using these two simple tricks, you help a minority without hindering the majority in any way and without additional development overhead!

Actually, you’ll be getting away a lot cheaper than before. GeoIP is expensive if you want it to be accurate (and you do want that. Don’t you?), whereas there are ready-to-use libraries to determine the correct language even from the most complex Accept-Language-Header.

Asking the OS for the UI language isn’t harder than asking it for the locale, so no overhead there either.

Please, developers, please have mercy! Stop the annoyance! Stop it now!

VMWare Fusion Speed

This may be totally placebo, but I noticed that using Vista inside a VMWare Fusion VM has just turned from nearly unbearable slow to actually quite fast by updating from 2.0 Beta 2 to 2.0 Final.

It may very well be that the beta versions contained additional logging and/or debug code which was keeping the VM from reaching its fullest potential.

So if you are too lazy to upgrade and still running one of the Beta versions, you should consider updating. For me at least, it really brought a nice speed-up.

Dynamic object creation in Delphi

In a quite well-known pattern, you have a certain amount of classes, all inheriting from a common base and you have a factory that creates instances of these classes. Now let’s go further ahead and assume that the factory will have no knowledge of what classes will be available at run-time.

Each of this classes registers itself at run-time depending on a certain condition and then the factory will create instances depending on that registration.

This post is about how to do this in Delphi. Remember that this sample is very much abstracted and the real-world application is quite a bit more complex, but this sample should be enough to demonstrate the point.

Let’s say, we have these classes:

type
  TJob = class(TObject)
    public
      constructor Create;
  end;

  TJobA = class(TJob)
    public
      constructor Create;
  end;

  TJobB = class(TJob)
    public
      constructor Create;
  end;

  TJobAA = class(TJobA)
    public
      constructor Create;
  end;

Each of these constructors does something to initialize the instance and thus calls its parent using ‘inherited’.

Now, let’s further assume that we have a Job-Repository that stores a list of available jobs:

type
  TJobRepository = class(TObject)
    private
      FAvailableJobs: TList;
    public
      procedure registerJob(cls: TClass);
      function getJob(Index: Integer): TClass;
   end;

Now we can register our jobs

   rep = TJobRepository.Create;
   if condition then
     rep.RegisterJob(TJobAA);
   if condition2 then
     rep.RegisterJob(TJobB);

and so on. Now at runtime, depending on some condition, we will instantiate any of these registered jobs. This is how we’d do that:

  job = rep.getJob(0).Create; 

Sounds easy. But this doesn’t work.

job in this example will be of type TJobAA (good), but its constructor will not be called (bad). The solution is to

  1. Declare the constructor of TJob as being virtual.
  2. Create a Meta-Class for TJob, because the Constructor of TObject is NOT virtual, to when you dynamically instantiate an object from a TClass only the constructor of TObject will be called.
  3. Override the inherited virtual constructor.

So in code, it looks like this:

type
  TJobClass = class of TJob;
  TJob = class(TObject)
   public
    constructor Create; virtual;
  end;

  TJobA = class(TJob)
    public
      constructor Create; override;
    end;

TJobAA = class(TJobA)
    public
      constructor Create; override;
    end;

TJobRepository = class(TObject)
    private
      FAvailableJobs: TList;
    public
      procedure registerJob(cls: TClass);
      function getJob(Index: Integer): TJobClass;
   end

This way, Delphi knows that when you call

  job = rep.getJob(0).Create; 

that you are creating an instance of a TJobAA object which has a constructor that overrides the virtual Constructor of TJob by the virtue that the Class of TJobAA is a class of TJob.

Personally, I would have assumed that this just works without the need of declaring the Meta-Class and the trickery with the need to explicitly declare the constructor as virtual. But seeing that Delphi is a compiled static language, actually, I’m happy that this works at all.

Food for thought

 

  1. When you open a restaurant, you know the risk of people going to the supermarket and cook their own meal, not paying you as the restaurant owner.
  2. When you publish a book, you know there are going to be libraries where people can share one copy of your work.
  3. When you build a house and sell it, you know the people living there will be going in and out of your house for year without ever paying you anything more.
  4. When you live in a family and clean the parents car for one Euro, you know about the risk of your sister doing it for 50 cents next time around.

But

  1. The music industry claims to have a monopoly on their work, managing to get laws created that allow them to control distribution and disallow anybody to create a lookalike without paying them.
  2. The game industry is hard at work making it impossible for honest customers to even use the game they bought on multiple devices. And now they even begin to go after the used games market (think about that SNES pearl you just saw in your small games store. The one you wanted so badly ever since you’ve been young. Wouldn’t it be a shame it was illegal for them to sell it?)
  3. The entertainment industry is hard at work to make you pay for every device you want to play the same content on.
  4. Two words. “SMS pricing”.

Why do things applying to “small people” not apply to the big shots? Why does the government create laws to turn around well-known facts we have grown up with just so that the wealthy companies (the ones not paying nearly enough taxes) can get even wealthier?

I just don’t get it.

iTunes 8 visualization

Up until now I have not been a very big fan of iTunes’ visualization engine, probably because I’ve been spoiled with MilkDrop in my Winamp days (which still owns the old iTunes display on so many levels).

But with the release of iTunes 8 and their new visualization, I have to admit that, when you chose the right music (in this case it’s Liberi Fatali from Final Fantasy 8), you can really get something out of this.

The still picture really doesn’t do it justice, so I have created this video (it may be a bit small, but you’ll see what I’m getting at)  to visualize my point. Unfortunately, near the end it gets worse and worse, but the beginning is something of the more impressive shows I have ever seen generated out of this particular piece of music.

This may even beat MilkDrop and I could actually see myself assembling a playlist of some sort and put this thing on full screen.

Nice eyecandy!