-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #103 from Onlineberatung/OB-7091-mailservice-and-w…
…eblate-integration Ob 7091 mailservice and weblate integration
- Loading branch information
Showing
26 changed files
with
520 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<config | ||
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' | ||
xmlns='http://www.ehcache.org/v3' | ||
xsi:schemaLocation=" | ||
http://www.ehcache.org/v3 | ||
http://www.ehcache.org/schema/ehcache-core-3.7.xsd"> | ||
|
||
<cache alias="translations"> | ||
<expiry> | ||
<ttl unit="seconds">60</ttl> | ||
</expiry> | ||
|
||
<resources> | ||
<offheap unit="MB">10</offheap> | ||
</resources> | ||
</cache> | ||
|
||
<cache-template name="default"> | ||
<expiry> | ||
<ttl unit="seconds">60</ttl> | ||
</expiry> | ||
<listeners> | ||
<listener> | ||
<class>de.caritas.cob.mailservice.api.cache.CacheEventLogger</class> | ||
<event-firing-mode>ASYNCHRONOUS</event-firing-mode> | ||
<event-ordering-mode>UNORDERED</event-ordering-mode> | ||
<events-to-fire-on>CREATED</events-to-fire-on> | ||
<events-to-fire-on>EXPIRED</events-to-fire-on> | ||
<events-to-fire-on>EVICTED</events-to-fire-on> | ||
</listener> | ||
</listeners> | ||
<resources> | ||
<heap>1000</heap> | ||
<offheap unit="MB">10</offheap> | ||
<disk persistent="true" unit="MB">20</disk> | ||
</resources> | ||
</cache-template> | ||
</config> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/main/java/de/caritas/cob/mailservice/api/RestApiMessageSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package de.caritas.cob.mailservice.api; | ||
|
||
import de.caritas.cob.mailservice.api.service.TranslationService; | ||
import java.util.Locale; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.context.MessageSource; | ||
import org.springframework.context.MessageSourceResolvable; | ||
import org.springframework.context.NoSuchMessageException; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class RestApiMessageSource implements MessageSource { | ||
|
||
|
||
public final @NonNull TranslationService translationService; | ||
|
||
@Override | ||
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { | ||
log.info("getMessage called with code: {}, args: {}, defaultMessage: {}, locale: {}", code, | ||
args, defaultMessage, locale); | ||
return translationService.fetchTranslations(locale.getLanguage()).get(code); | ||
} | ||
|
||
@Override | ||
public String getMessage(String code, Object[] args, Locale locale) | ||
throws NoSuchMessageException { | ||
return getMessage(code, args, null, locale); | ||
} | ||
|
||
@Override | ||
public String getMessage(MessageSourceResolvable resolvable, Locale locale) | ||
throws NoSuchMessageException { | ||
if (resolvable == null) { | ||
log.warn("getMessage called with null resolvable"); | ||
return null; | ||
} | ||
return getMessage(resolvable.getCodes()[0], null, locale); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/de/caritas/cob/mailservice/api/cache/CacheEventLogger.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package de.caritas.cob.mailservice.api.cache; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.ehcache.event.CacheEvent; | ||
import org.ehcache.event.CacheEventListener; | ||
|
||
@Slf4j | ||
public class CacheEventLogger implements CacheEventListener<Object, Object> { | ||
|
||
@Override | ||
public void onEvent(CacheEvent<? extends Object, ? extends Object> cacheEvent) { | ||
log.info( | ||
"caching event: ", cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue()); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/main/java/de/caritas/cob/mailservice/api/controller/TranslationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package de.caritas.cob.mailservice.api.controller; | ||
|
||
import de.caritas.cob.mailservice.api.service.TranslationService; | ||
import java.util.Map; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.ResponseBody; | ||
|
||
|
||
@Controller | ||
@RequiredArgsConstructor | ||
public class TranslationController { | ||
|
||
private final @NonNull TranslationService translationService; | ||
|
||
@GetMapping(value = "/translations") | ||
public ResponseEntity<Map<String, String>> getTranslations() { | ||
var result = translationService.fetchTranslations("de"); | ||
return new ResponseEntity<>(result, org.springframework.http.HttpStatus.OK); | ||
} | ||
|
||
@GetMapping(value = "/translations/evict") | ||
@ResponseBody | ||
public String evictTranslationCache() { | ||
translationService.evictCache(); | ||
return "Cache evicted"; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/main/java/de/caritas/cob/mailservice/api/service/TranslationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package de.caritas.cob.mailservice.api.service; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import de.caritas.cob.mailservice.config.apiclient.TranlationMangementServiceApiClient; | ||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import lombok.NonNull; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.commons.io.IOUtils; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.cache.annotation.CacheEvict; | ||
import org.springframework.cache.annotation.Cacheable; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
|
||
@Service | ||
@Slf4j | ||
public class TranslationService { | ||
|
||
@Value("${weblate.api.url}") | ||
private String apiUrl; | ||
|
||
@Value("${weblate.api.key}") | ||
private String apiKey; | ||
|
||
@Value("${weblate.project}") | ||
private String project; | ||
|
||
@Value("${weblate.component}") | ||
private String component; | ||
|
||
private final @NonNull TranlationMangementServiceApiClient tranlationMangementServiceApiClient; | ||
|
||
public TranslationService(TranlationMangementServiceApiClient tranlationMangementServiceApiClient) { | ||
this.tranlationMangementServiceApiClient = tranlationMangementServiceApiClient; | ||
} | ||
|
||
@Cacheable(value = "translations") | ||
public Map<String, String> fetchTranslations(String languageCode) { | ||
try { | ||
|
||
return fetchTranslationAsMap(languageCode); | ||
} catch (JsonProcessingException ex) { | ||
throw new TranslationServiceException(String.format( | ||
"Json file with translations could not be parsed, translation component name: %s", | ||
component), ex); | ||
} | ||
} | ||
|
||
@CacheEvict(value = "translations", allEntries = true) | ||
public void evictCache() { | ||
log.info("Evicting translations cache"); | ||
} | ||
|
||
private Map<String, String> fetchTranslationAsMap(String languageCode) throws JsonProcessingException { | ||
String translations = fetchTranslationsAsString(languageCode); | ||
ObjectMapper mapper = new ObjectMapper(); | ||
return mapper.readValue(translations, Map.class); | ||
} | ||
|
||
public Optional<Map<String, String>> tryFetchTranslations(String languageCode) { | ||
|
||
try { | ||
var result = fetchTranslationAsMap(languageCode); | ||
return Optional.of(result); | ||
} catch (JsonProcessingException e) { | ||
log.warn("Error while processing json file with translations. Returning empty translations", e); | ||
return Optional.empty(); | ||
} | ||
|
||
} | ||
|
||
private String fetchTranslationsAsString(String languageCode) { | ||
try { | ||
return tranlationMangementServiceApiClient.tryFetchTranslationsFromTranslationManagementService(project, component, | ||
languageCode); | ||
} catch (HttpClientErrorException e) { | ||
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { | ||
log.warn("Translations for component {}, language {} not found in weblate, returning default translations", component, | ||
languageCode); | ||
return fetchDefaultTranslations(component, languageCode); | ||
} else { | ||
log.error("Error while fetching translations from translation management service", e); | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
private String fetchDefaultTranslations(String translationComponentName, String languageCode) { | ||
var inputStream = TranslationService.class.getResourceAsStream( | ||
getTranslationFilename(translationComponentName + "." + languageCode)); | ||
if (inputStream == null) { | ||
return "{}"; | ||
} | ||
try { | ||
final List<String> fileLines = IOUtils | ||
.readLines(inputStream, StandardCharsets.UTF_8.displayName()); | ||
return String.join("", fileLines); | ||
} catch (IOException ex) { | ||
throw new IllegalStateException(String.format( | ||
"Json file with translations could not be loaded, translation component name: %s", | ||
translationComponentName), ex); | ||
} | ||
} | ||
|
||
private String getTranslationFilename(String templateName) { | ||
return "/i18n/" + templateName.toLowerCase() + ".json"; | ||
} | ||
|
||
private class TranslationServiceException extends RuntimeException { | ||
|
||
public TranslationServiceException(String format, JsonProcessingException ex) { | ||
super(format, ex); | ||
} | ||
} | ||
} |
Oops, something went wrong.