Localizing a client-side app
Localization (L10n) is the process of adapting your app to users with a different language and various settings like date format, currency, number formatting etc. It is often also referred to as Internationalization (I18n).
Closely related to Localization is Globalization (G11n), which is a preparatory step of making it possible to do L10n. If the app has no mechanism for switching language or does not have UI resources (strings) separate from code, it is regarded as not globalized and therefore not possible to localize in any effective way.
Some server-side web frameworks have built in support for I18n, like Rails for example. That way a localized page or app may be rendered on the fly by the server similar to how templating works, or by actually using templates.
For desktop applications L10n is sometimes done in resource files that define UI and gets fed to the compilers when building a localized product. Sometimes a product is built for each language, so the shipped installable app is in a language different than English, and there is still just one language in the product. Other times a multi-language product is built and the person installing it can decide at that time what language that machine should have, meaning the installer is multi-language but the resulting install is a single language. Some desktop apps are built so that the installer is multi-language as in previous example but also after install the user can switch language between executions, or even during execution.
Some companies do not build localized products up front when compiling but instead once the English product is built, a L10n specific process is used where UI resources are extracted from English binary files and then "resource hacked" back into place to make a localized product.
For localizing a front-end web app there are many ways and frameworks to do it. One really simple way is to use Polyglot from Airbnb. You can use it on the server side together with Node, Express and EJS templates, or even simpler, directly in the html file of your app. That's what I will demonstrate below.
Example using Polyglot on client-side
Polyglot is available at https://github.com/airbnb/polyglot.js. Get the production version (tiny) and reference it with a script tag into your html file. Then you need to put IDs for each text you want to localize (translate). If you use snake_case for the IDs then you can easily loop over all of them when the user wants to switch language.
Let's say we are doing a travel booking app. The IDs and their translations can be defined as follows. Here is one of the HTML elements where we have added the ID:
<h4 class="black-text" id="input_heading">Where to?</h4>
Then somewhere in our Javascript, we can add all our translations. In this example we want the the object keys to match the HTML IDs.
const phrasesByLocale = {
en: {
input_heading: "Where to?",
input_depart_field_heading: "Depart from:",
input_arrive_field_heading: "Arrive to:",
input_date_field_heading: "Date:",
search_button_text: "Search",
output_heading: "Your Connections:",
output_departure_date_heading: "Departure Date",
output_departure_time_heading: "Departure Time",
output_arrival_time_heading: "Arrival Time"
},
es: {
input_heading: "¿A donde quieres ir?",
input_depart_field_heading: "Salir de:",
input_arrive_field_heading: "Llegar a:",
input_date_field_heading: "Fecha:",
search_button_text: "Busque",
output_heading: "Sus conexiones:",
output_departure_date_heading: "Fecha de salida",
output_departure_time_heading: "Hora de salida",
output_arrival_time_heading: "Hora de llegada"
}
// More languages here..
We are also going to need a function that changes all UI strings. It's a simple implementation as the object keys are matching HTML element IDs.
function setLanguage(locale) {
let phrases = phrasesByLocale[locale];
let polyglot = new Polyglot();
polyglot.extend(phrases);
for (phraseKey in phrases) {
document.getElementById(phraseKey).innerHTML = polyglot.t(phraseKey);
}
}
Then somewhere in the the HTML we need to add language selecting links:
<li><a href="#" id="select_EN">EN</a></li>
<li><a href="#" id="select_ES">ES</a></li>
And finally the event listeners for those links:
document.getElementById("select_EN").addEventListener("click",
function () { setLanguage('en')});
document.getElementById("select_ES").addEventListener("click",
function () { setLanguage('es')});
This example works for very small apps, where you the developer can copy out the "en" part of object "phrasesByLocale" above and ask your translators to look at both keys and values and then replace the values for the language. When you get it back you would then paste the result into the "phrasesByLocale" object.
This does not scale well, so you could change it so that each language has its own translation file. The translators could then submit translations via GitHub pull requests.
Continuous localization
Chances are that you will need to change a string (an English string value) after translation to Spanish has already been completed, or add a new string. Then it is very helpful to the translator to have the previous version of the English and Spanish files, to make diffs to spot what's new. - Or GitHub can help with those diffs.