Skip to content

Commit 9984cfe

Browse files
Merge pull request #338 from cap-java/translationissue
Translation of all the service exception messages
2 parents 256741b + 077223f commit 9984cfe

16 files changed

+1348
-102
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
2020
- Copy attachments: Provides the capability to copy attachments from one entity to another entity.
2121
- Link as attachments: Provides the capability to support link or URL as attachments.
2222
- Edit Link-type attachments: Provides the capability to update URL of link-type attachments.
23-
23+
- Localization of error messages and UI fields: Provides the capability to have the UI fields and error messages translated to the local language of the leading application.
2424
## Table of Contents
2525

2626
- [Pre-Requisites](#pre-requisites)
@@ -35,6 +35,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
3535
- [Support for Copy attachments](#support-for-copy-attachments)
3636
- [Support for Link type attachments](#support-for-link-type-attachments)
3737
- [Support for Edit of Link type attachments](#support-for-edit-of-link-type-attachments)
38+
- [Support for Localization](#support-for-localization)
3839
- [Known Restrictions](#known-restrictions)
3940
- [Support, Feedback, Contributing](#support-feedback-contributing)
4041
- [Code of Conduct](#code-of-conduct)
@@ -859,7 +860,26 @@ annotate Attachments with @Common: {SideEffects #ContentChanged: {
859860
- Replace `AdminService` in `Action: 'AdminService.editLink'` with the name of your service.
860861
- Repeat for other entities and elements if you have defined multiple `composition of many Attachments`.
861862

863+
## Support for Localization
864+
If the UI fields have to be available in the local language of the leading application ensure to add the below fields in the i18n_[languagecode].properties file under app/_i18n folder.
865+
Default language translations are present in i18n.properties files. If leading application does not provide any keys and values in their language properties files then default english language messages are shown to the user.
866+
867+
Example i18n_de.properties for german language.
868+
```
869+
Attachment=Attachment
870+
Attachments=Attachments
871+
Note= Attachment Note
872+
Filename=File Name
873+
linkUrl=Link Url
874+
type=Type
875+
```
876+
For the exception messages as well the translation can be done by adding the translation to messages_[languagecode].properties files present under srv/src/main/resources.
877+
Default language translations are present in messages.properties. If leading application does not provide any keys and values in their language properties files then default english language messages are shown to the user.
862878

879+
Example for german language
880+
```
881+
SDM.Attachments.maxCountError = Maximum number of attachments reached in German......
882+
```
863883
## Known Restrictions
864884

865885
- UI5 Version 1.135.0: This version causes error in upload of attachments.

sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ private SDMConstants() {
2929
"Upload not supported for versioned repositories.";
3030
public static final String VIRUS_REPO_ERROR_MORE_THAN_400MB =
3131
"You cannot upload files that are larger than 400 MB";
32+
public static final String VIRUS_REPO_ERROR_MORE_THAN_400MB_MESSAGE = "SDM.VirusRepoErrorMessage";
3233
public static final String VIRUS_ERROR = "%s contains potential malware and cannot be uploaded.";
34+
public static final String VIRUS_ERROR_MESSAGE = "SDM.VirusErrorMessage";
35+
public static final String SDM_DUPLICATE_ATTACHMENT = "SDM.DuplicateAttachment";
3336
public static final String REPOSITORY_ERROR = "Failed to get repository info.";
34-
public static final String NOT_FOUND_ERROR = "Failed to read document.";
35-
public static final String NAME_CONSTRAINT_WARNING_MESSAGE =
36-
"Enter a valid file name for %s. The following characters are not supported: /, \\";
3737
public static final String SDM_MISSING_ROLES_EXCEPTION_MSG =
3838
"You do not have the required permissions to update attachments. Kindly contact the admin";
3939
public static final String SDM_ROLES_ERROR_MESSAGE =
@@ -67,6 +67,18 @@ private SDMConstants() {
6767
public static final String ATTACHMENT_MAXCOUNT_ERROR_MSG = "SDM.Attachments.maxCountError";
6868
public static final String MAX_COUNT_ERROR_MESSAGE =
6969
"Cannot upload more than %s attachments as set up by the application";
70+
71+
// Localized error message keys
72+
public static final String VERSIONED_REPO_ERROR_MSG = "SDM.Repository.versionedRepoError";
73+
public static final String USER_NOT_AUTHORISED_ERROR_MSG =
74+
"SDM.Authorization.userNotAuthorizedError";
75+
public static final String USER_NOT_AUTHORISED_ERROR_LINK_MSG =
76+
"SDM.Authorization.userNotAuthorizedLinkError";
77+
public static final String FAILED_TO_EDIT_LINK_MSG = "SDM.Link.failedToEditLinkError";
78+
public static final String REPOSITORY_ERROR_MSG = "SDM.Repository.repositoryError";
79+
public static final String FILE_NOT_FOUND_ERROR_MSG = "SDM.File.fileNotFoundError";
80+
public static final String MIMETYPE_INVALID_ERROR_MSG = "SDM.File.mimetypeInvalidError";
81+
public static final String FAILED_TO_FETCH_FACET_MSG = "SDM.Facet.failedToFetchFacetError";
7082
public static final String NO_SDM_BINDING = "No SDM binding found";
7183
public static final String DI_TOKEN_EXCHANGE_ERROR = "Error fetching DI token with JWT bearer";
7284
public static final String DI_TOKEN_EXCHANGE_PARAMS =
@@ -96,6 +108,39 @@ private SDMConstants() {
96108
public static final String FETCH_ATTACHMENT_COMPOSITION_ERROR =
97109
"Failed to fetch attachment composition";
98110

111+
// Error messages for ServiceException
112+
public static final String FAILED_TO_EDIT_LINK = "Failed to edit link";
113+
public static final String ERROR_IN_SETTING_TIMEOUT = "Error in setting timeout";
114+
public static final String SDM_CREDENTIALS_MISSING_OR_INVALID =
115+
"SDM credentials are missing or invalid.";
116+
public static final String FAILED_TO_RETRIEVE_SDM_CREDENTIALS =
117+
"Failed to retrieve SDM credentials.";
118+
public static final String FAILED_TO_CREATE_HTTP_CLIENT = "Failed to create HTTP client.";
119+
public static final String ERROR_WHILE_CREATING_HTTP_CLIENT = "Error while creating HTTP client.";
120+
public static final String FAILED_TO_SET_REPOSITORY_DETAILS = "Failed to set repository details.";
121+
public static final String FAILED_TO_SERIALIZE_REPOSITORY_OBJECT_TO_JSON =
122+
"Failed to serialize repository object to JSON.";
123+
public static final String FAILED_TO_CREATE_STRING_ENTITY = "Failed to create StringEntity.";
124+
public static final String CLIENT_CREDENTIALS_MISSING_OR_INVALID =
125+
"Client credentials are missing or invalid.";
126+
public static final String FAILED_TO_CREATE_CLIENT_CREDENTIALS =
127+
"Failed to create client credentials.";
128+
public static final String FAILED_TO_REPLACE_SUBDOMAIN_IN_BASE_TOKEN_URL =
129+
"Failed to replace subdomain in base token URL.";
130+
public static final String ERROR_WHILE_FETCHING_REPOSITORY_ID =
131+
"Error while fetching repository ID.";
132+
public static final String UNEXPECTED_ERROR_WHILE_FETCHING_REPOSITORY_ID =
133+
"Unexpected error while fetching repository ID.";
134+
public static final String FAILED_TO_OFFBOARD_REPOSITORY = "Failed to offboard repository.";
135+
public static final String ERROR_WHILE_OFFBOARDING_REPOSITORY =
136+
"Error while offboarding repository.";
137+
public static final String UNEXPECTED_ERROR_WHILE_OFFBOARDING_REPOSITORY =
138+
"Unexpected error while offboarding repository.";
139+
public static final String FAILED_TO_PARSE_REPOSITORY_RESPONSE =
140+
"Failed to parse repository response";
141+
public static final String ERROR_IN_SETTING_TIMEOUT_MESSAGE = "Error in setting timeout";
142+
public static final String FAILED_TO_CREATE_FOLDER = "Failed to create folder";
143+
99144
public static String nameConstraintMessage(
100145
List<String> fileNameWithRestrictedCharacters, String operation) {
101146
// Create the base message

sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMCreateAttachmentsHandler.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.sap.cds.sdm.handler.applicationservice;
22

33
import com.sap.cds.CdsData;
4-
import com.sap.cds.reflect.CdsAssociationType;
5-
import com.sap.cds.reflect.CdsElement;
64
import com.sap.cds.reflect.CdsEntity;
75
import com.sap.cds.sdm.caching.CacheConfig;
86
import com.sap.cds.sdm.caching.SecondaryPropertiesKey;
@@ -383,22 +381,4 @@ private void handleWarnings(
383381
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "create"));
384382
}
385383
}
386-
387-
private List<String> getEntityCompositions(CdsCreateEventContext context) {
388-
List<CdsElement> compositions = context.getTarget().compositions().toList();
389-
List<String> attachmentsCompositionList = new ArrayList<>();
390-
for (CdsElement cdsElement : compositions) {
391-
if (cdsElement != null) {
392-
CdsAssociationType cdsAssociationType = cdsElement.getType();
393-
String targetAspect =
394-
cdsAssociationType.getTargetAspect().isPresent()
395-
? cdsAssociationType.getTargetAspect().get().getQualifiedName()
396-
: null;
397-
if (targetAspect != null && targetAspect.equalsIgnoreCase("sap.attachments.Attachments")) {
398-
attachmentsCompositionList.add(cdsElement.getName());
399-
}
400-
}
401-
}
402-
return attachmentsCompositionList;
403-
}
404384
}

sdm/src/main/java/com/sap/cds/sdm/handler/applicationservice/SDMUpdateAttachmentsHandler.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.sap.cds.sdm.handler.applicationservice;
22

33
import com.sap.cds.CdsData;
4-
import com.sap.cds.reflect.CdsAssociationType;
5-
import com.sap.cds.reflect.CdsElement;
64
import com.sap.cds.reflect.CdsEntity;
75
import com.sap.cds.sdm.caching.CacheConfig;
86
import com.sap.cds.sdm.caching.SecondaryPropertiesKey;
@@ -378,22 +376,4 @@ private void handleWarnings(
378376
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "update"));
379377
}
380378
}
381-
382-
private List<String> getEntityCompositions(CdsUpdateEventContext context) {
383-
List<CdsElement> compositions = context.getTarget().compositions().toList();
384-
List<String> attachmentsCompositionList = new ArrayList<>();
385-
for (CdsElement cdsElement : compositions) {
386-
if (cdsElement != null) {
387-
CdsAssociationType cdsAssociationType = cdsElement.getType();
388-
String targetAspect =
389-
cdsAssociationType.getTargetAspect().isPresent()
390-
? cdsAssociationType.getTargetAspect().get().getQualifiedName()
391-
: null;
392-
if (targetAspect != null && targetAspect.equalsIgnoreCase("sap.attachments.Attachments")) {
393-
attachmentsCompositionList.add(cdsElement.getName());
394-
}
395-
}
396-
}
397-
return attachmentsCompositionList;
398-
}
399379
}

sdm/src/main/java/com/sap/cds/sdm/service/DocumentUploadService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ private void executeHttpPost(
8383
try (CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(uploadFile)) {
8484
formResponse(cmisDocument, finalResponse, response);
8585
} catch (IOException e) {
86-
throw new ServiceException("Error in setting timeout", e);
86+
throw new ServiceException(SDMConstants.ERROR_IN_SETTING_TIMEOUT, e);
8787
}
8888
}
8989

sdm/src/main/java/com/sap/cds/sdm/service/SDMAdminServiceImpl.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ public String onboardRepository(Repository repository)
4747
sdmCredentials = tokenHandler.getSDMCredentials();
4848
if (sdmCredentials == null || sdmCredentials.getUrl() == null) {
4949
logger.error("SDM credentials are missing or invalid.");
50-
throw new ServiceException("SDM credentials are missing or invalid.");
50+
throw new ServiceException(SDMConstants.SDM_CREDENTIALS_MISSING_OR_INVALID);
5151
}
5252
} catch (Exception e) {
5353
logger.error("Failed to retrieve SDM credentials: " + e.getMessage());
54-
throw new ServiceException("Failed to retrieve SDM credentials.", e);
54+
throw new ServiceException(SDMConstants.FAILED_TO_RETRIEVE_SDM_CREDENTIALS, e);
5555
}
5656

5757
HttpClient httpClient = null;
@@ -61,11 +61,11 @@ public String onboardRepository(Repository repository)
6161
null, null, repository.getSubdomain(), "TECHNICAL_CREDENTIALS_FLOW");
6262
if (httpClient == null) {
6363
logger.error("Failed to create HTTP client.");
64-
throw new ServiceException("Failed to create HTTP client.");
64+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_HTTP_CLIENT);
6565
}
6666
} catch (Exception e) {
6767
logger.error("Error while creating HTTP client: " + e.getMessage());
68-
throw new ServiceException("Error while creating HTTP client.", e);
68+
throw new ServiceException(SDMConstants.ERROR_WHILE_CREATING_HTTP_CLIENT, e);
6969
}
7070

7171
String sdmUrl = sdmCredentials.getUrl() + SDMConstants.REST_V2_REPOSITORIES;
@@ -78,23 +78,23 @@ public String onboardRepository(Repository repository)
7878
onboardRepository.setRepository(repository);
7979
} catch (Exception e) {
8080
logger.error("Failed to set repository details: " + e.getMessage());
81-
throw new ServiceException("Failed to set repository details.", e);
81+
throw new ServiceException(SDMConstants.FAILED_TO_SET_REPOSITORY_DETAILS, e);
8282
}
8383

