Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
WouterLemaire
SAP Mentor
SAP Mentor
1,280

Problem

We encountered unexpected behavior with the language selection in BTP Work Zone on mobile devices using the 'Dutch (Belgium)' language setting. The primary cause is that Work Zone does not officially support this language, leading to inconsistencies in how the interface is displayed. This issue is particularly noticeable on mobile devices, where the language fallback mechanism does not always work as expected. While it occasionally occurs on desktop browsers, it is less frequent and harder to reproduce. As a result, users with this language setting may experience partial translations or a fallback to English, creating a confusing user experience.

To better illustrate the issue, here is a screenshot showing the device language settings where 'Dutch (Belgium)' is selected:

WouterLemaire_2-1741364438864.png

 

In the following screenshot, you can see the unexpected behavior: although the launchpad is configured to use the device language, it incorrectly displays French. It is unclear why French is selected as the fallback instead of English.

WouterLemaire_3-1741364470254.png

Solution

As a solution for our applications, I implemented the following logic in each app used on mobile devices. This logic ensures consistent language handling by following these steps:

 

  • Retrieve the browser’s language.
  • Obtain the launchpad language using the UI5 SDK (via the older API, as we are using an older version of UI5).
  • By default, set the app’s language to the launchpad language.
  • Compare the launchpad language with the browser/device language.
  • If the languages differ, check the language from the launchpad personalization settings.
  • If a personalized language is available, use it. If it is empty, fall back to the device language.
  • Set the application language using only the first two characters to prevent conflicts caused by unsupported region-specific language codes.

 

This approach ensures the app respects user preferences while handling inconsistencies between the launchpad and device languages.

        setLanguage:function(){
            const browserLanguage = navigator.language || navigator.userLanguage;
            console.log(`Detected browser language: ${browserLanguage}`);
            const ui5Language = sap.ui.getCore().getConfiguration().getLanguage();
            console.log(`Detected UI5 language: ${ui5Language}`);
            let finalLanguage = ui5Language; //for now, we assume the ui5 language is correct untill proven wrong
            // if browserlanguage is different from ui5 language => language might have been changed in the launchpad or something is wrong with the launchpad languages
            if (browserLanguage.substr(0, 2) !== ui5Language.substr(0, 2)) {
                //get the selected language from the launchpad conifguration
                const urlParams = new URLSearchParams(window.location.search);
                //async doesn't work in the init function!!!
                // const launchpadSettingsResponse = await fetch(window.location.origin + "/cp.portal/portal/rest/v1/personalization?siteId="+urlParams.get('siteId'));
                // const launchpadSettings = await launchpadSettingsResponse.json();
                try {
                    const launchpadSettingsResponse = this.synchronousRequest(window.location.origin + "/cp.portal/portal/rest/v1/personalization?siteId=" + urlParams.get('siteId')+'&cacheBusterToken='+ Date.now());
                    console.log('Response data:', launchpadSettingsResponse);
                    const launchpadSettings = JSON.parse(launchpadSettingsResponse);
                    const launchpadLanguage = launchpadSettings?.persAdapter["sap.ushell.personalization#sap.cf.portal.site"]["ITEM#language"];
                    console.log(`Detected launchpad language: ${launchpadLanguage}`);
                    //if launchpad language is set, this is always correct, if not we have to use the language of the browser
                    //if all is good, the launchpad language should be the same as the UI5 language, if not something went wrong and launchpad language is the only correct value
                    //a check if launchpad and ui5 language are the same could be done but is only overhead, result would be the same as the next simple line:
                    finalLanguage = launchpadLanguage || browserLanguage;
                } catch (error) {
                    console.error('Error fetching or parsing launchpad settings:', error.message);
                }
            }
            console.log(`Final app language: ${finalLanguage}`);
            // if(browserLanguage.startsWith("fr-")) Localization.setLanguage("fr");
            // if(browserLanguage.startsWith("fr-")) sap.ui.getCore().getConfiguration().setLanguage("fr");
            //whatever the language is, we only use the two first charachters
            console.log(`Set app language: ${finalLanguage.substr(0, 2)}`);
            sap.ui.getCore().getConfiguration().setLanguage(finalLanguage.substr(0, 2));
        },

