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