UI5
No Comments

Ultimate Guide to Internationalization or i18n in SAP UI5

Grouping of various flags of the world on white.

The SAP UI5 framework offers out of the box an internationalization functionality. Internationalization means that all texts of an application are in a central place and can easily be translated into different languages – that an application offers a mechanism to translate its texts in multiple languages.

The abbreviation for internationalization is i18n. i18n can be broken down into three parts to understand why i18n is supposed to stand for internationalization:

  1. i for the first letter of the word internationalization
  2. n for the last letter of the word internationalization
  3. and 18 for the eighteen letters between the first letter i and the last letter n of the word internationalization: in(1)t(2)e(3)r(4)n(5) a(6)t(7)i(8)o(9)n(10)a(11)l(12)i(13)z(14)a(15)t(16)i(17)o(18)n.

Therefore, i18n means: i plus 18 letters plus n equals internationalization.

The full form of the abbreviation i18n is internationalization: i + 18 letters + n.
The full form of the abbreviation i18n is internationaliation: i plus eighteen letters plus n – i18n.

How i18n Works in SAP UI5

The i18n mechanism in SAP UI5 consists of three parts:

  1. resource bundles
  2. resource model
  3. controls that consume the resource model

The resource bundles are the actual language files which hold the key for a translation and the translation itself.

The resource model brings the resource bundles and the controls which consume the resource bundles together – kind of the glue.

And the controls consume the resource bundles and therefore, language data through the model via bindings that refer to the key of the i18n text.

Data binding in SAP UI5.
The i18n model is in its core, just a JSON model. The i18n model holds the language data from the resource bundles. The controls consume via binding paths the language data from the i18n model.

Resource Bundles

A resource bundle is a file that contains the translatable texts. For each language, there is one resource-bundle. Plus, one default resource bundle that the SAP UI5 application uses if no resource bundle exists for a language.

A resource bundle stores the translatable texts as key-value pairs. A resource bundle key-value pair exists of a key and a value separated by an equal sign.

The key is consistent overall resource bundles – it always remains the same – the value changes to the corresponding language. The keys are written in CamelCase. And the value is the actual text that is supposed to be displayed.

For example, a key-value pair in a resource bundle for the English language:

# key-value pair in a resource bundle for English

appTitle=My Application

And a key-value pair for the same text in a resource bundle for the German language:

# key-value pair in a resource bundle for German

appTitle=Meine Application

Or for the French language:

# key-value pair in a resource bundle for French

appTitle=Mon application

A resource bundle has a simple structure; in a resource bundle exists no hierarchy – the structure is flat:

# resource bundle file

appTitle=My Application
description=That is a SAP UI5 application

viewTitle=My View

dialogTitle=My Dialog

cancel=Cancel
save=Save

The resource bundle files reside in the i18n folder in the folder structure of an SAP UI5 application:

— webapp
—— controller
—— i18n
——— i18n.properties
——— i18n_en.properties
——— i18n_en_US.properties
——— i18n_de.properties
——— i18n_de_CH.properties
——— i18n_fr.properties
—— localService
—— model
—— test
—— view
—— localService
—— model
—— test
—— view

All resource bundles have as naming convention the suffix .properties. Plus, their names start with an i18n, followed by an underscore, and the acronym for a language, such as i18n_en.properties. All in lower case letters.

Sometimes a language can be split into more specific languages, such as English can be split into American English and British English. A resource bundle for a more specific language file has in its name an additional underscore after the first language acronym followed by the more specific language acronym in upper case letters, such as US for American English: i18n_en_US.properties.

The SAP UI5 framework always requests the most specific language file first. For example, if the browser language is set to US then the SAP UI5 framework requests the i18n_en_US.properties resource bundle.

If an i18n_en_US.properties file does not exist, then the application asks for the next most specific resource bundle: In case of the example from above, is that the i18n_en.properties resource bundle.

If an i18n_en.properties file does not exist then the SAP UI5 framework goes for the default language of the application: The i18n.properties file. That is called the language determination fallback process.

Resource Model

The resource model is the bridge between the resource bundles with the language data and the controls which consume the language data. The resource model gets initiated in the manifest.json.

