Suppose you begin the long and complex task of internationalizing your software, only to discover a fundamental flaw in your i18n framework. What if your language files aren’t compatible with the translation vendor? What if the chief architect has identified a key software component for replacement? What if your approach isn’t compatible with each of the locales you wish to target? Overlooking the optimal sequence of i18n, or missing critical components altogether, can lead to significant, and costly, mistakes.
I18n Communication, Planning and Architecture
Large companies with multiple development teams operate within a paradox. The development teams operate independently to ensure fast delivery of product enhancements, but that same independence often results in a lack of communication or big picture design of the system itself. The first step in any i18n project is to communicate with the teams and examine both the long and short terms plans of all aspects of the product.
It’s surprisingly common for long term architectural plans to be overlooked in the i18n process. For example, a company may have a solid framework using RequireJS, and the development team moves forward using the integrated RequireJS framework for i18n. But just a few years later, support for the RequireJS framework stagnates, and the architects find themselves in the unfortunate position of needing to upgrade not only their RequireJS component, but their entire i18n framework that uses it. Following the optimal sequence of i18n would have solved this problem.
Do you write documentation? Small, agile teams often do very little in this regard, preferring instead to focus on manageable enhancements that can easily be documented with a short paragraph. But i18n of a large software product is a different beast, and requires detailed planning and documentation. And with that documentation comes a listing of the components that need to be refactored, what changes are needed with each refactor, and the sequence of refactors needed to ensure a seamless implementation in that agile environment.
Looking beyond design, are there specific refactors in an i18n project that should happen before others? The short answer is yes. Once a proper design has been determined, it’s still critical that upgrading of certain components takes place before others. Failure to do so can lead to lost time as developers wait for dependent projects to complete, redundant passes through code as interfaces are upgraded haphazardly, and bugs in the app when code does not interface properly throughout the entire i18n process.
String Externalization and Concatenation
First, let’s talk strings. Supposed Jeff was given the task of externalizing the strings in the app. With the string externalization framework in place, this would simply be a matter of replacing each string with a call to the string framework. On the surface, the task seems pretty easy: if you see a string, externalize it! But Jeff and his superiors didn’t consider the optimal sequence of i18n, and they overlooked a critical prerequisite: concatenations. So, Jeff continued on his merry way, refactoring strings like this:
var text = “The ” + fieldName + ” field is required.”;
and turning them into this:
key.the = “The “;
key.fieldisrequired = ” field is required.”;
var text = GetString(key.the) + fieldName + GetString(key.fieldisrequired);
It wasn’t until much later that they discovered sentence structure plays a key role in localization, and concatenations should therefore be refactored to use insertion points prior to the strings being externalized. Using Jeff’s incorrect refactor, the phrase
“The Name field is required.”
could not be properly translated into Spanish since the word “field” (campo in Spanish) switches to the left side of the inserted “Name” (Nombre in Spanish):
“El campo Nombre es obligatorio.”
Even further, translators have difficulty translating partial sentences. What does “The” refer to? Will it refer to a masculine or feminine noun? A more proper refactor would therefore have been:
key.thefieldisrequired = “The {0} field is required.”;
var text = String.Format(key.thefieldisrequired, fieldName);
By using the refactored concatenation, the Spanish translation can adjust for the revised sentence structure:
key.thefieldisrequired = “El campo {0} es obligatorio.”;
var text = String.Format(key.thefieldisrequired, fieldName);
I18n and the Database
Next, let’s talk database. Suppose Sally’s project was to refactor addresses in the app, allowing storage of additional address lines and adding a country. On the surface, the project seemed pretty easy. The db administrator had already added a Countries table for reference, plus added 2 additional address columns to the client database. Sally thought everything was good to go.
But after adding the new address fields and running a test, she discovered that Japanese characters weren’t being properly stored in the database. After a great deal of debugging, she discovered the address columns were VARCHAR and couldn’t store Unicode characters! She spent the next few hours putting in a request to the database admin to upgrade the address columns to NVARCHAR, and waited patiently for the database to be upgraded.
But Sally’s next problem quickly arose. The ZipCode column was only 10 characters long, and she realized that international Postal Codes could be significantly longer than that. So again, she put in a request for a database change, and again she waited patiently for the upgrade.
Sally’s problems, however, were not over. As she continued her i18n of addresses, she discovered that some countries have “States” and others have “Provinces”. The Countries table they’d originally created had no knowledge of this distinction, but clearly one needed to be made. So again, Sally put in a request to the db administrator to add a new column to the Countries table, and waited patiently for the upgrade.
One of the greatest inefficiencies in software development is improper planning. By ignoring the optimal sequence of i18n, Sally and the db administrator had to go back and forth multiple times, upgrading the database piecemeal and slowing the i18n process considerably. The proper sequence should have been: Complete Address Design > Complete Database Refactor > Complete Code Refactor.
Synchronizing i18n Processes
Finally, let’s talk synchronization. The I18n Team at Widgets R Us had a number of front-end and back-end modules that needed refactoring, and they began merging their front-end upgrades first. All seemed fine, until customers began reporting program exceptions in various areas throughout the app. A crisis was underway.
As it turned out, the I18n Team had refactored the dates sent to the server to be in ISO format (YYYY-MM-DD). And while they had tested many of the adjaxPostSync calls, there were still a number of untested interfaces where the server was expecting a localized MM/DD/YYYY format, and the app was crashing with the unexpected data.
Improper synchronization in the i18n process can lead to program errors, and unhappy customers. In the case of Widgets R Us, the server interfaces either should have been refactored first to allow the use of both ISO and localized dates, or the client and server modules should have been upgraded together.
Does i18n have an optimal sequence? Every app is unique in its requirements, but the answer is definitely “yes”. Communication amongst all development teams is paramount, extensive planning and design is critical, and the sequence of implementation is vital. Failing to follow the optimal sequence of i18n can lead to time consuming, and costly, mistakes. Don’t let it happen to you.