Closed pubmikeb closed 4 years ago
Hi @pubmikeb,
this was indeed a problem for years. When we started UI5, our internal translation service provided an interface for the Java platform. Therefore, our ResourceBundle
implementation took over the specifics of that platform, including the *.properties
file format as well as the underscore in the language codes and, last but not least, the legacy ISO codes "in", "iw", "ji", "no" and "sh".
I'm sure this is documented somewhere, but I can't find it quickly (which obviously is a problem by itself).
Luckily, since 1.77, there's a solution for this and for other problems around localization. ResourceBundles
(or more precisely, ResourceModels
) that are declared in the manifest can now declare their set of supportedLocales
. If this set contains "he", the framework knows that Hebrew should be loaded from the "messagebundle_he.properties" file, whereas when the list contains "iw", the framework will request "messagebundle_iw.properties" when the current language is Hebrew (no matter whether it is configured as "he" or "iw").
This list of supported locales also finally helps to avoid the 404s for "en_US" etc. when those locales don't exist in the backend. And it allows to configure the locales per bundle, which is important for bigger, componentized apps.
In 1.77, only the runtime mechanisms is present and can be used via manifest.json or via API. For future versions of the ui5-tooling, it is planned to fill the corresponding manifest entries automatically, based on the existing resources of a project.
More has been done regarding ResourceBundles
and addtl. documentation will follow soon (hopefully).
HTH + Kind Regards
@codeworrior, thanks for the detailed explanation! Great, now I realize how really important the Supported Locales and Fallback feature is. The description in What's New in OpenUI5 1.77 seems to be more theoretical, rather than applied.
The What's New section also names the addtl. stuff that I shortly mentioned: terminologies. They are a way of preparing a single app for different domain languages, something that SAP has to scope with in its industry solutions.
As I said, documentation hopefully will follow soon ("soon" in the usual meaning of "I don't know exactly when; not now, but somewhen later").
@codeworrior, one more question regarding the supportedLocales
and fallbackLocale
features. I've tried to figure out how to use them, but it seems to not work out for me:
webapp/i18n
I have two files:
i18n_en.properties
i18n_he.properties
manifest.json
, into sap.app
and sap.ui
I've added the following code:
"_version": "1.21.0",
"sap.app": {
"applicationVersion": {
"version": "1.0.0"
},
"description": "{{appDescription}}",
"i18n": {
"bundleUrl": "i18n/i18n.properties",
"fallbackLocale": "he",
"supportedLocales": [
"en",
"he"
]
},
"id": "webapp",
"title": "{{appTitle}}",
"type": "application"
},
"fallbackLocale": "he"
, but the UI remains in English as well.Could you, please, point me how to make supportedLocales
/ fallbackLocale
working?
Thanks.
The bundle under "sap.app" / "i18n" is only used for the text placeholders within the manifest.json itself, not for the UI. For texts in the UI, you need to use a ResourceModel
under "sap.ui5" / "models".
See this sample manifest for details. You should ignore the terminologies
and enhanceWith
properties.
@codeworrior, thanks a lot.
supportedLocales
and fallbackLocale
inside of sap.ui5/models
:
"_version": "1.21.0",
"sap.ui5": {
"models": {
"i18n": {
"settings": {
"bundleName": "webapp.i18n.i18n",
"fallbackLocale": "he",
"supportedLocales": [
"en",
"he"
]
},
"type": "sap.ui.model.resource.ResourceModel"
}
}
}
work, but with some exception — if fallbackLocale
returns he
, the text direction remains ltr
instead of rtl
. If I explicitly require he
, then UI5 knows automatically apply rtl
.
How to apply rtl
in case the fallbackLocale
language requires it?
One more strange thing.
I've specified "fallbackLocale": "he"
, in Chrome I set German as a favorite language, then I run the app and get Hebrew (although with a wrong text direction), but when I check the network, I still see that the app requires i18n_de.properties
and downloads all available localisations:
i18n_en.properties
i18n_he.properties
I've assumed that supportedLocales
should eliminate the request of un-existing localization (i18n_de.properties
) and fallbackLocale
will ensure that in case the un-existing localization requested, the localization specified in fallbackLocale
will be provided instead, and not all available localisations.
I've also paid attention that "async": true
in "sap.ui5"/"models"/"i18n"/"settings"
leads to the problem, it doesn't allow to open a view, I get an error:
Uncaught TypeError: oBundle.getText is not a function
at f.onBeforeRendering (WantedView.controller.js:113)
at f.b.fireEvent (EventProvider-dbg.js:247)
at f.d.fireEvent (Element-dbg.js:559)
at f.fireBeforeRendering (ManagedObjectMetadata-dbg.js:781)
at f.onBeforeRendering (View-dbg.js:646)
at f.k.onBeforeRendering (XMLView-dbg.js:623)
at f.d._handleEvent (Element-dbg.js:287)
at Z (RenderManager-dbg.js:779)
at Object.R.renderControl (RenderManager-dbg.js:900)
at NavContainerRenderer-dbg.js:68
Once, I've removed "async": true
, everything is working OK, despite that in some samples "async": true
is used.
I've checked the documentation «Use Asynchronous Loading», there it's written:
To also load all application-specific configuration settings asynchronously, set the
async
property in the metadata of the manifest.json file to true:"sap.ui5": { "rootView": { "viewName": "sap.ui.demo.worklist.view.App", "type": "XML", "async": true, "id": "app" } }
@codeworrior, could you, please, provide some info, where exactly "async": true
is required to ensure that 100% of my UI5 app is loaded asynchronously?
Thanks.
Reg." fallbackLocale": "he" and RTL: the fallbackLocale is a configuration per resource bundle whereas the RTL flag is a global thing in UI5. If one bundle falls back to "he", there still might be others (like SAPUI5's own bundles) that can handle "de").
There's no logic that would check whether all bundles fall back to "he" and then derive RTL from that. Basically, the fallbackLocale is not meant to redirect the logon language. It is rather a last resort during development when translation is not complete yet and when the text in an otherwise supported language has not been provided yet.
If you need a kind of global fallback for the login language, you better should validate the logon languages and set sap-language accordingly.
Reg. the requests ("en" and "he", despite limiting the fallbackLocale to "he"): that's indeed strange and should not happen. Without the complete manifest.json, I can only guess that the request for "en" came from some other place, e.g. from the "sap.app" bundle?
Reg. "async": using async for bootstrap (data-sap-ui-async), for the rootView and for the router (if any) is definitely recommended. Whether resource bundles for views need special treatment, I can't say out-of-the-box. I'll check that.
There's no logic that would check whether all bundles fall back to "he" and then derive RTL from that.
Wow, I assumed, that there is a default rtl
/ltr
text direction property for any language, which is applied, unless is not explicitly overridden.
Reg. the requests ("en" and "he", despite limiting the fallbackLocale to "he"): that's indeed strange and should not happen. Without the complete manifest.json, I can only guess that the request for "en" came from some other place, e.g. from the "sap.app" bundle?
The entire manifest.json:
{
"_version": "1.21.0",
"sap.app": {
"applicationVersion": {
"version": "0.0.1"
},
"description": "{{appDescription}}",
"i18n": "i18n/i18n.properties",
"id": "webapp",
"title": "{{appTitle}}",
"type": "application"
},
"sap.ui": {
"deviceTypes": {
"desktop": true,
"phone": true,
"tablet": true
},
"technology": "UI5"
},
"sap.ui5": {
"contentDensities": {
"compact": true,
"cozy": true
},
"dependencies": {
"libs": {
"sap.m": {}
},
"minUI5Version": "1.77"
},
"models": {
"i18n": {
"settings": {
"bundleName": "webapp.i18n.i18n",
"fallbackLocale": "he",
"supportedLocales": [
"en",
"he"
]
},
"type": "sap.ui.model.resource.ResourceModel"
}
},
"resources": {
"css": [
{
"uri": "css/general.css"
}
]
},
"rootView": {
"async": true,
"id": "app",
"type": "XML",
"viewName": "webapp.view.App"
},
"routing": {
"config": {
"async": true,
"bypassed": {
"target": "notFound"
},
"controlAggregation": "pages",
"controlId": "app",
"routerClass": "sap.m.routing.Router",
"transition": "slide",
"viewPath": "webapp.view",
"viewType": "XML"
},
"routes": [],
"targets": {}
}
}
}
The language-related properties are:
sap.app
:
"i18n": "i18n/i18n.properties"
sap.ui5
/ "models"
/ "i18n"
/ "settings"
:
"bundleName": "webapp.i18n.i18n"
"fallbackLocale": "he"
"supportedLocales": ["en", "he"]
Here you may see what the app requires from the server. If "fallbackLocale": "he"
is applied, then the OpenUI5 app downloads all available in supportedLocales
localizations.
Perhaps, it's worth to note, here I'm talking about the OpenUI5 app, which doesn't have an SAP-backend.
Wow, I assumed, that there is a default rtl/ltr text direction property for any language, which is applied, unless is not explicitly overridden.
That's indeed the case, but for the sap-language (session language), not for each bundle that is loaded. And fallbackLocale even might be loaded in addition to, let's say, "de", just to get one of 99 text keys which hasn't been defined in the"de" file. It's a different concept of 'fallback' than what you imagined.
OpenUI5 app downloads all available in supportedLocales localizations.
The request for "en" occurs because "en" is the default fallback locale. Under "sap.app", you did not specify "he" as fallback, so "en" is requested (first request). The second request is for the model. If you use a different path under sap.app, e.g. "i18n/manifest.properties", you'll get the difference (not that you should do that in your app, just for illustrating the difference).
Wow, thanks for detailed info.
Under "sap.app", you did not specify "he" as fallback, so "en" is requested (first request).
Do I understand it correctly, that to avoid of loading of extra i18n-files, I have to specify both fallbackLocale
and supportedLocales
not only under sap.ui5
/ models
/ i18n
/ settings
, but under sap.app
as well?
To avoid extra-loading or 404s, configuring the supportedLocales
usually is enough. The fallbackLocale
only needs to be configured, if "en" (the default fallback locale) is not part of the supportedLocales
or if you think that a language other than "en" fits better to look for texts that might be missing in the other text files.
Within SAP, we create texts first in the file without locale (we call that the "raw" locale) and we create them as English text. Obviously, that file therefore would be a natural candidate for the fallbackLocale
. But after translation, "en" might be more appropriate for a native speaker and therefore we introduced another fallback "en" that is checked before the "raw" file. That's how fallbackLocale
came into life.
Without any configuration, we would search the following sequence of files for a text (assuming the session language is "pt_BR"):
pt_BR -> pt -> en -> raw locale
The search stops when a text is found.
fallbackLocale
you can pick another locale for the step before the raw locale supportedLocales
, you can limit the whole sequence to the specified set of locales.BTW: if you don't need a fallbackLocale
for missing text keys (because all properties files are complete or because text quality doesn't differ between locales), then you can also configure fallbackLocale="" and thereby skip the 3rd step above. Only makes a difference, if text files are not complete.
@codeworrior, thanks again for your time and passion to share the knowledge.
To avoid extra-loading or 404s, configuring the
supportedLocales
usually is enough.
So, I've specified:
"fallbackLocale": "en",
"supportedLocales": [
"en",
"he"
],
in both sap.app
and sap.ui5/models/i18n/settings
, but still observe 404, when a client has any language beyond the scope of supportedLocales
.
Besides that, I've paid attention that now I'm loading i18n_en.properties
twice:
which is not a case for https://openui5nightly.hana.ondemand.com/, for instance.
It looks like that in my case supportedLocales
is not enough to prevent 404 and also for some reason i18n_en.properties
appears twice in a logs.
Perhaps, it's worth to note, that as a backend I'm using Node.js 14 with Express.js.
From our conversation, I learn a lot about what needs to be documented :-)
Well, without knowing your app in full detail, all I can say is: the remaining 404s must be caused by bundles that are not configured in the manifest.json.
Do you use bundles that are configured in XML views? Or create some via API calls? The Initiator column in Chrome's network tab might reveal what code loads the bundle.
From our conversation, I learn a lot about what needs to be documented :-)
Indeed. Actually, the UI5 documentation is fairly good, the real problem is its verbosity, accompanied by a poor built-in search engine, which makes it quite difficult/time consuming to find something specific. Real-world example, try to find information regarding the accordance of _version
inside of the app manifest to the UI5 version with built-in search and with Google.
Do you use bundles that are configured in XML views?
No, as far as I know. At least the code of the XML-template for the initial login view is quite plain:
<core:View xmlns:core = "sap.ui.core"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns = "sap.m"
controllerName = "app.controller.Login"
xsi:schemaLocation = "sap.ui.core ">
<Page title = "{i18n>loginPageTitle}">
<content>
<Panel headerText = "{i18n>loginPageText}" expandable = "true" expanded = "true">
<content>
<Input id = "userID" value = "{/login}" placeholder = "Username" change = "onChanged" />
<Input type = "Password" id = "pwd" placeholder = "Password" change = "onChanged" />
<Button text = "Login" press = "btnClicked" />
</content>
</Panel>
</content>
</Page>
</core:View>
The Initiator column in Chrome's network tab might reveal what code loads the bundle.
I've checked the initiator value:
It looks like the missed file is required by sap-ui-core.js
via jQuery:
Perhaps, in addition to supportedLocales
there is some extra meta-parameter in manifest, which I forgot to specify to avoid requesting something, which is not mentioned in supportedLocales
?
@codeworrior, thanks for your support, I really appreciate and learn a lot from such a direct contact!
Hi @pubmikeb ,
the supportedLocales is the property for filtering and defines what are valid locales for properties files to be requested.
If supportedLocales is configured in your manifest for both: sap.app / i18n
and sap.ui5 / models / i18n / settings
there should be no request for locale en_US
The stacktrace is triggered by the manifest loading.
Hi @tobiasso85,
thanks for the link, it helped me a lot! The following solved my issue:
With manifest version 1.21.0 the
sap.app
i18n
section can hold an object containingbundleUrl
,supportedLocales
andfallbackLocale
.
The general problem with the UI5 documentation is that from one point of view it's so detailed, and from another it lacks some critical info and samples, or they a burred somewhere so deep, so you can find them only if you know exactly what you are looking for, e.g. explanation about manifest version and a table with UI5 library version vs. manifest version.
For instance, in the Supported Locales and Fallback article there is no mention regarding a new structure of i18n
section and no sample for sap.app
, there is only sample for sap.ui5
:
"i18n": {
"bundleUrl": "i18n/i18n.properties",
"supportedLocales": ["en", "de"],
"fallbackLocale": "en"
},
Ideally, it should explain what is an expected structure for i18n
in both sap.ui5
and sap.app
.
Besides that, there is no any information what's the difference between sap.ui5
and sap.app
in terms of i18n
configuration.
P.S. Please, consider reviewing the UI5 JSON schemas and updating them if needed (https://github.com/SAP/openui5/issues/2943).
Hi @pubmikeb , thanks a lot for reporting back that you were able to solve the issue. Your hints regarding the documentation will be considered in one of the following releases. With that I'll close the ticket. Best Regards, Florian
OpenUI5 version: 1.77.0
Steps to reproduce the problem:
chrome://settings/languages
) Hebrew as a priority # 1 in "Order languages based on your preference"i18n_he.properties
What is the expected result? UI5 will load
i18n_he.properties
What happens instead? UI5 looks for
i18n_iw.properties
, can't find it and tries to load the priority # 2.Any other information? (attach screenshot if possible)
If I rename the
i18n_he.properties
toi18n_iw.properties
everything is OK.In Identifying the Language Code / Locale it's written that UI5 supports:
If so, then why UI5 expects
iw
instead ofhe
for Hebrew?