i18n Library – in the Spotlight

by Steven Crighton on July 6, 2022 7 comments

Hello, Hola, Bonjour, Ciao, Γεια, Halò and welcome to another edition of in the Spotlight. We’re looking at the new i18n library from LiveCode. If the intro did not give this away this library is all about internationalization. i18n allows you to easily handle language translations inside your application. Let’s dive in…

First, why i18n? It’s a question I had when I first saw this new library. It turns out, Internationalization just takes too darn long to type, so if you count the number of letters between the first i and the last n in the word you reach 18. There, now it makes sense. Take a look at this short demo video.

I18n is an internationalization library written in and for LiveCode. It consists of a translation system that allows support for multiple languages in our LiveCode applications.

Note: This library is inspired by i18njs.com with some modifications.

We start off with language files. Language files are where your translated text is stored. In this example lets assume my app consists of just two buttons. Button 1 has a label of “Back” and button 2 has a label of “Next Step”. Our English language file would look something like this…

{
  "id": "en",
  "values": {
    "back": "Back",
    "next": "Next Step" 
}
}

We would then need to create a language file for all of the languages we wish to translate our app into. For this example let’s say we wish to translate into Gaelic. Ali Lloyd on our team has been learning this language and it’s probably one you all don’t see very often. Well our Gaelic language file would look something like this

{
  "id": "gd",
  "values": {
    "back": "Air ais",
    "next": "An ath cheum"
}
}

Now that we have our language files and we have our app that consists of two buttons, we now have to initialise the library by telling LiveCode where our language files are located. This is a short snippet of code and in this example we add it to our preopenstack handler. This means that if we ever add any new language files they will be detected each time preopenstack is run.

on preopenstack
     local tPath
     set the itemdel to "/"
     put item 1 to -2 of the filename of this stack into tPath
     i18nInit (tPath & "/languages")
end preopenstack

We now need to tell the library which values in our language file match to our LiveCode objects. This is made easy by the Magic Palette plugin included with the bundle. It is also worth noting here that you only have to do this step for one of the languages. Once these match ups have been made for a single language, any new languages added will take care of it automatically.

Thats it. Our sample app now translates between English and Gaelic.

In the sample app shown in the video we have built in a dropdown language selector and we use this to change the language shown in the app. When you are working in the IDE you can quickly change the active language using the Magic Palette as shown in the screenshot below. However in a real world app you may want to do something more like this…

The language selector used in this example changes the language by using setActiveLocale. This allows the library to switch to the correct language. Here is the snippet of code that runs when you click on Spanish in the dropdown.

on mouseup
     setActiveLocale "es"
     # Updating all UI texts.
     updateLocale the long id of this stack
end mouseup

The i18n library offers many more features not covered in the video. One of these additional features is Pluralisation. Pluralisation is how the library handles some of rules found in languages. The following is an example of how you might use pluralisation in the English language file. In this example we are showing the results of a search. In English you would not expect to see 0 result, you would expect to see 0 results. Similarly you would not expect to see 1 results, you would expect to see 1 result. Finally you would not expect to see 10 result, you would expect to see 10 results. Here is what your language file might look like to achieve this.

{
  "id":"en",
  "values":{
    "%n results":[
      [0, 0, "%n results"],
      [1, 1, "%n result"],
      [2, null, "%n results"]
    ]
  },
  "name":"English"
}

Then we would add this our search script

answer translate("%n results", numberOfResults)

This would result in one of the following

  • 0 results
  • 1 result
  • >1 results

This has been a great library to put in the Spotlight and it’s been a lot of fun using it. To sum up, it’s an incredibly simple to use library, especially when you are using it the way I have used it in the video. You can produce an app for multiple languages with relatively little effort. It has more advanced options such as pluralisation, formatting and context which are there and well documented in a user guide if you need them.

Some things to look out for when using this library – make sure your fields are big enough for the translation that has the most characters in it. Always get quality translations when you can, the library is only as good as the translations we put into it.

