Localization (i18n)
With ‘Localization’, we refer to adapting your app to the languages of specific target markets. This is particularly needed when serving UIs.
This guide focuses on static texts like labels. See CDS also Localized Data on how to manage and serve actual payload data in different translation.
Content
Externalizing Texts Bundles
All you have to do to internationalize your models is to externalize all your literal texts to text bundles and refer to the respective keys from your models as shown below.
service Bookshop {
entity Books @(
UI.HeaderInfo: {
Title.Label: '{i18n>Book}',
TypeName: '{i18n>Book}',
TypeNamePlural: '{i18n>Books}',
},
){/*...*/}
}
Book = Book
Books = Books
foo = Foo
Note: The keys of your properties entries can be freely chosen.
Then you can translate the texts in localized bundles each with a language/locale code appended to its name, for example,
_i18n/
i18n.properties # dev master -> 'default fallback'
i18n_en.properties # English -> 'default language'
i18n_de.properties # German
i18n_zh_TW.properties # Traditional Chinese
...
Where to Place Text Bundles?
By default, text bundles can be placed in and are fetched from folders named _i18n
, i18n
, or assets/i18n
. These folder are placed next to the model files or in a parent folder as follows:
srv/
my-service.cds # the model file
_i18n/i18n.properties # next to the model file
_i18n/i18n.properties # in a parent folder
You can configure the folder names where
cds
searches for property bundles by settingcds.i18n.folders
in your project’spackage.json
. The default is:"cds":{"i18n":{ "folders": [ "_i18n", "i18n", "/docs/03-Cookbook/51-Localization/assets/i18n" ] }}
CSV-Based Text Bundles
For smaller projects you may choose CSV files instead of .properties
files, which you can easily edit in Excel, Numbers or alike.
The format is like that:
key | en | de | zh_CN | … |
---|---|---|---|---|
Book | Book | Buch | … | |
Books | Books | Bücher | … | |
… |
With that CSV source:
key;en;de;zh_CN;...
Book;Book;Buch;...
Books;Books;Bücher;...
...
Merging Algorithm
Each localized model is constructed by applying:
- The default fallback bundle (that is,
i18n.properties
), then … - The default language bundle (usually
i18n_en.properties
), then … - The requested bundle (for example,
i18n_de.properties
), in that order.
So, the complete stack of overlaid models for the given example would look like that (higher ones override lower ones):
Source | Content |
---|---|
_i18n/i18n_de.properties |
specific language bundle |
_i18n/i18n_en.properties |
default language bundle |
_i18n/i18n.properties |
default fallback bundle |
srv/my-service.cds |
service definition |
db/data-model.cds |
underlying data model |
Note: The default language is usually
en
but can be overridden by configuringcds.i18n.default_language
in your project’spackage.json
.
Merging Reuse Bundles
In case your application is importing models from a reuse package, that package comes with own language bundles for localization. These are applied upon import, so can be overridden in your models as well as in your language bundles and translations thereof.
For example, assumed your data model imports from a foundation
package, then the overall stack of overlays would look like that:
Source |
---|
./_i18n/i18n_de.properties |
./_i18n/i18n_en.properties |
./_i18n/i18n.properties |
./srv/my-service.cds |
./db/data-model.cds |
foundation/_i18n/i18n_de.properties |
foundation/_i18n/i18n_en.properties |
foundation/_i18n/i18n.properties |
foundation/index.cds |
foundation/<private model a>.cds |
foundation/<private model b>.cds |
… |
Determining User Locales
Upon incoming requests at runtime, the user’s preferred language is determined as follows:
- Read the preferred language from first of:
- The value of URL parameter
sap-language
, if present - A chosen language from the user’s applications settings, if available
- A chosen language in the user’s global settings, if available
- The first entry from the request’s
Accept-Language
header - The default language configured on app level (for example,
en
)
- The value of URL parameter
- Narrow to normalized locales as described below.
Normalized locales
To reduce the number of required translations, determined locales are normalized as follows:
- most locales are narrowed to their main language codes only
- for example,
en_US
,en_CA
,en_AU
→en
- except of these white-listed ones:
Locale | Language |
---|---|
zh_CN | Chinese - China |
zh_HK | Chinese - Hong Kong, China |
zh_TW | Chinese traditional - Taiwan, China |
en_GB | English - English |
fr_CA | French - Canada |
pt_PT | Portuguese - Portugal |
es_CO | Spanish - Colombia |
es_MX | Spanish - Mexico |
en_US_x_saptrc | SAP tracing translations w/ sap-language=1Q |
en_US_x_sappsd | SAP pseudo translations w/ sap-language=2Q |
This white list is configurable, so if there’s a real need to change it, that is possible.