One of the most frequently requested features for TicketDesk 2 was support for localization. TicketDesk is a stringy application; lots of system generated text that will end up in the user’s face at some point. Localizing TD2 required combing through the source code, line-by-line, translating magic strings by hand.
Clearly, this is not an acceptable approach with TicketDesk 3.
Since localization is thorny, and a weak spot in my own skill-set, I consider it essential to designed for localization as early in the process as possible… and now that the code has gotten to the point where it draws a useful UI, it is time to get started.
In the typical Asp.Net application, localization is mostly just a matter of creating resource files that contain the text translations, then making sure the code only gets text from those resources. There is a lot of support in .Net around localization, cultures, and resource files, so this is pretty easy to do. The only difficult part, for the mono-lingual developer, is getting the text translated into those other languages in the first place.
Translations in TicketDesk 3:
TicketDesk performs text functions on the server too, so it still needs resource files, so I wanted to be able to pipe the contents of the resource files to i18next directly, rather than maintaining separate translation files for the server and client. For this, I leveraged Asp.Net Web Api. Configuring i18next to get its json translations from Web Api is simple –just map the URLs it uses to Web Api endpoints.
The Web Api controller itself was a bit more complex. It has to detect the specific language that i18next is requesting, then build an appropriate response in a format i18next can consume. The controller loads a ResourceSet for the requested culture, then loops through the properties to build a dynamic key/value object with all the translated text. Once that’s done, it outputs the dynamic collection as a json response.
i18next has a richer set of capabilities than straight .Net resource files. Resource files are just simple name/value lookups. With i18next, the translation files can have nested properties, replacement variables, and there are features for interpolation (plural forms, gender forms, etc.). These features are available in .Net with some advanced language frameworks, but the basic resource files don’t go that far. Fortunately, TicketDesk only needs the basic set of features, so a flat name/value lookup should be sufficient to get the job done; though it doesn’t leverage some of i18next’s more advanced features.
Localization is more than text translations. TicketDesk also deals with numbers occasionally, and there are some dates too. Fortunately, it isn’t a number heavy application, nor are are there user editable dates or numbers. The moment.js library easily handles local date display formatting, and numeral.js can handle the couple of numbers.
The main weak point in TicketDesk 3’s localization will be an absence of structural language transformations. Once you get into right-to-left languages and other exotic forms, the physical layout of the entire UI has to change. Sadly, I do not have the expertise to correctly design for such languages. HTML 5 and CSS 3 do have decent support for this kind of cultural formatting though, so my hope is that anyone needing to localize for these languages can do so themselves without difficulty.
My intention for TicketDesk 3 was simple localization; the admin would tell the server what language to use, and the system would just generate the UI in that language for all users. I did not initially expect to support dynamic internationalization — the ability to support multiple languages based on individual user preference.
When I got into the details of the i18next implementation though, it quickly became apparent that TicketDesk 3 could easily achieve real internationalization… in fact, internationalization would be about as easy as static localization.
The result is that TicketDesk 3 will be internationalized, not just localized. It will detect the user’s language and dynamically serve up a translated UI for them –as long as resource files exist for their language. If translations for their specific language and culture aren’t available, it will fall back to the best-matching language, or to the the default if no better match exists.
State of the Code:
I have the plumbing for internationalization in place in the alpha already. It auto-detect’s the browser’s language, or you can override it via the query string (e.g. ?setLng=es-MX). Since I don’t speak any other languages, I can’t provide any real translations myself. For the short term, I have created a generic Spanish resource file, into which I copied the English text surrounded by question marks. This isn’t real localization, but it serves to validate that the localization support works correctly.
For dates, I’m using moment.js, so it should adapt to the browser’s language settings automatically, but I haven’t setup moment to use the querystring override yet… I’ll get to that soon though. I’m not doing any number formatting yet, but when I do I’ll implement numeral.js or a similar library.
When TicketDesk 3 gets into beta, and I have the full list of English text strings in resource files, then I will get a native Spanish speaker to help generate a real set of translations. Hopefully, the community will pitch-in to provide other languages too.
If you want to take a look at the early alpha version, I have published a TicketDesk 3 demo on Azure. I can’t promise that it will be stable, and it certainly isn’t a complete end-to-end implementation. But feel free to play around with it. To play with localization, either change your browser’s language to something spanish (es, or es-MX, or similar), or use the querystring override: ?setLng=es