Hi All, this posting started off as a simple(ish) question I was going to post as a discussion but as I went through building up my findings I ended up answering (some) of my own questions, so thought I’d share my findings for all to read and comment on…  It began with some simple queries around the usage of i18n resource bundles.

I’m building up a Shell based desktop app template and using it to work through various different controls, partly as a learning exercise and partly in response to this brilliant blog.

I’ve hit a bit of a funny with i18n resource bundles and how they are parsed at runtime, that I just can’t get my head around.  I’m pretty sure there is a simple answer but I’ll be ****** if I know what it is 😉

In my index.html I have


<title>UI5 Desktop App - Boilerplate</title>


within the <HEAD> tag.  I’d like to change this to be replaced by something like


<title>"{i18n>APP.TITLE}"</title>


so that a translated title can come from my i18n.properties file.  I understand that this can’t work in the index.html file as at that point, the i18n model has not been loaded.  I’ve tried performing a


document.title = "{i18n>APP.TITLE}"


in various places through my application:-

  • app.js – this doesn’t work and that makes sense, as at this point I still haven’t loaded the i18n model
  • Component.js – this doesn’t work even if I perform the title update after I have loaded the i18n model as per the below code.  I’m aware that just doing a “document.title…” at this point probably isn’t the best thing to do but I’m just playing around at the moment:-

jQuery.sap.declare("app.Component");
jQuery.sap.require("sap.ui.model.resource.ResourceModel");
sap.ui.core.UIComponent.extend("app.Component", {
  createContent : function() {
  // App View
  var oView = sap.ui.jsview("app", "view.App");
  // set i18n model
  var i18nModel = new sap.ui.model.resource.ResourceModel({
  bundleUrl : "i18n/i18n.properties"
  });
  oView.setModel(i18nModel, "i18n");
  // over-ride window title?
  document.title = "{i18n>APP.TITLE}";
  return oView;
  }
});



This gives me:

i18n Title.jpg

  • App.controller.js – adding it into the onInit() function or onAfterRendering() function or indeed any other function, again this doesn’t work and gives me the same result as the screenshot above.  (Can you tell I’m clutching at straws here?!)

Moving on, in a similar vein I’m trying to add a link to an external webpage from a Button and add it as a headerItem in my Shell.  So I have code like this:


// define any header items, next to the logout button - Button, MenuButton or TextView are allowed
  headerItems : [
  // TextView that could show user name
  new sap.ui.commons.TextView({
  text : "User Name", // logic required to authenticate user and determine their name
  tooltip : "{i18n>APP.USERNAME_TOOLTIP}"
  }),
  // Button to link to "your company's" website
  new sap.ui.commons.Button({
  text : "{i18n>APP.COMPANY_LINK_TEXT}",
  tooltip : "{i18n>APP.COMPANY_LINK_TOOLTIP}",
  press : function(oEvent) {
  window.open("{i18n>APP.COMPANY_LINK_URL}");
  }




Here, instead of opening a new window with “http://www.yourcompany.co.uk” (the value of APP.COMPANY_LINK_URL in my i18n.properties file) I get this:

NewURL.jpg

Again, it appears that the i18n translation hasn’t occured, just like it doesn’t if I try to use it in an alert(“”) function or by setting the document.title property as shown above.

I’ve also tried to do something like this:


// store company url in variable for later
  var companyURL = "{i18n>APP.COMPANY_LINK_URL}";




<snip>


// Button to link to "your company's" website
  new sap.ui.commons.Button({
  text : "{i18n>APP.COMPANY_LINK_TEXT}",
  tooltip : "{i18n>APP.COMPANY_LINK_TOOLTIP}",
  press : function(oEvent) {
  window.open(companyURL);
  }




With similar results.

So, in a round-about manner I finally get to my question – is there somewhere I have missed that explains how and when the “i18n>” data binding translation works as I can’t find it but am conscious it will just be hidden somewhere in the DemoKit and I’ve missed it!

I do actually have a working solution, that makes use of direct access to my resource bundle via code, rather than depending upon the data binding method.  So in my app.js file I now have:


sap.ui.localResources("view");
sap.ui.localResources("model");
sap.ui.localResources("app");
sap.ui.localResources("img");
jQuery.sap.require("app.Component");
jQuery.sap.require("jquery.sap.resources");
// get resource bundle for use where a straight translation from data
// binding doesn't appear to work
var oBundle = jQuery.sap.resources({
  url : "i18n/i18n.properties"
});
// store company url in variable for later
var windowTitle = oBundle.getText("APP.TITLE");
document.title = windowTitle;
// create app Component and place at dom element with id = content
new sap.ui.core.ComponentContainer({
  name : "app"
}).placeAt('content');

This ensures the title of my window comes from my i18n files and hence will be translated at run time.

For my company url, I’ve done similar in my App.view.js:


jQuery.sap.require("jquery.sap.resources");

<snip>


// get resource bundle for use where a straight translation from data
  // binding doesn't appear to work
  var oBundle = jQuery.sap.resources({
  url : "i18n/i18n.properties"
  });
  // store company url in variable for later
  var companyURL = oBundle.getText("APP.COMPANY_LINK_URL");

<snip>


// Button to link to "your company's" website
  new sap.ui.commons.Button({
  text : "{i18n>APP.COMPANY_LINK_TEXT}",
  tooltip : "{i18n>APP.COMPANY_LINK_TOOLTIP}",
  press : function(oEvent) {
  window.open(companyURL);
  }

This now also works as expected.  In summary, it appears that the data binding route to i18n texts doesn’t work in all scenarios and I’ll be honest in stating I don’t know why.  At least with the above snippets of code I do have a solution that works, isn’t particularly untidy and doesn’t seem to add any overhead or performance issues.

Hope this is of use to others.

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Pritin Tyagaraj

    Hey Gareth,

    “Hello”, “My title” and “{i18n>MY_TEXT_KEY}” are all just strings in Javascript; and they behave exactly like “just strings” until they are expected to carry more information than ‘just a series of characters’.

    When you do a property binding (like you’ve bound the Button’s ‘text’ property in your last snippet), the UI5 framework kicks-in (because you’re dealing with a UI5 control) and looks for a particular structure in the string you’re using. If it finds curly braces and a “X>Y” structure, it interprets the ‘X’ (i18n) as the model name and ‘Y’ (MY_TEXT_KEY) as the path within the model.

    When you do a document.title = “xyz”, you’re talking directly to the browser (and not via the UI5 framework), and for the browser, “xyz” is just a sting. It doesn’t look for a specific structure within it, and is also unaware of what a “model” or “text bundle” means. Only the UI5 framework knows about them.

    I hope the explanation helps a bit 🙂

    Cheers,

    Pritin

    (0) 
    1. Gareth Ryan Post author

      Hi Pritin,

      Thanks – that makes perfect sense and was what I “thought” was happening but good to have confirmation.

      Cheers,

      Gareth.

      (0) 

Leave a Reply