Technical Articles
UI5ers Buzz #54: I18n with supportedLocales and fallbackLocale configuration
Internationalization with supportedLocales and fallbackLocale configuration
In this blog post you will learn how to configure the supportedLocales
and the fallbackLocale
in your app’s manifest
to avoid ‘404 Not Found’ network responses and control the resource bundles.
Note:
Please note that the available properties files for a resource bundle and the specified locales in supportedLocales
need to be in sync. Missing properties files result in 404 responses by the server.
But more severely, a missing entry in supportedLocales leads to a language fallback, even though the texts for the
corresponding language are actually available.Only use the supportedLocales feature if you are also in control of adding and deleting properties files
for resource bundles. For instance, if you use translation tools which control the lifecycle of properties files
but are not able to update supportedLocales, you cannot make use of the supportedLocales feature yet.
404s, missing translations and other curiosities
When developing apps and working with resource bundles for internationalization (i18n),
you might have run into the following problems:
- ‘404 Not Found’ responses in the network trace,
for example for a request tomyapp/i18n_de_DE.properties
when the client’s locale is"de_DE"
,
although there is no translation file for this locale. - Resource bundle requests for language “en”,
such as for e.g.myapp/i18n_en.properties
, although the client’s locale is not set to English.
These issues occur more often when a translated text cannot be found in the resource bundle.
The resource bundle then tries to load all potential locale-specific translation files using synchronous requests.
These requests are executed one after the other.
This means that if a particular translation file cannot be found, it causes a delay until the next one is requested.
This not only looks bad when checking the network trace but also comes at a price:
bad performance and unwanted traffic.
But don’t worry! Since UI5 version 1.77 it can be avoided/fixed by
providing the supportedLocales
and fallbackLocale
configuration in your app’s manifest
.
Control over translation or “How to make coffee”
Since UI5 1.77 you can configure the supported locales and the fallback locale for resource bundles.
This enables the client to know in advance which language bundles to request.
You can think of the mechanism for loading a resource bundle and its translation files as a kind of coffee-making process.
Step one: Selection
The bean and the roast
Coffee cherries are picked by hand. The flesh is separated from the bean, and the beans are washed with water.
The defective beans are sorted out, and the high-quality beans are collected.
Afterwards, the beans are roasted and develop their unique flavour.
Fallback Chain
Just like the hand-picking of the cherries is the process for finding locale candidates using a fallback chain.
The fallback chain is a mechanism to determine the locale-specific resource bundle file to load.
A locale can either be a BCP47 language tag or a JDK compatible locale string (e.g. “en-GB”, “en_GB” or “en”).
The fallback chain mechanism is used when loading the resource bundle initially, or when the translation key cannot be found in the already loaded resource bundle.
Part of this fallback chain is the configured fallbackLocale
, which defaults to “en”.
The fallback chain produces locale candidates using the following directives:
- determine the input language, e.g “de_DE”
- remove the region suffix from the locale, e.g. “de_DE” -> “de”
- use the
fallbackLocale
configured, e.g. “en” (defaults to “en”) - use the raw bundle, i.e. “”
Each directive produces a locale candidate, which is then used to create a request.
E.g. “de_DE” is used to create a request for “i18n/i18n_de_DE.properties”.
The directives are executed in order until a resource bundle is loaded (successful request).
The raw bundle “” means that no locale is appended to the requested file. For example, it may be called “i18n/i18n.properties”.
Sample:
input locale: "de_DE"
fallbackLocale: "en"
fallback chain: "de_DE" -> "de" -> "en" -> ""
Step two: Filtering
The brew
The roasted beans are ground before brewing.
There are several ways to brew coffee, but all of them use the same principle:
- The ground coffee is mixed with hot water.
- The liquid is separated from the used grounds after a specific time.
Supported Locales
Just like the separation of ground and liquid is the filtering of the locale candidates using the supportedLocales.
Only the ones which are in the list of supportedLocales remain.
This way, only resource bundles for configured locales are requested.
input locale: "de_DE"
fallbackLocale: "en"
fallback chain: "de_DE" -> "de" -> "en" -> ""
supportedLocales: ["de", "fr", "en"]
For the given fallback chain only bundle files for "de" and "en" are requested at most, because the list of supportedLocales contains them.
"fr" is not part of the fallback chain so although supported it won't be requested.
Note: If the requested text can be found in "de", "en" will not be requested.
Step three: Result
Fresh coffee
Enjoy your fine cup of coffee!
Clean network trace
The locale for the request is determined, and the translation can be loaded.
The text is presented in the requested locale, and there should be a clean network trace.
BAZINGA!
Sample
File system:
i18n/i18n_en.properties
English translationi18n/i18n_de.properties
German translation
Excerpt from manifest.json
{
"_version": "1.21.0",
"sap.app": {
"id": "sap.ui.demo.todo",
"type": "application",
"i18n": {
"bundleUrl": "i18n/i18n.properties",
"supportedLocales": ["en", "de"],
"fallbackLocale": "en"
},
"title": "{{appTitle}}"
},
"sap.ui5": {
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleUrl": "i18n/i18n.properties",
"supportedLocales": ["en", "de"],
"fallbackLocale": "en"
}
}
}
}
}
Note:
With Manifest version
1.21.0
thesap.app
i18n
section can hold an object containingbundleUrl
,supportedLocales
andfallbackLocale
.
This is similar to theResourceModel
configuration.
What is loaded with this configuration:
de_DE
will loadi18n_de.properties
en_US
will loadi18n_en.properties
fr_FR
will loadi18n_en.properties
Demo: Before and After
The left-hand side (“Before”) shows the old configuration
without supportedLocales
and without fallbackLocale
configuration.
The browser’s locale is “en_US”, and no supportedLocales
configuration means that all locales are supported.
Therefore, this leads to a request for i18n_en_US.properties
, which results in a 404 Not Found
response.
The next locale candidate according to the fallback chain is “en”.
The corresponding request for i18n_en.properties
succeeds.
The right-hand side (“After”) shows the new configuration
with supportedLocales
and with a fallbackLocale
configuration.
The browser’s locale is “en_US”, but this locale is not part of the supportedLocales.
The next locale candidate in the fallback chain is “en”.
It is part of the supportedLocales
, and the request succeeds.
Bingo!
There is only one request in the network trace, the one for i18n_en.properties
.
Moving forward
After using this information and adjusting your manifests, there is no more “back to normal”.
But there is a “back to controlled normal” with new configuration possibilities for your i18n files.
Everything is then under control to provide the best experience and get the most out of your app.
Lessons learned
- How to configure the app’s manifest regarding i18n
- How to make coffee
Further Reading
Previous Post: UI5ers Buzz #53: Terminologies in UI5
Author
![]() If you liked it, tell your friends about it – if not, tell me ๐ |
Great work! Just made the change in my current app, it certainly clears up some of the network errors!
It's a little weird typing
bundleUrl: "i18n/i18n.properties"
but that file doesn't exist - it loads the filei18n/i18n_en.properties
. I guess it is no weirder than typingbundleName: "sap.ui.demo.todo.i18n.i18n"
!Nevermind - the default I was looking for was
So that it loads the default i18n without trying any other locales first. This is useful for developing and removes the 404s ๐
Cool, that it worked out ๐
The raw locale "" is not explicitly mentioned here to avoid confusion.
But your solution is perfect:
The supportedLocales should always match the i18n file suffixes in the filesystem
E.g.
would result in supportedLocales: ["", "de"]
The fallbackLocale should be explicitly defined and it should be one of the supportedLocales.
Sounds like an important feature,
but I'm a little confused right now:
I have done a small test (before adding the new supportedLocales, fallbackLocale attributes) of the system behaviour in case of not supported language and I couldn't reproduce the described scenario:
I don't see in the network trace any call to i18n resource with 404 response.
Moreover, it seems that the contents of the response are returned implicitly according to the described fallback chain ("de_DE" -> "de" -> "en"), while the default language is en.
i.e. When I enter system language en_GB, I get a response with the contents of the i18n_en file and not a 404 error.
How exactly does it work?
It might depend on the server,
some serverโs are configured to always answer the request for a pattern (e.g. ending with .properties) although the actual file does not exist.
E.g.
https://sapui5.hana.ondemand.com/test-resources/sap/suite/ui/commons/demokit/icecream/webapp/i18n/i18n_XX.properties
This might be the reason why there is no 404 response from the server.
Thanks.
I'm using an ABAP repository.
Where can I find this configuration? Is it applicable for all ABAP repositories (on any NW version)?
Hi Tobias
Very nice blog! So in 1.71 there is no alternative to this solution?
Thanks in advance.
Matthijs
Hi Matthijs,
if you just support one language you could use the data-sap-ui-language parameter in the script tag which loads sap-ui-core.js.
For multiple languages you could either replicate the language files, e.g. having "i18n_en.properties" and "i18n_en_US.properties" as a copy. Or let the server just respond to any "unknown" i18n_*.properties request with the default one to avoid the 404 requests.
Regards
Tobias