Once the resource model is described in the manifest.json, the SAP UI5 framework takes care of everything else: Loading the resources bundles into the resource model and providing the language data globally.

// manifest.json

{
  "_version": "1.12.0",
  
  "sap.app": {
    "id": "my.app",
    "type": "application",
    "i18n": "i18n/i18n.properties",
    "title": "{{appTitle}}",
    "description": "{{appDescription}}",
    "applicationVersion": {
      "version": "1.0.0"
    }
  },
  
  "sap.ui": {
    "technology": "UI5",
    "deviceTypes": {
      "desktop": true,
      "tablet": true,
      "phone": true
    }
  },
  
  "sap.ui5": {
    "rootView": {
      "viewName": "my.app.view.Foo",
      "type": "XML",
      "async": true,
      "id": "foo"
    },
    "dependencies": {
      "minUI5Version": "1.60",
      "libs": {
        "sap.m": {}
      }
    },	
    "models": {
      "i18n": {
        "type": "sap.ui.model.resource.ResourceModel",
        "settings": {
          "bundleName": "my.app.i18n.i18n"
        }
      }
    }
  }

}

Controls

The controls consume the language files – a control is any SAP UI5 element, such as a button or a table. Against the backdrop of best practice in SAP UI5, controls are initiated via an XML view and adapted in a controller.

A sap.m.Button control initiated in an XML view:

<!-- instantiate control via an XML view -->

<button 
  id="button-id" 
  text="foo" 
  press="onButtonPress">
</button>

A sap.m.Button control adapted in a controller:

// adapt control in a controller

var oButton = this.byId("button-id");
oButton.setText("bar");

The SAP UI5 internalization framework works for both controls initiated in an XML view and controls adapted in a controller.

SAP UI5 i18n in XML Views

Best practice in SAP UI5 is it to use XML views to instantiate controls such as a button or a table. To use the i18n framework for a control in an XML view is fairly easy.

A control uses the i18n data through the standard binding syntax. Binding means in SAP UI5 to connect data from a model to a control.

For example, there is a model named myModel with data for the text of a button. For the sake of simplicity, the model is a JSON model and holds the following data:

// JSON model data

{
  "buttonText": "Press me"
}

The button text data gets bind to the text property of the button in an XML view in the following way:

<!-- bind the JSON model data to an SAP UI5 control -->

<Button text="{myModel>/buttonText}">

Therefore, the general binding syntax is {modelName>pathToData}. The binding syntax consists of five parts:

  1. {
  2. model name
  3. >
  4. data path
  5. }

The model name of the internationalization model in SAP UI5 is i18n as declared in the manifest.json.

And as stated above the structure of a resource bundle file is entirely flat. Therefore, the data structure in the i18n model, which holds the resource bundles data is entirely flat as well. Therefore, after the model name i18n follows just the language data key of the resource bundle without any path

Hence, to bind language data from the i18n model to a control the binding syntax is {i18n>resourceBundleKey}.

  1. {
  2. i18n as model name
  3. >
  4. resourceBundleKey as data path
  5. }

For example, in the resource bundle file i18n_en.property exists the following key and value language pair:

# i18n_en.properties
# pressMe - key
# Press me - value, the text

pageTitle=Foo Bar

Then the text Foo Bar for the English language would be set to a page title in an XML view like this:

<!-- bind the Foo Bar text via its key to a page title -->

<mvc:View 
  height="100%"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  
  <Page title="{i18n>pageTitle}"></Page>

</mvc:View>

And that it is – the SAP UI5 framework takes care of everything else behind the scenes, such as loading the data from the right resource bundle according to the browser language of the user or displaying the text.

SAP UI5 i18n in Controllers

To adapt an SAP UI5 control in a controller is a bit more tricky than to add an i18n text in an XML view. First, it is necessary to manually retrieve in the controller from the i18n model the i18n resource bundle to access a text. Second, to retrieve the control which is supposed to consume the text. Only then the i18n text can be extracted from the i18n resource bundle and glued to the control.

Therefore, there are three steps necessary to bind an i18n text to a control in a controller:

  1. retrieve from the i18n model the i18n resource bundle
  2. retrieve the control
  3. get and glue the i18n text to the control

