Internationalisation and Localisation

As part of the largest expansion of the BBC World Service since the 1940’s the iOS News App was expanded to include three new languages.

As all variants of the app are created from a single code base each new language brings configuration work. The main changes to the code however, if you had guessed NSLocalizedString you’d be right, were done with the first variant, Cymru Fyw.

Later variants, such as Russian, provided new challenges as in Russian numeral syntax is more complex than many other languages, certainly any supported by the app to date. In Russian there are three cases rather then two :
  • 1 is nominative
  • 2 to 4 are genitive singular
  • 5 and up genitive plural
In addition to configuration and code changes much of the work was managing translated strings supplied by dedicated regional teams. In a perfect world keys to be used with NSLocalizedString would be in recorded in a database and translators would enter translated values against them for each language. This system would be set up before any translation starts and this database could then be employed to create a .strings file for the language variant.

Real life being different from a perfect world we were working with an online spreadsheet into which translations were being recorded against strings that appeared in English in the app interface. When we started working on the code some of the translation teams had started entering translations already and all were at different stages of the process.

We quickly had to harmonise our team’s activities with the translators and the first two tasks had to be done manually :
  1. Create an English .strings file, and corresponding NSLocalisedString code.
  2. Enter the keys from the English .strings file on the translators’ spreadsheet
Having the translators record translations against plain English strings is unsatisfactory because there is no context and it’s easier for errors to creep in, e.g. white space.

For strings where a value needed to be injected in to the translation we opted for templating similar to those founds in URIs, see rfc6570, which used curly braces.

“app.heading.day_of_week” = “Hello.  Today is {day_of_week}.”

Automation Tools

Once we had our iOS keys added to the spreadsheet against the English strings, which now could act as an example of context for the translators, we could start automating things. The benefits of automating tasks here are many. As the iOS NewsApp team is a small one we had to protect ourselves from being drawn in to a lot of manual repetitive work which takes a long time. Automation is great for repetitive tasks and often can result in saving a lot of time.

Bringing down the time it took for us to response to translations to minutes meant we could also cope with very late changes to the translations. This is of course typical of the type of thing that happens in big organisations where work is being done across multiple teams and where many people can change / copy data sources. Mistakes, regressions and communication from one team to another easily introduce the type of delay which are hard to plan for in advance.

I wrote a number of Python scripts that automated tasks needed to prepare and check translations :

Compare two spreadsheets

Even though we were using a web spreadsheet application, regional translators had been
downloading and working with local copies as their Internet connection was unreliable.
Multiple versions were being emailed around and there was no single source of truth.

This script compared values, not keys, of specified columns in two spreadsheets and help
us manage multiple versions of spreadsheets that had already begun to circulate by the time we started the app work.

Create an iOS String File

By specifying a spreadsheet, a column containing keys and the column with translation values an iOS .string file is created. This takes a matter of seconds and meant late
submission of translations could be easily accommodated.

Compare iOS String Files

Compare two .string files and report keys present in one and missing in the other. This provided a simple and absolute mechanism in determining gaps in one translation when compared to another.

Duplicate Keys

Interrogate a spreadsheet for keys that appear more than once. Even when working from one spreadsheet online, many people had access and editing permissions. This script ensured unique key integrity.

Insert String File Keys into a Spreadsheet

This script proved invaluable in the case where values had been added directly to
a .strings file and not via the translator’s spreadsheet. These values could be automatically
entered against keys for a specified language backfilling the spreadsheet in a matter of