Translating Oracle JET Applications

Datetime:2016-08-23 02:23:40          Topic: Oracle           Share

I've been playing with the translation features of Oracle JET and they're pretty impressive.

Let's start by looking at the result. Here's 4 different languages in action, with a screenshot of 3 of them:

Everything to achieve the above is documented in " Internationalizing and Localizing Applications " in the Oracle JET Developer Guide. This topic is also dealt with in the 3rd week of theOracle JET MOOC.

There are several bits and pieces involved in this sample:

  1. Bundled translations for Oracle JET components.  Oracle JET components, such as the date/time picker that you see above, have already been translated. The translations are found in libs/oraclejet/dist/js/libs/oj/resources/nls.
  2. Custom translation bundles.  Aside from the Oracle JET components, which have already been translated, Oracle JET provides a facility for storing and loading your own translations. Below, you can see a folder called "resources/nls", with subfolders for each of the languages I am supporting:

    In "main.js", I have this, which registers the "resources/nls/l10" structure and merges it with the translations that are provided by Oracle JET:

    config: {
        ojL10n: {
            merge: {
                'ojtranslations/nls/ojtranslations': 'resources/nls/l10'
            }
        }
    }

    The most important file in "resources/nls" is the file named "l10.js", which could be named anything at all, so long as it matches the registration in "main.js" shown above. It looks like this, in my case:

    define({
      "root": {
        "date": "Date:",
        "greeting": "Good Morning"
    },
      "ar": true,
      "fr": true,
      "cs": true
    });
    In each of the folders that have been enabled above, i.e., "ar", "fr", and "cs", translations of the above texts are found, e.g., in "ar":

    Now, anywhere in our viewModel, we can use this statement to retrieve the greeting of the current locale:

    oj.Translations.getTranslatedString('greeting')
  3. RTL Support. Bidirectional features are included too,read here, simply by setting the "dir" attribute of the "html" element to "rtl" and back to "ltr".
  4. Dynamic Locale Switching. Via the buttons you see above, the locale can be switched,as described here.

Following from the above, the complete code for the viewModel is as follows, focused on enabling the switching between locales, which will cause the translation bundles to be loaded dynamically:

define(['ojs/ojcore', 'knockout', 'ojs/ojbutton', 'ojs/ojdatetimepicker'],
    function (oj, ko) {
        function mainContentViewModel() {
            var self = this;
            self.date = ko.observable();
            self.greeting = ko.observable("Good Morning");
            self.localeDate = ko.observable();
            self.localeDate(oj.Translations.getTranslatedString('date')); 
            self.localeGreeting = ko.observable();
            self.localeGreeting(oj.Translations.getTranslatedString('greeting')); 
            self.setLang = function (data) {
                var newLang = '';
                switch (data) {
                    case 'Arabic':
                        newLang = 'ar-EG';
                        break;
                    case 'Czech':
                        newLang = 'cs-CZ';
                        break;
                    case 'French':
                        newLang = 'fr-FR';
                        break;
                    default:
                        newLang = 'en-US';
                }
                oj.Config.setLocale(newLang,
                    function () {
                        $('html').attr('lang', newLang);
                        if (newLang === 'ar-EG') {
                            $('html').attr('dir', 'rtl');
                        } else {
                            $('html').attr('dir', 'ltr');
                        }
                        self.localeDate(oj.Translations.getTranslatedString('date')); 
                        self.localeGreeting(oj.Translations.getTranslatedString('greeting')); 
                        $('#dateInput').ojInputDateTime('refresh');
                    }
                );
            };
        }
        return new mainContentViewModel();
    });

And here's the view:

<button data-bind="
        click: function(){setLang('Arabic')}, 
        ojComponent: {component: 'ojButton', label: 'Arabic'}"></button>
<button data-bind="
        click: function(){setLang('Czech')}, 
        ojComponent: {component: 'ojButton', label: 'Czech'}"></button>
<button data-bind="
        click: function(){setLang('French')},
        ojComponent: {component: 'ojButton', label: 'French'}"></button>
<button data-bind="
        click: function(){setLang('English')}, 
        ojComponent: {component: 'ojButton', label: 'English'}"></button>
<br/>
<br/>
<span style="font-size: 50pt" id="greeting" data-bind="text: localeGreeting"></span>
<br/>
<span data-bind="text: localeDate"></span>
<input id="dateInput" type="text" 
    data-bind="ojComponent: {
        component:'ojInputDateTime', 
        value: date,
        datePicker: {changeMonth: 'none', changeYear: 'none'}
    }"/>

That's it. And here's the sample code shown above:

https://github.com/GeertjanWielenga/OJETCourse/tree/master/Part-024

A next step is to generate all the buttons automatically from JavaScript, i.e., there should be some way to provide new buttons to switch to new languages easily, without having to code them in HTML, i.e., in the viewModel, find the lists of available translation locales and create the buttons, and their logic, based on that.





About List