First, retrieve from the i18n model the resource bundle in the controller …

// in some method in the controller

...

foo: function() {

  // retrieve the i18n resource bundle
  var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

},

...

… then second, retrieve retrieve the control from the view …

// in some method in the controller

...

foo: function() {

  // retrieve the i18n resource bundle
  var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

  // retrieve the control from view
  var oButton = this.byId("button-id");

},

...

… and finally, to retrieve from the resource bundle the i18n text and set it to the control …

// in some method in the controller

...

foo: function() {

  // retrieve the i18n resource bundle via the i18n model
  var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

  // retrieve the control via its id "button-id" from the controller's view
  var oButton = this.byId("button-id");

  // retrieve the i18n text via its key "bar" from the resource bundle
  // and set it to the control
  oButton.setText(oResourceBundle.getText("bar"));

},

...

SAP UI5 i18n and Parameters

It is possible to you use parameters in an i18n text – to dynamically enhance an i18n text with words or sentences. For example, if an i18n text says Products but it is supposed to dynamically show after Products the count of the products. This count comes from the back-end via an OData service and therefore SAP UI5 OData model.

For i18n parameters are two steps necessary:

  1. create an i18n key/value pair with parameters in the i18n resource bundles
  2. glue the 18n text to a control and pass the parameters to the i18n text

First, set a key/value pair with a parameter in the i18n resource bundles. For example, the default resource bundle i18n.properties:

# default resource bundle i18n.properties

products=Products {0}

The syntax for a parameter in an i18n text is {<number>}; if there would be three parameters then the text would be, for example, ‘Products overall {0}, products sold {1}, and products in production {2}‘:

# multiple parameters

productsOverallSoldProduction=Products overall {0}, products sold {1}, and products in production {2}

A parameter number starts with 0 and increments with each new parameter for a particular text. For a new text, the first parameter starts again with 0.

Second, after the key/value pair with parameters is set in the resource bundles, the i18n text is to glue to a control and the parameters are to pass to the text.

The gluing to the control and passing of the parameters is to do in an XML view or a controller via binding.

i18n text with parameters binding in an XML view:

<!-- bind the i18n text with parameters via its key to a page title -->
<!-- i18n key is productsOverallSoldProduction from the example above -->

<mvc:View 
  height="100%"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  
  <Page
    id="foo-bar"
    title="{
    parts:[
      {path:'i18n>productsOverallSoldProduction'},
      {path:'odataModel>/argument1'}, 
      {path:'odataModel>/argument2'},
      {path:'odataModel>/argument3'}
    ], 
    formatter:'jQuery.sap.formatMessage'}">
  </Page>

</mvc:View>

i18n text with parameters binding in a controller:

// in some method in the controller

...

foo: function() {

  // retrieve the i18n resource bundle via the i18n model
  var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

  // retrieve the dynamic values from the OData model
  var sProductsC = this.getView().getModel("oDataModel").getProperty("/Products/count");
  var sProductsSoldC = this.getView().getModel("oDataModel").getProperty("/ProductsSold/count");
  var sProductsProdC = this.getView().getModel("oDataModel").getProperty("/ProductsProduction/count");
  
  // set the i18n text to the control via its key
  // pass the dynamic arguments to the i18n text
  this.byId("foo-bar").setText(oResourceBundle.getText("bar", [
  
    sProductsC,
    sProductsSoldC,
    sProductsProdC    

  ]));

},

...

Full Example of SAP UI5 i18n in an XML View and a Controller Each With and Without Parameters

The requirement is to provide a French translation for the texts ‘that is foo’ and ‘bar <closed, open> at <date>’. Whereby, <closed, open> and <date> are two parameters which get dynamically filled with data from an OData model. For example, the text could be ‘bar closed at 11.11.2019’.

Plus, when a button is clicked both texts are supposed to switch – the ‘that is foo’ text switches with the ‘bar <closed, open> at <date>’ and vice versa.

