In Part 1 of this blog, we looked at building Hybrid Mobile Apps and the technologies one could use. In this part, we will look at the translation of the app so users can interface with the app in the language of their choice.
To start, you need to add translation support to your app in order to render your app in multiple languages. Here’s how we did it @ Unvired for Hybrid Mobile app.
1. Identify and enable strings for translation:
All user-facing strings need to be translated. However, some strings could be embedded in HTML, while others are in Typescript code. We need to enable strings in both these places for translation. Angular JS provides an internationalization library (i18n) (https://github.com/ngx-translate/core) specifically for this purpose. For enabling translation,
we used a translate pipe in HTML:
<div>{{ “Messages” | translate }}</div>
we used a method call for strings in code:
this.translate.instant(“Messages”)
In both these cases, we are translating the string “Messages”. The way it works, this library looks up for translation for the key “Messages” in a special strings file (which we will be constructing next), and once located, replaces the “Messages” string with the translated value.
2. Construct Strings file:
Strings file in an ionic app is a JSON file containing key-value pairs. The value containing the translation for the key. We need to add a strings file for every language the app supports. Each of these files should have the translation for all strings which require translation.
We automated the process of extracting all translatable strings onto a strings file with the help of an npm tool called angular-translate-extract (https://www.npmjs.com/package/angular-translate-extract) which can be configured as a grunt task. However, this project was published two years ago and not in active development and was only able to extract strings from HTML and JavaScript code, which we didn’t have in our project. Luckily, this project supported adding of a custom parser which accepts a pattern (Regular expression) for extracting strings. We used this excellent website https://regex101.com and constructed a regex pattern to match the translatable strings in the code. Depending on the number of languages to support, you will need to configure the grunt tasks to generate required output files. For e.g. en.json (English), es.json (Spanish) etc.
We ran the grunt task and we were able to extract all the strings in the app to the required files. These json files can then be handed off to the translators to provide the translated strings. Note that the files need to be saved as UTF8 encoding to ensure the strings are saved correctly.
In the last step, we added a way for the user to select his preferred language.
3. Select preferred language in the app:
We created a new page in the app to select the preferred language and made it as the very first screen of the app. Only after the user selects a language, she can continue with using the app. Once a user selects the language, we made that language as the default language for the app so that all strings get displayed in that language. We also stored this selected language code locally, so that next time the user starts the app she does not have to choose the language again. The app also allows the user to switch languages after login if they desire.
Note that some apps take the approach of using locale to figure out the language to use. For e.g. German in Germany or French in Paris could be obvious choices once can make in these countries. While this is a very valid approach we feel that it’s better to use this mechanism to default a choice for the user but still permit them to choose their language of choice (for e.g. Spanish in the US) rather than the tie to local.
3. How do we know all strings are covered?
Instead of manually updating strings in json files and verifying, one can generate something called as pseudo-localized strings file. There are various online tools available which can generate this file for you. These tools make the value visually distinguishable from the original by replacing the original characters with accented characters. We replaced our Spanish son file with pseudo-localized strings file and executed the project.
We tested and enabled few other strings for translation. Ran the grunt tool to extract these strings. Re-generated pseudo-localized strings. We did this cycle many times until we were sure that all strings are covered for translation.
4. Translating Dates:
While translating messages can be done by language experts and complete coverage can be achieved, the dates (Month and Day names) were in fact not translated and had to be handled programmatically. We had used Moment.js library for formatting dates and this library supports internationalizing by means of calling a very simple function:
moment.locale(‘es’)
After this point, all day and month names were translated into Spanish.
5. The last mile, let the server know what language to speak:
Few messages that were displayed in the app were sent from the server (this could also be true for errors). Since all the messages from the server to the user have to be in the user’s preferred language, so we created a new API in the server to accept and store user’s preferred language. We added Internationalization support for all the user-facing strings sent by the server and got it display in the user’s preferred language in the device. This can be achieved with standard web app internationalization (similar to some of the details above).
Read Part 3 of this blog about Integrating BLE in Hybrid Mobile Apps.