As discussed earlier, localisation generally depends on skinability. Often too, localisation will require a deeper level of adaptive behaviour: This is the role of customisation. In fact, localistion projects are often hybrids (blended localisation *and* customisation projects).
In what follows, remember that the topic is about retroffitting the adaptations needed to support localisation. In brand new projects, a lot of these issues can be planned for and dealt with differently. In a retroactive scenario however, these are some of the issues that come up during customisation:
Rule #1: locale-oriented customisations will yield cross-cutting concerns
This is more of a gotcha for the developers involved than anyone else. In simple terms, a cross-cutting concern is a bunch of recurring, intrusive logic or program statements that manifest themselves everywhere. In short, it poops all over your pretty codebase, in every possible nook and cranny… unless you happen to have adopted something nifty like aspect-oriented programming or similar. But would you *really* have done that, *just* for a localisation project? Not likely.
Cross-cutting concerns are especially an issue if localisation is at run-time (dynamic adaptation), because there really is no reducible logic for handling all the ifs, buts and wherefores of localisation. Examples of recurring and intrusive logic:
-checking string lengths (remember that different languages use a different number of words/characters to say the same thing, greatly impacting design elements such as layout)
-checking size/extent of UI elements (ditto)
-checking/setting fonts (remember that not all fonts are created equal, especially when it comes to unicode)
-checking/setting keyboard layouts, etc…
You can blame the laws of requisite variety till the cows come home, but all you can hope to do is encapsulate your tweaks and hide them away as much as possible. Or resort to programming languages or development environments that do a lot of this sort of lifting for you. However you cut it, this ‘locale-sensing’ logic will still be there, eating up CPU cycles under the hood and cluttering up code.
Rule #2: Prepare to have N ‘locales’ for N clients.
Locales are funny things. Just when you think you have them completely nailed down, you will discover that folks south of the river in country X like to have things *this* way, whereas folk north of the river like to have things *the other* way. In fact, prepare to have clients within the same locale completely override your application’s (naively expected) norms for their geographic/cultural region.
Sales and marketing teams understand that you have to pitch differently to different groups of people. It is very hard for a development team, however, to accept that what goes down well in Spanish Mexico isn’t necessarily going to fly in Spanish Argentina. Having localised right down to the correct ‘flavour’ of spanish (the language code), the time zones and currency formats etc, don’t be surprised to find that the Mexicans insist on ‘foo’ while the argentinians simply must have ‘bar’, or some other such random, unforseen variance.
In otherwords, behavioural customisations follow swiftly on the heels of actual localisation. It is naive (though forgivable) to think that beyond localisation, no other regional changes will have to be accomodated.
Rule #3 : Your locale file is not a settings file
Now that you understand that customisations are inevitable, the next pitfall awaits: it is the temptation to use your locale file to include settings or switches which affect the flow of control in the application. Imagine a dummy locale file as follows:
Now let’s say you discover that your Quebecois client can in fact support both English and French. So the user interface now needs a shiny new button that allows these bilinguals to toggle to their preferred language. The design guy has already created the button. But where to put it? The layout doesn’t really have a decent spot for the new button (it not having been forseen) and some layout changes have to be made, on the fly, just for Quebec.
To accomodate this new ui-element, just for the French-Canadians, it would be very tempting to include this logic in the locale file:
But in so doing, you will have changed the locale file into a configuration file, and that is a NO-NO. Why? Configuration files are normally for a developer’s eyes only. And there should really only be only be one such file per build. This is where all the ‘behavioural’ switches should live, and quite frankly your client doesn’t want to wade through them. Why stick this logic in the locale file that, (if you’ve been smart) is the client’s domain of activity? At worst they’ll keep pestering you for explanations (“Hi.. we get what ‘hello’ and ‘goodbye’ mean but could you remind has what ‘hasLanguageButton’ is? Oh really? It’s for the bilingual thing we discussed? Oh Ok. So what do you want us to put there?”…) and so on. At worst, they will insert whatever settings they believe to be correct, and the application will simply barf and die.
Locale files are for everyone. There may be (should be) several such files in one build. Keep them user-friendly and separate; add a settings or configuration file to your project instead. Even if your application structure is such that you have as many settings/config files as you do locale files, that’s OK. The important thing is that the poxy things are separate.
Rule #4: Testability will reduce over time, unless you fight the good fight
As the different variants pile up, and the one codebase adopts its multiple ‘personalities’ to accomodate the wishes of more and more clients, The QA effort (unless you’ve hired some kind of QA Nazi to ‘run tings’) will slowly dissolve into a fuzzy affair that only ever excercises a single variance/instance sufficiently. Note: remember that if you are retro-fitting localisation, you are probably retrofitting the necessary QA tasks too.
Of all the different types of testing, Regression Testing is the most important (and unfortunately the most unwieldy, by its very nature) to perform for adaptive applications. Imagine that an application has 200 test cases before being localised for N locales. What should the test coverage be, after the Nth deployment? Do we really want to run through 200*N test cases? Or would we want to just run 200 test cases, but tailored to the Nth locale? (And what do we mean by tailored? Are we going to assume that the tester is familiar enough with the application to infer how to adapt each test case for the new locale, or are we actually going to hire someone to write 200 new test cases just for locale N, plus any extra adaptations that have been made specifically for it?).
While it is easy to test the Nth locale alone and ‘hope’ that the other N-1 locales are ‘still okay’, this becomes more of an issue with progressive additions. I would guess that a recurring regression test of a random selection of locales at a set interval should be a bare minimum… at least to cover the collective behind of everyone on the QA team.
Based on the above, it should be clear that you can, especially if you will yield to your client’s every whim, end up with a separate ‘locale’ for each client. The reductio ad absurdum, then, is to assume this at the outset… and simply allocate a unique identifier to each variant of the application (which corresponds to each client). This approach will give you the greatest flexibility in the long run. In this approach, each localisation ‘id’ specifies a 2-fold adaptation of the existing application: i) presentation level adaptations (eg via locale files) and ii) behavioural adaptations (via configuration files).
You can imagine a sort of 3D space for all the possible variations of your app. (identifier,locale,config)=(z,x,y). The key to successful project management (and business growth) in this space is to understand that ids are free, locales are cheap and configs should cost a good bit of money. Armed with this intelligence, it should be possible to squeeze out a good business model based on localisation projects. Additionally, if product managers are able to work closely with project teams to assess the true impact of planned/new feature sets, decisions can be made about when the codebase can absorb the next round of structural and behavioural adaptations.