One important remark: we use a synchronous request to retrieve the personalization settings because the language must be set before the component initializes—otherwise, the app will not start properly.

 

While this solution works well for our applications, the language inconsistency still persists within the launchpad shell. To address this, I have raised a case with SAP and will keep you posted if an official solution becomes available!

 

Complete code in component.js to implement this fix:

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/Device",
    "zopsnotif/model/models",
    "zopsnotif/model/formatter",
    "zopsnotif/model/DataManager",
    "zopsnotif/controller/ListSelector"
], function (UIComponent, Device, models, formatter, DataManager, ListSelector) {
    "use strict";

    return UIComponent.extend("zopsnotif.Component", {

        metadata: {
            manifest: "json"
        },
        init: function () {
            this.setLanguage();

            UIComponent.prototype.init.apply(this, arguments);

            this.setModel(models.createDeviceModel(), "device");
            this.getRouter().initialize();
        },
        setLanguage:function(){
            const browserLanguage = navigator.language || navigator.userLanguage;
            console.log(`Detected browser language: ${browserLanguage}`);
            const ui5Language = sap.ui.getCore().getConfiguration().getLanguage();
            console.log(`Detected UI5 language: ${ui5Language}`);
            let finalLanguage = ui5Language; //for now, we assume the ui5 language is correct untill proven wrong
            // if browserlanguage is different from ui5 language => language might have been changed in the launchpad or something is wrong with the launchpad languages
            if (browserLanguage.substr(0, 2) !== ui5Language.substr(0, 2)) {
                //get the selected language from the launchpad conifguration
                const urlParams = new URLSearchParams(window.location.search);
                //async doesn't work in the init function!!!
                // const launchpadSettingsResponse = await fetch(window.location.origin + "/cp.portal/portal/rest/v1/personalization?siteId="+urlParams.get('siteId'));
                // const launchpadSettings = await launchpadSettingsResponse.json();
                try {
                    const launchpadSettingsResponse = this.synchronousRequest(window.location.origin + "/cp.portal/portal/rest/v1/personalization?siteId=" + urlParams.get('siteId')+'&cacheBusterToken='+ Date.now());
                    console.log('Response data:', launchpadSettingsResponse);
                    const launchpadSettings = JSON.parse(launchpadSettingsResponse);
                    const launchpadLanguage = launchpadSettings?.persAdapter["sap.ushell.personalization#sap.cf.portal.site"]["ITEM#language"];
                    console.log(`Detected launchpad language: ${launchpadLanguage}`);
                    //if launchpad language is set, this is always correct, if not we have to use the language of the browser
                    //if all is good, the launchpad language should be the same as the UI5 language, if not something went wrong and launchpad language is the only correct value
                    //a check if launchpad and ui5 language are the same could be done but is only overhead, result would be the same as the next simple line:
                    finalLanguage = launchpadLanguage || browserLanguage;
                } catch (error) {
                    console.error('Error fetching or parsing launchpad settings:', error.message);
                }
            }
            console.log(`Final app language: ${finalLanguage}`);
            // if(browserLanguage.startsWith("fr-")) Localization.setLanguage("fr");
            // if(browserLanguage.startsWith("fr-")) sap.ui.getCore().getConfiguration().setLanguage("fr");
            //whatever the language is, we only use the two first charachters
            console.log(`Set app language: ${finalLanguage.substr(0, 2)}`);
            sap.ui.getCore().getConfiguration().setLanguage(finalLanguage.substr(0, 2));
        },
        synchronousRequest: function (url) {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', url, false);
            xhr.send(null);
            if (xhr.status === 200) {
                return xhr.responseText;
            } else {
                throw new Error('Request failed: ' + xhr.statusText);
            }
        }     
    });
});
2 Comments