8484
String json;
8585
try {
8686
json = objectMapper.writeValueAsString(onboardRepository);
8787
} catch (JsonProcessingException e) {
8888
logger.error("Failed to serialize repository object to JSON: " + e.getMessage());
89-
throw new ServiceException("Failed to serialize repository object to JSON.", e);
89+
throw new ServiceException(SDMConstants.FAILED_TO_SERIALIZE_REPOSITORY_OBJECT_TO_JSON, e);
9090
}
9191

9292
StringEntity entity;
9393
try {
9494
entity = new StringEntity(json);
9595
} catch (UnsupportedEncodingException e) {
9696
logger.error("Failed to create StringEntity: " + e.getMessage());
97-
throw new ServiceException("Failed to create StringEntity.", e);
97+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_STRING_ENTITY, e);
9898
}
9999

100100
onboardingReq.setEntity(entity);
@@ -146,11 +146,11 @@ public String offboardRepository(String subdomain) {
146146
|| sdmCredentials.getUrl() == null
147147
|| sdmCredentials.getBaseTokenUrl() == null) {
148148
logger.error("SDM credentials are missing or invalid.");
149-
throw new ServiceException("SDM credentials are missing or invalid.");
149+
throw new ServiceException(SDMConstants.SDM_CREDENTIALS_MISSING_OR_INVALID);
150150
}
151151
} catch (Exception e) {
152152
logger.error("Failed to retrieve SDM credentials: " + e.getMessage());
153-
throw new ServiceException("Failed to retrieve SDM credentials.", e);
153+
throw new ServiceException(SDMConstants.FAILED_TO_RETRIEVE_SDM_CREDENTIALS, e);
154154
}
155155

