With OutSystems you can create apps using any human language. E.g. creating an app in English is as easy as creating an app in Portuguese. But what if your app needs to be both in English and in Portuguese, and it’s up to the end-user to choose the language in which to use the app?
For web-responsive apps, OutSystems already provides built-in mechanisms to localize the app. However, those same mechanisms are not yet available for mobile apps. In this document we describe a component that you can use to easily create multi-language mobile apps.
Together with the component, we’re also providing an app, MultiLingual To Do, that you can use as an example when creating your own multi-language mobile app.
At a high-level, creating a multi-language app is a two step process involving two different personas: developers and translators.
Internationalization (or I18n) is the process of making your app ready to be translated.
In this section we describe the steps that you need to follow when using the MultiLingual component.
The MultiLingual module exposes several client actions that you might need to reference:
Typically you’ll want to reference the GetLocale, SetLocale, and GetTranslation actions, and either AddTranslations or AddTranslationsFromResource depending on how you plan to store and load translations.
You need to identify each Text widget that you want to translate by setting the data-trans attribute.
The value of the attribute is a key (a text, also known as the “resource key”.) Keys don’t need to follow a specific format, but you should ensure their uniqueness: two widgets with the same key will be translated at runtime to the same value. A simple way to avoid duplicates is to use GUIDs.
In the example below we’re setting the data-trans attribute in a Text widget.
Text literals in client-side expressions are translated using the GetTranslation function. This function expects two arguments:
In the example below we’re setting Input_DueDate.ValidationMessage. The original message was "Due Date cannot be in the past."
You must keep a list of the resource keys used in Text widgets and the GetTranslation function, together with their associated default text. This list will be used by the translator when localizing your app. As an suggestion, you may use Excel to keep track of translations.
Using the examples in the preceding sections as a reference, this would be the information that you’d collect:
Your app needs to explicitly load translations at runtime; the MultiLingual component doesn’t do that automatically. The place where translations are loaded is app-specific, but in most cases it makes sense to load translations when the app starts (in theOnApplicationReady system event.)
The MultiLingual component offers two different ways to load translations. The one that you should use depends on where you store translations:
If you opt to bundle the translations as a resource in your app, you can use the AddTranslationsFromResource action to load them.
In the example below, we’re using the AddTranslationsFromResource action in the OnApplicationReady system event to load the translations in the ToDo.translations.json resource.
In this case we’re bundling several languages in a single resource file; if you choose to split languages throughout several files then you have to call AddTranslationsFromResource once for each file.
Check the attached PDF file for additional information on what the AddTranslationFromResource action expects as inputs.
The MultiLingual component also allows you to load translations from an arbitrary source, e.g. from a database entity, by using the AddTranslations action. Storing translations in a database entity is interesting for scenarios in which your app and its translations have different lifecycles, e.g. if you need the flexibility to update translations without republishing the app.
It is your responsibility as a developer to prepare the data in the format expected by theAddTranslations action.
The SetLocale action is used at runtime to set the desired language for the app. If you do not call it, the application will be presented in the default language, i.e., in the language in which it was designed.
By setting the locale, the next time a screen is rendered it will use the translations defined for that locale. A resource’s default value will still be used in the following two instances:
The place where SetLocale is called depends entirely on your particular app. As an example, you may have a Settings screen where the user can select the language you want. When the settings are saved you then call the SetLocale action.
Another alternative is to use the device’s preferred language. See the Globalization Plugin component in the Forge for an example.
Localization (or L10n) is the process of adding support for a particular language.
Localization involves the work of a translator (a process which is out of the scope of this document). The translator is responsible for providing a translation for each resource that has been identified by the developer.
After the translator hands off the translations to the developer, it is the developer’s responsibility to bundle them into the app. As described in the "Load Translations" section, he may opt to bundle the translations as resources inside the app, a process which is detailed below, or load them in a custom way.
There is a set of predefined messages that can be always translated and for which the developer doesn’t need to create resource keys: built-in validation and upgrade messages.
Check the attached PDF for a full list of keys and messages.
Add the file with the translations as a resource to your app’s main module. The resource file must follow the rules presented in the "Load translations from a local resource" section. Make sure that the resource has the “Deploy Action” set to “Deploy to Target Directory”, as in the example below.
Hello
The PDF file is now being shown to be downloaded.
Regards
I'm new to Outsystems and this resource, so I may be looking in the wrong location and I apologize for that. But I'm not finding the PDF file of instructions. Could you either send to me, or point me in the right direction? Thanks!
JM Ackerman wrote:
Hello JM,
The PDF is attached to the 1st post, but unfortunately we're having an issue with the forums and it's not visible... This problem will be fixed soon, but in the meantime I've added the bulk of the documentation on the 1st post. Hope that helps.
Cheers,R
Hey JM,
We have fixed this issue, so you should be able to see the PDF now.
Thanks for your patience!
-Alexandra
So if I understand this correctly, the load translations call will load the translations and translate all fields with attribute data-trans set to the selected locale, i'm searching for a translation action in layout or screen but doesn't seem to be here .. so all is done by the LoadTranslations call ? And if I change runtime the translation, I should reload the correct translation to make it work on the screen ?
Hi Wim,
The LoadTranslations action only loads the translations and stores them in memory. The actual translation happens when a screen is rendered, and that is done automatically by the component. That's the reason why you don't see any action being explicitly called to translate the text literals.
Whenever you change the translations (by calling LoadTranslations again), the new translations will be effective the next time the screen is rendered.
Hope this helps,
Hugo Lourenço
That helped a lot, I now understand the mechanics of this thing
Wim
Hi,
I want to translate my mobile application, but the only thing I have managed to do has been to translate the current screen, once the screen change the translation dissapears. How can I translate all the screens at once? I can do this in WEB application but not in mobile app.
Regards,
Jordi.
Great component but still a lot more work than translating web apps. Adding the function AddTranslationFromResource on each label is quite a job.
Are there plans (don't know if it is possible) to make it more aligned with web development?
I find it quite interesting & it is a native kind of approach where we maintain same key with multiple different values for languages.
Perhaps I have some question:
- How I can detect the device language i.e Mobile Settings , so that I can set the default one to that?
- What about RTL orientation like Arabic Language, I did see the input check in your functions but I just want to know your feedback on that ?
thanks
assif_tiger wrote:
Answer :
I've uploaded some new resources, but if i download resources, the excel doesn't have new ones, even if i can see them in the dashboard
There's nothing like excel with this plugin, you might be working with Multilingual Web Component.
Bette4 you post your question with more detail on Multilingual Web Component Support.
I have been using this component within a POC for a new application we are developing.I have noticed an intermittent bug, whereby the translations fail to load.When I output GetLocale in an expression on screen there is no value set. However, when I add a JS block with a console.log into the OnApplicationReady process we can see the locale is being set.e.g. on the screen we have "locale set:" but, in the console we have Locale set: {"Locale":"en-us"}Note. this only appears to occur in Chrome.
Do you have any advice as to why this might be happening?