Monday 25 January 2016

Internationalization (i18n) and Localization (l10n) of Keycloak

Keycloak's admin console needs to be fully localized.  That is, we need to replace all of our static English text and replace it with something that can display readable text in the user's local language.  I've done this sort of thing many times in Java, but our admin console is written in AngularJS, which is rather new to me.


So I set out to discover what i18n/l10n libraries might help.  I found three candidates.

angular-localization

angular-localization is a relatively new library written by Rahul Dashi.  I must say I was pretty impressed with this talk he gave at an AngularJS user group.

I also checked out the GitHub repo and documentation.  This was definitely in the running.  Worth a test-drive.

angular-translate

angular-translate is very similar to angular-localization.  angular-translate's founder and primary author is Pascal Precht.  "Pascal" is a phenomenal name for a programmer, so his library must be good.  But just to check, I did watch a talk, looked at GitHub, and the docs. This one would get a test-drive too.

angular-gettext

Among the three, angular-gettext wins the award for best web site.  But beyond that, I didn't like what I saw.  The approach is completely different from the first two.  You annotate your code and run it against a tool that tries to figure out where the static text is.  Then it uses the English text as keys to put into .po files for translation.  Magical!  But as any Harry Potter fan knows, while magic can be fun, it can also go horribly wrong.

The more I read about angular-gettext, the more it just didn't seem right for Keycloak.  I hate an over-reliance on tools.  I don't like forcing developers and translators to learn new tools either.  Plus, I don't think our translators ever use .po files.

Maybe I was punting on third down*, but I just couldn't justify spending more time on angular-gettext.

(*Note that "punt on third down" is an American football reference that that can not be localized to soccer. :-) ) 

angular-localization vs angular-translate

So it's down to two candidates.  To try these out, I created a simple app that localizes the Keycloak login page.  In Keycloak today, this page is already localized using Freemarker.   But for this exercise I just grabbed the raw HTML and created two AngularJS pages, one to test each library.  You can see the code or try it yourself.  I've uploaded the source to my GitHub account.

Here is how it looks with both libraries.  Both allow you to change languages with the press of a button:

So both libraries work, and the code I had to write for each is very similar.

Here is a simple translation for angular-localization:
 <label for="password">{{'password' | i18n}}</label>
Here is the same translation for angular-translate:
 <label for="password">{{'password' | translate}}</label>
Both let you do translations with directives or filters.  Both use JSON resource bundles for translation mapping.  Both let you parameterize your messages, and both have support for AngularJS features like pluralization and two-way binding.  Both meet Keycloak's requirements.

So which do we choose?

The maturity heuristic

There are indeed some technical differences between the two libraries.  And judging from what I've seen, angular-localization probably learned some things from its older, more mature cousin.  But therein lies the rub.  angular-translate is considerably more mature.

The great thing about open source is that I can assess this maturity.  It's quick and easy to look under the hood and see how far along a project really is.  You can see the frequency of commits.  You can see the diversity of the developers who have submitted pull requests.  And most important, you can see if the project is still "alive" with recent commits and releases.

In other words, you can assess the community.  Software is only as good as the company or community that stands behind it.  So in the end, the choice was pretty easy.  We went with angular-translate.