156156
ClientCredentials clientCredentials;
@@ -159,11 +159,11 @@ public String offboardRepository(String subdomain) {
159159
new ClientCredentials(sdmCredentials.getClientId(), sdmCredentials.getClientSecret());
160160
if (clientCredentials.getId() == null || clientCredentials.getSecret() == null) {
161161
logger.error("Client credentials are missing or invalid.");
162-
throw new ServiceException("Client credentials are missing or invalid.");
162+
throw new ServiceException(SDMConstants.CLIENT_CREDENTIALS_MISSING_OR_INVALID);
163163
}
164164
} catch (Exception e) {
165165
logger.error("Failed to create client credentials: " + e.getMessage());
166-
throw new ServiceException("Failed to create client credentials.", e);
166+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_CLIENT_CREDENTIALS, e);
167167
}
168168

169169
String baseTokenUrl = sdmCredentials.getBaseTokenUrl();
@@ -174,7 +174,7 @@ public String offboardRepository(String subdomain) {
174174
baseTokenUrl = baseTokenUrl.replace(providersubdomain, subdomain);
175175
} catch (Exception e) {
176176
logger.error("Failed to replace subdomain in base token URL: " + e.getMessage());
177-
throw new ServiceException("Failed to replace subdomain in base token URL.", e);
177+
throw new ServiceException(SDMConstants.FAILED_TO_REPLACE_SUBDOMAIN_IN_BASE_TOKEN_URL, e);
178178
}
179179
}
180180