The steps that need to be done:

  1. i18n resource bundle file – i18n_fr.properties
  2. key/value pair for the text ‘that is foo’ in i18n_fr.properties
  3. key/value pair for the text ‘bar <closed, open> at <date>’ in i18n_fr.properties
  4. set up i18n framework in manifest.json
  5. set i18n text ‘foo’ in XML view
  6. set i18n text ‘bar <closed, open> at <date>’ in XML view
  7. set i18n text ‘foo bar’ for button press in controller

First, the i18n resource bundle and the keys and their texts …

# i18n_fr.properties resource bundle file

foo=c'est foo
bar=bar {0} à {1}

… second, the i18n setup in the manifest.json …

// i18 setup in the manifest.json

{
  "_version": "1.12.0",
  
  "sap.app": {
    "id": "my.app",
    "type": "application",
    "i18n": "i18n/i18n.properties",
    "title": "{{appTitle}}",
    "description": "{{appDescription}}",
    "applicationVersion": {
      "version": "1.0.0"
    }
  },
  
  "sap.ui": {
    "technology": "UI5",
    "deviceTypes": {
      "desktop": true,
      "tablet": true,
      "phone": true
    }
  },
  
  "sap.ui5": {
    "rootView": {
      "viewName": "my.app.view.Foo",
      "type": "XML",
      "async": true,
      "id": "foo"
    },
    "dependencies": {
      "minUI5Version": "1.60",
      "libs": {
        "sap.m": {}
      }
    },	
    "models": {
      "i18n": {
        "type": "sap.ui.model.resource.ResourceModel",
        "settings": {
          "bundleName": "my.app.i18n.i18n"
        }
      }
    }
  }

}

… third, set the i18n text in the XML view …

<!-- bind the texts via its key -->
<!-- pass arguments to the bar text -->

<mvc:View 
  height="100%"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  
  <Text
    id="text1" 
    text="{i18n>foo}"></Text>

  <Text
    id="text2" 
    text="{ 
    parts:[
      {path:'i18n>bar'},
      {path:'odataModel>/state'}, 
      {path:'odataModel>/date'}
    ], 
    formatter:'jQuery.sap.formatMessage'}>
  </Text>

  <Button
    text="Change Texts"
    press="onButtonPress">
  </Button>

</mvc:View>

… four, adapt the texts on a button click in the controller …

// in the XML view's controller

...

onButtonPress: function() {

  // retrieve the i18n resource bundle via the i18n model
  var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

  // retrieve the dynamic values from the OData model
  var sState = this.getView().getModel("oDataModel").getProperty("/state");
  var sDate = this.getView().getModel("oDataModel").getProperty("/date");
  
  // switch the i18n text
  // set the i18n text to the control via its key
  // pass the dynamic arguments to the i18n text with parameters
  this.byId("text2").setText(oResourceBundle.getText("foo");

  this.byId("text1").setText(oResourceBundle.getText("bar", [
  
    sState,
    sDate

  ]));

},

...

SAP UI5 i18n and Right-to-Left Languages

All texts in the i18n resource bundle files are ISO-8859-1 (LATIN-1). That has an important effect regarding right-to-left languages such as Arabic, Hebrew, and Urdu, etc.

LATIN-1 assumes that text is written from right to left by default and therefore, left-to-right languages must be entered into the resource bundle file through Unicode and not through the script of the native language. Plus, the characters need to be reversed.

For example, the text is supposed to say Shalom Olam. That is Hebrew and means Hello World.

First, there needs to be a Hebrew resource bundle file – i18n_he.properties. Second, the text needs to be entered in Unicode and not the Hebrew script. Third, the text needs to be entered in the reverse order.

Therefore, it has to look like that …

# i18n resource bundle file i18n_he.properties
# RIGHT - right-to-left texts via Unicode in reverse order

helloWorld=\u05E9\u05DC\u05D5\u05DD \u05E2\u05D5\u05DC\u05DD

… and NOT like that where the text is entered in Hebrew script without Unicode:

# i18n resource bundle file i18n_he.properties
# WRONG - right-to-left texts via the respective language script

helloWorld=םולש םלוע

Most Recent Articles

Will SAP UI5 replace the SAP Web UI?

SAP Full Forms

More Similar Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu