Working with Localized Data, Code Lists and Common Reuse Types

Objectives

After completing this lesson, you will be able to:
  • Serve localized versions of application data
  • Provide code lists
  • Use the common reuse types Country and Currency

Localized Data

In this lesson, we will look at how to provide translations for textual application data. For example, there may be a requirement to maintain the title of a book in different languages.

We will first look at how to declare localized data.

Declaring Localized Data

The localized modifier is used to declare localized data. Use it to identify the entity elements that require translated texts. In the following figure, the title element of the Books entity is marked accordingly:

Behind the Scenes

Based on the preceding definition, various things are automatically generated by the cds compiler. Amongst others, a separate Books.texts entity is generated to hold translated texts. This entity has the following structure:

Code Snippet
12345
entity Books.texts { key locale : sap.common.Locale; key ID : UUID; title : String(255); }

The Books.texts entity has the two key fields locale and ID.

The key field locale has the data type sap.common.Locale, which is a common reuse type from the aforementioned @sap/cds/common model. Ultimately, this type is used to define a string with a length of 14. The locale field is intended to store language codes such as en or de.

The second key field ID corresponds to the primary key of the Books entity.

With the Books.texts entity, a translated title for each language code (locale) can be saved for each book, i.e. each ID.

Besides the Books.texts entity, additional views are also created via the generated SQL DDL in order to read the localized texts.

Serving Localized Data

The generic handlers of the service runtimes automatically serve read requests in the user's preferred language with the help of the generated views. In our example, users automatically receive the book title in their preferred language or, if no translation is available for this language, in the fallback language. This is then the title as it is stored in the table belonging to the Books entity.

You can use the URL parameter sap-locale to test different languages. In the following example, German texts are requested:

Code Snippet
1
GET <your_service_url>/Books?sap-locale=de

Alternatively, you can also use requests with an appropriate Accept-Language header:

Code Snippet
12
GET <your_service_url>/Books Accept-Language: de

The URL parameter sap-locale has the highest preference. It overrides the Accept-Language header if this should also be set.

Let's now take a look at how localized data can initially be made available for the application.

Adding Initial Data

Watch the video to see how to add initial data.

In the following section, we will discuss the CodeList aspect and the Country and Currency types from the @sap/cds/common model.

Code Lists

The Purpose of Code Lists

Let us now discuss the concept of code lists provided by CAP. It offers a standardized way to provide translatable value lists.

Watch the video to get an overview of code lists.

Next, let's look at how to use code lists.

Aspect sap.common.CodeList

The sap.common.CodeList aspect provides the base definition for code lists in CAP. It belongs to the @sap/cds/common model. The namespace sap.common is set there via the context directive (see following figure). This directive is used for nested namespace sections within a definition.

The aspect sap.common.CodeList defines the two elements name and descr, which are marked with the previously discussed localized modifier. This makes it possible - as already explained - to provide translated texts for these fields.

Of the annotations used in the preceding definition, the annotation @cds.autoexpose is particularly important here: We will later implement our own code list called Epochs in the form of an entity, which we will extend with sap.common.CodeList. This means that our Epochs entity inherits @cds.autoexpose from sap.common.CodeList. As a result, our Epochs code list entity is automatically exposed in services that contain entities with associations to our Epochs entity. In our scenario, the Authors entity will define such an association to the Epochs entity. This means that without any further action on our part, the generated OData service will then expose an entity set for our Epochs entity.

Create Your Own Code Lists

To create your own code list, import the sap.common.CodeList aspect from the @sap/cds/common model via the using directive. In the example in the following figure, this is done via the ES6-like deconstructor variant of using.

In the example, the CodeList aspect is used as an include to extend the Epochs entity accordingly. The entity ultimately has the following structure:

Code Snippet
12345
entity Epochs { key ID : Integer; name : localized String(255); descr : localized String(1000); }

Note

You must use the fully qualified name sap.common.CodeList for the import. Afterwards, you use the imported aspect via the unqualified name CodeList.

We know from the discussion about the localized modifier that the cds compiler generates a separate Epochs.texts entity based on the preceding definition to hold translated texts. This entity has the following definition to be able to store a translation for name and description for each language code (locale) for each ID:

Code Snippet
123456
entity Epochs.texts { key locale : sap.common.Locale; key ID : Integer; name : String(255); descr : String(1000); }

Providing Initial Data

For code lists, you can provide initial data in the same way as described for the book titles. To do this, you first need a .csv file that contains all the data in the default language.

In our scenario, this is the file com.sap.learning-Epochs.csv. The entries in this file look as follows, whereby in the example only the name and no description is maintained in the default language English:

Translations into other languages that the application supports can then be created via a corresponding second .csv file. In the example, this is file com.sap.learning-Epochs.texts.csv, whose entries look as follows to provide German translations for the epoch names.

Using Code Lists

We use the Epochs code list in the Authors entity to assign an epoch to an author. To do this, we create a managed to-one association called epoch from the Authors entity to the Epochs entity as shown in the following figure:

We already know how this managed to-one association epoch is realized by CAP: Since the Epochs code list has the key field ID, a foreign key field called epoch_ID is created in the database table generated for the Authors entity:

Code Snippet
1234
CREATE TABLE com_sap_learning_Authors ( ... epoch_ID INTEGER );

This foreign key field is used to store the relationship between an author and the epoch to which it is assigned on the database.

Predefined Types Country and Currency

For countries, currencies and languages, CAP provides the predefined code lists sap.common.Countries, sap.common.Currencies and sap.common.Languages via the @sap/cds/common model.

In your own models, however, you will rarely refer directly to these code lists. Instead, you will use the reuse types Country, Currency and Language also contained in the @sap/cds/common model, which define corresponding associations to these code lists.

In the following sections, we will take a closer look at how to use the Country and Currency types. You can find more detailed information for languages in the CAP documentation.

Type Country

The common reuse type Country is defined in @sap/cds/common as a managed to-one association to the code list entity sap.common.Countries, as shown in the following figure:

The code list entity sap.common.Countries is intended for the use of ISO 3166-1 two-letter alpha codes as primary keys. This means that the corresponding key field code contains the value "DE" for Germany, for example.

Hint

As can be seen in the figure, the code element is defined as String(3) so that you can enter three-letter codes if required.

The preceding definition of the sap.common.Countries entity, in which sap.common.CodeList is used as an include, ultimately leads to an entity with the following structure by resolving the include:

Code Snippet
12345
entity sap.common.Countries { key code : String(3); name : localized String(255); descr : localized String(1000); }

The cds compiler in turn generates a separate sap.common.Countries.texts entity on this basis, as already discussed, to hold translated texts. This entity has the following definition to be able to store a translation for name and description for each language code (locale) for each country (code):

Code Snippet
123456
entity sap.common.Countries.texts { key locale : sap.common.Locale; key code : String(3); name : String(255); descr : String(1000); }

Type Currency

The common reuse type Currency is defined analogously to the type Country. It specifies a managed to-one association to the code list entity sap.common.Currencies:

The code list entity sap.common.Currencies is intended for use with ISO 4217 three-letter alpha codes as primary keys. This means that the corresponding key field code contains, for example, "USD" for US Dollar. In addition, this code list contains an element for the common currency symbols and one for the minor unit in the form of the number of decimal places.

The previous definition of the entity sap.common.Currencies, in which sap.common.CodeList is used as an include, ultimately leads to an entity with the following structure by resolving the include:

Code Snippet
1234567
entity sap.common.Currencies { key code : String(3); symbol : String(5); minorUnit : Int16; name : localized String(255); descr : localized String(1000); }

The cds compiler also creates a separate entity sap.common.Currencies.texts to hold translated texts. This entity has the following definition to be able to store a translation for name and description for each language code (locale) for each currency (code):

Code Snippet
123456
entity sap.common.Currencies.texts { key locale : sap.common.Locale; key code : String(3); name : String(255); descr : String(1000); }

Providing Initial Data

To provide initial data for the countries and currencies code lists, create the following .csv files in the db/data directory:

File NameContent
sap.common-Countries.csvList of countries in default language
sap.common-Countries.texts.csvTranslations for the list of countries
sap.common-Currencies.csvList of currencies in default language
sap.common-Currencies.texts.csvTranslations for the list of currencies

The following figure shows an example of the two files for the countries code list. For the sake of simplicity, the descr field is not maintained here. The file sap.common-Countries.texts.csv contains the German translations for the country names from sap.common-Countries.csv:

Accordingly, the following example shows the two files for the currencies code list. Only the code, name and symbol fields are maintained here. Translations of the currency names are not required, which is why the sap.common-Currencies.texts.csv file only contains the column titles and no translation entries:

Note

The package @sap/cds-common-content contains prebuilt data for the code lists sap.common.Countries, sap.common.Currencies and sap.common.Languages. The names and descriptions of the codes are translated into the most important languages supported by SAP. Read the package documentation to find out how you can integrate this package and its data into your application.

Using the Country and Currency Types

To be able to use the Country and Currency types described above, import them via the using directive, as shown in the following figure:

Assign the imported types to the corresponding elements in your definitions in order to ultimately define associations to the sap.common.Countries and sap.common.Currencies code lists.

In the example, the publCountry element of the Books entity has the data type Country and thus implements an association to the sap.common.Countries code list. Correspondingly, the currency component of the price element of the Books entity defines an association to the sap.common.Currencies code list.

Due to the assigned types, the elements publCountry and price_currency become navigation properties in the generated OData service.

Note

Remember that structured elements such as the price element of the Books entity are flattened with underscores. This means that the Books entity ultimately has a flat structure with two fields called price_amount and price_currency.

The navigation targets of publCountry and price_currency, i.e. the code list entities sap.common.Countries and sap.common.Currencies, are automatically exposed as entity sets in the OData service due to the @cds.autoexpose annotation in the base type sap.common.CodeList. We have already discussed this behavior above using the example of the epoch element of the Authors Entity. We implemented this navigation property as an association to our self-defined Epochs code list.

The associations to the code lists are realized in the database table generated for the Books entity via corresponding foreign key fields. Since the sap.common.Countries code list has the key field code, a foreign key field called publCountry_code is created in the database table generated for the Books entity. Accordingly, a foreign key field price_currency_code is created for the association to the sap.common.Currencies code list:

Code Snippet
12345
CREATE TABLE com_sap_learning_Books ( ... publCountry_code NVARCHAR(3), price_currency_code NVARCHAR(3) );

The foreign key fields are used to store the relationship between a book and the assigned country of publication as well as the assigned currency in the database.

Demonstration & Exercise: Work with Localized Data, Code Lists and Common Reuse Types

Note

As exercise, carry out the step-by-step instructions in the following demonstration yourself in the SAP Business Application Studio.

As a starting point for the exercise, use the outcome of the previous exercise Use Pre-Defined Aspects if you have successfully completed it. Alternatively, you can also use the branch 6_common_reuse_aspects from the following GitHub repository as a starting point:

https://github.com/SAP-samples/cap-development-learning-journey

The complete implementation of the simulation can be found in the 7_localized_data branch of the GitHub repository.

Detailed information on the content of the repository and how to use it can be found here.

Watch the video to see how to work with localized data, code lists and common reuse types.

Log in to track your progress & complete quizzes