@@ -196,11 +196,11 @@ public String offboardRepository(String subdomain) {
196196
httpClient = factory.createHttpClient(destination);
197197
if (httpClient == null) {
198198
logger.error("Failed to create HTTP client.");
199-
throw new ServiceException("Failed to create HTTP client.");
199+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_HTTP_CLIENT);
200200
}
201201
} catch (Exception e) {
202202
logger.error("Error while creating HTTP client: " + e.getMessage());
203-
throw new ServiceException("Error while creating HTTP client.", e);
203+
throw new ServiceException(SDMConstants.ERROR_WHILE_CREATING_HTTP_CLIENT, e);
204204
}
205205

206206
String sdmUrl = sdmCredentials.getUrl() + SDMConstants.REST_V2_REPOSITORIES + "/";
@@ -215,10 +215,10 @@ public String offboardRepository(String subdomain) {
215215
}
216216
} catch (IOException e) {
217217
logger.error("Error while fetching repository ID: " + e.getMessage());
218-
throw new ServiceException("Error while fetching repository ID.", e);
218+
throw new ServiceException(SDMConstants.ERROR_WHILE_FETCHING_REPOSITORY_ID, e);
219219
} catch (Exception e) {
220220
logger.error("Unexpected error while fetching repository ID: " + e.getMessage());
221-
throw new ServiceException("Unexpected error while fetching repository ID.", e);
221+
throw new ServiceException(SDMConstants.UNEXPECTED_ERROR_WHILE_FETCHING_REPOSITORY_ID, e);
222222
}
223223

