Geertjan's Blog

Translating Oracle JET Applications

Geertjan Wielenga
Product Manager

The Oracle JET MOOC starts on Monday. When we talk about Oracle JET we always say that it solves "enterprise challenges". One of these is internationalization/localization/translation of JavaScript applications. Recently I started playing with the translation features of Oracle JET and they're pretty impressive. Really, if you want to create JavaScript applications that need to be translated, you should look no further than Oracle JET.

Let's start by looking at the result of a small sample I've been working on. Here's an application that can be switched to 4 different languages, with a screenshot of 3 of them below: 

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 the Oracle 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:

    "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:

  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.formats = ko.observableArray(["english"]);
self.date = ko.observable();
self.greeting = ko.observable("Good Morning");
self.localeDate = ko.observable();
self.localeGreeting = ko.observable();
self.setLang = function (data) {
var newLang = '';
switch (data) {
case 'Arabic':
newLang = 'ar-EG';
case 'Czech':
newLang = 'cs-CZ';
case 'French':
newLang = 'fr-FR';
newLang = 'en-US';
function () {
$('html').attr('lang', newLang);
if (newLang === 'ar-EG') {
$('html').attr('dir', 'rtl');
} else {
$('html').attr('dir', 'ltr');
return new mainContentViewModel();

And here's the view:

<div data-bind="ojComponent: {component: 'ojButtonset', checked: formats}">
<label for="arabic">Arabic</label>
<input data-bind="click: function(){setLang('Arabic');}"
type="checkbox" value="arabic" id="arabic"/>
<label for="czech">Czech</label>
<input data-bind="click: function(){setLang('Czech');}"
type="checkbox" value="czech" id="czech"/>
<label for="french">French</label>
<input data-bind="click: function(){setLang('French');}"
type="checkbox" value="french" id="french"/>
<label for="english">English</label>
<input data-bind="click: function(){setLang('English');}"
type="checkbox" value="english" id="english"/>
<span style="font-size: 50pt" id="greeting" data-bind="text: localeGreeting"></span>
<span data-bind="text: localeDate"></span>
<input id="dateInput" type="text"
data-bind="ojComponent: {
value: date,
datePicker: {changeMonth: 'none', changeYear: 'none'}

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


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. 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.