If you’ve got any questions or comments about the library let me know in the comments below. The i18n library along with the Magic Palette are included free with the Summer Mega Bundle.

Steven Crightoni18n Library – in the Spotlight

Related Posts

Take a look at these posts

7 comments

Join the conversation
  • Mark Wieder - July 8, 2022 reply

    Leaves a lot unsaid here. The i18Init command takes as an argument either a folder or a file or an array. If it’s a folder, is there a naming convention for individual language files? Are the individual files accumulated into an internal array? and from then on treated the same as if I had handed the init command an array? If the argument is a single file, should it then contain all the JSON language objects instead of placing them into separate files? If I build a standalone, do I need to list the language files in the Copy Files section of the standalone builder?

    Steven Crighton - July 8, 2022 reply

    Hi Mark, Thanks for the comments. There is indeed lots about this libraries features I did not cover in the blog post. The blog post really only looks at what was required to get my sample app working. i18n does have good documentation entries in both the dictionary and user guide. I recommend checking them out. Let me try to answer your questions as best as I can.

    1. With regards to individual file naming convention. It does not matter if your file is called en.json, englishlanguage.json, untitled.json, indeed it doesn’t even need to include .json it could be a .txt file. The library will look in the folder and so long as it can find the JSON Structure that I have included in the blog post it will do it’s work. Indeed the ID inside the language files which I have in this example "id": "en", could be "id": "anythingyoulike", You just have to make sure that matches up to everything else you do e.g. When you do setlocale. Now I would recommend that you name your language files 2lettercountrycode.json and include the 2 letter country code as the ID just for neatness but it is not a requirement of the library.

    2. Yes individual files are accumulated into an internal array by the library. This is transparent to the user and dealt with by the library.

    3. So not quite – when the init command is called or a language is loaded by the library, the language file/array is processed and added to the internal array (cache), but with some changes in the structure to speed up later use. This is all totally transparent to the user.

    4. If the argument is a single file, only that file will be loaded. If the file contains multiple languages then all those languages inside the file are loaded. If the file is single language then only that single language will be loaded. So it’s possible to contain multiple languages in a single file.

    5. Yes, your files will need to be included in the Copy Files section.

    One additional thing to add. Since writing this blog post we have made an update that is not pushed yet but will be soon. In the video and blog post you will see that I have had to initialise the library using the i18Init command. If within the folder your stack is saved there is a subfolder with any of the following names “i18n, i18ns, locale, locales, language, languages, lang, langs” then the library will auto initialise and auto load language files. This will be pushed shortly.

  • Mark Wieder - July 13, 2022 reply

    Thanks. I’m looking forward to putting this to use.

  • Belhaj Tarik - September 30, 2022 reply

    Does i18n work in web mode with DP10 -4? If so, how do I proceed?

    Heather Laine - September 30, 2022 reply

    Yes, it will work with the latest 10 dp releases. You need to have a copy of the library, and Magic Palette installed in your plugins. You can get the library from our extensions store if you don’t have it already.

  • André De Tienne - January 17, 2023 reply

    I have created an LC app, “Internationalization Language Files Maker” that facilitates the creation of language files tailored to particular LC apps. It’s simply a matter of selecting some LC stack, listing all of its controls along with relevant properties (type, kind, name, label, text in case of label fields, and tooltips) within a polygrid. Clicking any row brings the control-related texts in various fields (for the base language) while readying their translation in any language in other fields through drop-down menus. Translations are provided automatically via a browser connected to Google Translate. All data get stored within language arrays. Users can choose any such or all of them to create JSON files instantly. My question: can LC’s i18n be used to translate tooltips? At the moment my algorithm moves them not within a values key but under a tooltip key, the idea being that this separation could be helpful to indicate intended destination.

    Heather Laine - January 19, 2023 reply

    This should be possible. The function translate(pStringID) can be used to translate anything, it could be used to set the tooltips. Something like

    set the tooltip of button “anybutton” to translate(“ACCEPT_STRING_ID”)

    should work. If you still have issues with this, please contact support@livecode.com and we’ll be happy to help.

Join the conversation

*