Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
Showing results for 
Search instead for 
Did you mean: 
Developer Advocate
Developer Advocate
This is a searchable description of the content of a live stream recording, specifically "Episode 17 - Digging into the annotation driven UI" in the "Hands-on SAP dev with qmacro" series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the "Catch the replays" section of the series blog post.

This episode, titled "Digging into the annotation driven UI", was streamed live on Fri 05 Apr 2019 and is approximately one hour in length. The stream recording is available on YouTube.

Below is a brief synopsis, and links to specific highlights - use these links to jump directly to particular places of interest in the recording, based on 'hh:mm:ss' style timestamps.

Brief synopsis

We take a look at the simple UI that we created in the previous episode and look a little bit behind the scenes, to learn a bit more about annotations, OData calls and more.

00:02:58: Pointing out the Subreddit Mechanical Keyboards where I get my fill of news and advice. Recommended, and talking about different keyboards such as the Vortex Race 3 (75% keyboard) and the Anne Pro 2 (60% keyboard), as rsletta is thinking about taking the plunge and getting one (perhaps a Ducky One).

Also I mention the geekiest (and possibly the best) Subreddit ever - which is vimkeyboard. Wonderful.

00:07:48: Reviewing what we did in the previous episode, getting a simple UI on the screen powered by UI annotations and Fiori Elements.

00:09:00: Introducing the Slack channel I recently created as a backchannel for the Hands-on SAP dev series. I did think of using Discord (as Ronnie mentions) but I thought that Slack was more likely to be a tool that folks like us use already, and may already be a member of the SAP Mentors and Friends Slack workspace where this new channel lives.

The idea of this channel is to have a continuum for chat between episodes, nothing strenuous or high-volume, just an ambient space for us to hang out in. You can join the workspace via this link here: and then head on over to the #handsonsapdev channel. See you there!

00:11:30: While we're on the subject of Slack channels, there's also a channel for discussion of the work on the GitHub project SITreg implemented in the SAP Cloud Application Programming Model, which is #sitregdiscussion, in the same SAP Mentors and Friends Slack workspace.

00:12:45: Introducing another live streamer Jeff Fritz, who has a great channel on Twitch and is building software for the Elgato Streamdeck.

00:13:45: Announcing that iinside will be joining us on the next episode, talking about CAP and Java!

00:15:30: Looking at what we have as far as the Northbreeze app is concerned, exploring the contents of the northbreeze directory.

00:16:30: Noting, in passing, the function import hello's definition (in service.cds) and implementation (in service.js), and also (trivially) that I turned on the 'box' outline in my Ranger setup.

00:17:40: Starting the app up with cds deploy && cds serve all and looking at the app in its natural habitat (i.e. the sandbox launchpad).

00:19:45: Opening up the Chrome Developer Tools to see what's going on behind the scenes.

00:21:40: Looking more closely at the annotations in index.cds. First, we're using SelectionFields: [] (i.e. an empty list) to cause no selection (filter) fields to appear in the UI. Then, we have a set of in-line label definitions for the line item columns, like this:
LineItem: [
{ Value: ID, Label: 'ID' },
{ Value: name, Label: 'Name' },
{ Value: country, Label: 'Country' }

These labels appear in the column headings in the UI.

Finally we have the TypeNamePlural annotation in the HeaderInfo section which is where the text for the section title in the UI comes from.

00:28:50: Looking at the OData requests that are being made, and peering inside the $batch requests to see what's going on (OData v4 uses batching significantly). We also look at the Breezy service's metadata document and note that the annotation texts we just changed are in there which sort of explains why we have to redeploy on CDS (annotation) changes.

Talking of OData batch, we look briefly at the contructors for the UI5 OData model mechanisms, specifically sap.ui.model.odata.v2.ODataModel and sap.ui.model.odata.v4.ODataModel and noting that the constructor for v4 does not have a useBatch option in the parameters, suggesting that OData v4 is (as they say) "all batch, all the time".

00:35:05: Looking back at the code now to see what we need to do to internationalise the app, following a question in the previous episode from Fabien Beuret.

00:35:50: First, we remove the labels from the LineItem annotation section and add them to a new, separate section. This is a small example of how you can separate annotation work (and, more generally, CDS definitions) into sections that can be individually and independently maintained.

This is where we put the label information:
annotate northbreeze.Suppliers with {
ID @title: '{i18n>ID}';

Note even at this stage that the VS Code extension for CDS is giving us a warning on the {i18n>ID} part: "Text for translation ID 'ID' not defined CDS(no-translation-text/title)". Nice!

00:39:20: It's now time to resolve these warnings by creating an annotation file, but first we have a quick look in the SAP Help Portal at the relevant documentation on Localization, where we see how we can organise our internationalisation (i18n) properties files.

We take the option of specifying some configuration in the cds section of our package.json file like this:

"cds": {
"i18n": {
"folders": [

to specify that i18n properties files are to be found in a directory called languages.

00:44:10: In a new directory srv/languages/ we create a new file, the "default fallback" file, and start adding regular i18n properties and values.

00:46:16: In passing, we note how the CDS compiler inside the VS Code extension is working; it can read the new configuration in package.json that we've just added, find relevant translations for the annotations for ID, name and country and stop giving us warnings about the fact that none exist. Now they do, it looks good!

00:48:30: After a redeploy we refresh the app to see what's happened. We can see the texts in our new properties file are now in use.

00:49:28: We now test this out further by specifying a different language in the UI. We do this by using a query parameter on the app's URL to specify the German language is required. Doing this with a query parameter (sap-language) this is just one way of doing this, of course:


00:51:00: Even though we haven't yet added any specific German translations to our properties files, we do see some German already ("Suchen" in the search field) because of the fact that UI5 controls come already internationalised!

00:51:39: Adding a second i18n properties file,, with some German texts.

00:52:30: Note that the request for the metadata document of the OData service is also made with the German language request, which we can see in the Chrome Developer Tools - in the form of a request header:
Accept-Language: de

00:54:24: We note now, when the app is refreshed, the new German texts are being picked up!

00:55:50: Just for fun, we try a different language, this time a right-to-left one, in the form of Hebrew, where we see that UI5 allows the app to precisely adapt to the locale requirements of that language. Did I mention I think UI5 is awesome? 🙂