224224
sdmUrl = sdmCredentials.getUrl() + SDMConstants.REST_V2_REPOSITORIES + "/" + repoId;
@@ -234,17 +234,17 @@ public String offboardRepository(String subdomain) {
234234
return "Repository with ID " + SDMConstants.REPOSITORY_ID + " not found.";
235235
}
236236
logger.error("Failed to offboard repository : " + responseString);
237-
throw new ServiceException("Failed to offboard repository.", responseString);
237+
throw new ServiceException(SDMConstants.FAILED_TO_OFFBOARD_REPOSITORY, responseString);
238238
}
239239

240240
logger.info("Repository " + repoId + " Offboarded");
241241
return "Repository " + repoId + " Offboarded";
242242
} catch (IOException e) {
243243
logger.error("Error while offboarding repository: " + e.getMessage());
244-
throw new ServiceException("Error while offboarding repository.", e);
244+
throw new ServiceException(SDMConstants.ERROR_WHILE_OFFBOARDING_REPOSITORY, e);
245245
} catch (Exception e) {
246246
logger.error("Unexpected error while offboarding repository: " + e.getMessage());
247-
throw new ServiceException("Unexpected error while offboarding repository.", e);
247+
throw new ServiceException(SDMConstants.UNEXPECTED_ERROR_WHILE_OFFBOARDING_REPOSITORY, e);
248248
}
249249
}
250250

@@ -268,7 +268,7 @@ private String getRepositoryId(String jsonString) {
268268
}
269269
}
270270
} catch (Exception e) {
271-
throw new ServiceException("Failed to parse repository response", e);
271+
throw new ServiceException(SDMConstants.FAILED_TO_PARSE_REPOSITORY_RESPONSE, e);
272272
}
273273
return null;
274274
}

sdm/src/main/java/com/sap/cds/sdm/service/SDMServiceImpl.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private void executeHttpPost(
127127
try (var response = (CloseableHttpResponse) httpClient.execute(uploadFile)) {
128128
formResponse(cmisDocument, finalResponse, response);
129129
} catch (IOException e) {
130-
throw new ServiceException("Error in setting timeout", e.getMessage());
130+
throw new ServiceException(SDMConstants.ERROR_IN_SETTING_TIMEOUT_MESSAGE, e.getMessage());
131131
}
132132
}
133133

@@ -356,7 +356,14 @@ public void readDocument(
356356
if (responseCode != 200) {
357357
response.close();
358358
if (responseCode == 404) {
359-
throw new ServiceException(SDMConstants.FILE_NOT_FOUND_ERROR);
359+
String errorMessage =
360+
context
361+
.getCdsRuntime()
362+
.getLocalizedMessage(
363+
"SDM.File.fileNotFoundError", null, context.getParameterInfo().getLocale());
364+
if (errorMessage.equalsIgnoreCase(SDMConstants.FILE_NOT_FOUND_ERROR_MSG))
365+
throw new ServiceException(SDMConstants.FILE_NOT_FOUND_ERROR);
366+
throw new ServiceException(errorMessage);
360367
}
361368
throw new ServiceException("Unexpected code");
362369
}
@@ -469,10 +476,10 @@ public String createFolder(
469476
else if (responseCode == 403) {
470477
throw new ServiceException(SDMConstants.USER_NOT_AUTHORISED_ERROR);
471478
} else {
472-
throw new ServiceException("Failed to create folder. " + responseBody);
479+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_FOLDER + ". " + responseBody);
473480
}
474481
} catch (IOException e) {
475-
throw new ServiceException("Failed to create folder " + e.getMessage());
482+
throw new ServiceException(SDMConstants.FAILED_TO_CREATE_FOLDER + " " + e.getMessage());
476483
}
477484
}
478485

0 commit comments

Comments
 (0)