diff --git a/src/main/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsService.java b/src/main/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsService.java index 5505463..4765b95 100644 --- a/src/main/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsService.java +++ b/src/main/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsService.java @@ -1,22 +1,34 @@ package de.caritas.cob.mailservice.api.service; -import de.caritas.cob.mailservice.api.model.Dialect; -import de.caritas.cob.mailservice.config.apiclient.TranlationMangementServiceApiClient; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.List; -import lombok.extern.slf4j.Slf4j; + import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import de.caritas.cob.mailservice.api.model.Dialect; +import lombok.extern.slf4j.Slf4j; + @Slf4j @Service public class DefaultTranslationsService { + @Value("${template.custom.default.translations.path}") + private String customTranslationsPath; + + @Value("${template.use.custom.resources.path}") + private boolean useCustomResourcesPath; + public String fetchDefaultTranslations(String translationComponentName, String languageCode, Dialect dialect) { - InputStream inputStream = tryFetchDefaultTranslationWithFallbackToEmptyDialect(translationComponentName, languageCode, dialect); + InputStream inputStream = useCustomResourcesPath ? tryFetchExternalTranslationWithFallbackToEmptyDialect(translationComponentName, languageCode, dialect) : + tryFetchDefaultTranslationWithFallbackToEmptyDialect(translationComponentName, languageCode, dialect); if (inputStream == null) { return "{}"; } @@ -31,6 +43,23 @@ public String fetchDefaultTranslations(String translationComponentName, String l } } + private InputStream tryFetchExternalTranslationWithFallbackToEmptyDialect(String translationComponentName, String languageCode, + Dialect dialect) { + InputStream inputStream = buildStreamForExternalPath(translationComponentName, languageCode, dialect); + return inputStream != null ? inputStream : buildStreamForExternalPath(translationComponentName, languageCode, null); + } + + private FileInputStream buildStreamForExternalPath(String translationComponentName, String languageCode, Dialect dialect) { + try { + String filename = String.format("%s/%s.%s%s.json", customTranslationsPath, translationComponentName.toLowerCase(), languageCode, getDialectSuffix(dialect)); + return new FileInputStream(filename); + } catch (FileNotFoundException e) { + log.warn("Default translations for component {}, language {} not found in external path {}", translationComponentName, + languageCode, customTranslationsPath); + return null; + } + } + private InputStream tryFetchDefaultTranslationWithFallbackToEmptyDialect(String translationComponentName, String languageCode, Dialect dialect) { InputStream inputStream = getInputStream(translationComponentName, languageCode, @@ -57,10 +86,20 @@ private InputStream getInputStream(String translationComponentName, String langu Dialect dialect) { String translationFilename = getTranslationFilename( translationComponentName + "." + languageCode - + TranlationMangementServiceApiClient.getDialectSuffix(dialect)); + + getDialectSuffix(dialect)); return TranslationService.class.getResourceAsStream(translationFilename); } + public static String getDialectSuffix(Dialect dialect) { + if (dialect == null) { + return StringUtils.EMPTY; + } + if (dialect == Dialect.INFORMAL) { + return "_informal"; + } + return StringUtils.EMPTY; + } + private String getTranslationFilename(String templateName) { return "/i18n/" + templateName.toLowerCase() + ".json"; } diff --git a/src/main/java/de/caritas/cob/mailservice/api/service/TranslationService.java b/src/main/java/de/caritas/cob/mailservice/api/service/TranslationService.java index 84cf634..a7b6c28 100644 --- a/src/main/java/de/caritas/cob/mailservice/api/service/TranslationService.java +++ b/src/main/java/de/caritas/cob/mailservice/api/service/TranslationService.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import de.caritas.cob.mailservice.api.model.Dialect; -import de.caritas.cob.mailservice.config.apiclient.TranlationMangementServiceApiClient; +import de.caritas.cob.mailservice.config.apiclient.TranslationManagementServiceApiClient; import java.util.Map; import java.util.Optional; import lombok.NonNull; @@ -32,13 +32,16 @@ public class TranslationService { @Value("${weblate.component}") private String component; - private final @NonNull TranlationMangementServiceApiClient tranlationMangementServiceApiClient; + @Value("${translation.management.system.enabled}") + private boolean translationManagementSystemEnabled; + + private final @NonNull TranslationManagementServiceApiClient translationManagementServiceApiClient; private final @NonNull DefaultTranslationsService defaultTranslationsService; public TranslationService( - TranlationMangementServiceApiClient tranlationMangementServiceApiClient, DefaultTranslationsService defaultTranslationsService) { - this.tranlationMangementServiceApiClient = tranlationMangementServiceApiClient; + TranslationManagementServiceApiClient translationManagementServiceApiClient, DefaultTranslationsService defaultTranslationsService) { + this.translationManagementServiceApiClient = translationManagementServiceApiClient; this.defaultTranslationsService = defaultTranslationsService; } @@ -85,9 +88,12 @@ private String fetchTranslationsAsString(String languageCode, Dialect dialect) { private String fetchDefaultTranslationsFromTranslationsManagementSystem(String languageCode, Dialect dialect) { try { - return tranlationMangementServiceApiClient.tryFetchTranslationsFromTranslationManagementService( + log.info("Fetching translations. Translation management system enabled value: {}", + translationManagementSystemEnabled); + return translationManagementSystemEnabled ? translationManagementServiceApiClient.tryFetchTranslationsFromTranslationManagementService( project, component, - languageCode, dialect); + languageCode, dialect) : defaultTranslationsService.fetchDefaultTranslations(component, languageCode, + dialect); } catch (HttpClientErrorException e) { if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { log.warn( diff --git a/src/main/java/de/caritas/cob/mailservice/config/apiclient/TranlationMangementServiceApiClient.java b/src/main/java/de/caritas/cob/mailservice/config/apiclient/TranslationManagementServiceApiClient.java similarity index 87% rename from src/main/java/de/caritas/cob/mailservice/config/apiclient/TranlationMangementServiceApiClient.java rename to src/main/java/de/caritas/cob/mailservice/config/apiclient/TranslationManagementServiceApiClient.java index 80184e8..8ec5776 100644 --- a/src/main/java/de/caritas/cob/mailservice/config/apiclient/TranlationMangementServiceApiClient.java +++ b/src/main/java/de/caritas/cob/mailservice/config/apiclient/TranslationManagementServiceApiClient.java @@ -16,7 +16,7 @@ @Service @RequiredArgsConstructor @Slf4j -public class TranlationMangementServiceApiClient { +public class TranslationManagementServiceApiClient { @Value("${weblate.api.url}") private String apiUrl; @@ -24,15 +24,13 @@ public class TranlationMangementServiceApiClient { @Value("${weblate.api.key}") private String apiKey; - - private final @NonNull RestTemplate restTemplate; public String tryFetchTranslationsFromTranslationManagementService(String project, String component, String languageCode, Dialect dialect) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Token " + apiKey); - String url = apiUrl + "translations/" + project + "/" + component + "/" + languageCode + getDialectSuffix(dialect) + String url = apiUrl + "translations/" + project + "/" + component + "/" + languageCode + getTranslationManagementServiceDialectSuffix(dialect) + "/file.json"; log.info("Calling url to fetch translations: {}", url); @@ -41,7 +39,7 @@ public String tryFetchTranslationsFromTranslationManagementService(String projec return response.getBody(); } - public static String getDialectSuffix(Dialect dialect) { + public static String getTranslationManagementServiceDialectSuffix(Dialect dialect) { if (dialect == null) { return StringUtils.EMPTY; } diff --git a/src/main/resources/application-testing.properties b/src/main/resources/application-testing.properties index b6c0ddd..3fb4796 100644 --- a/src/main/resources/application-testing.properties +++ b/src/main/resources/application-testing.properties @@ -6,6 +6,7 @@ mail.exchange.version=Exchange2010_SP2 template.use.custom.resources.path=false template.custom.resources.path=false +translation.management.system.enabled=false csrf.header.property=csrfHeader csrf.cookie.property=csrfCookie diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 63ea274..d244cd4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -62,6 +62,8 @@ csrf.cookie.property= # refactoring template.use.custom.resources.path= template.custom.resources.path= +template.custom.default.translations.path= +translation.management.system.enabled= weblate.api.url= weblate.api.key= @@ -74,4 +76,4 @@ management.endpoints.web.exposure.include=health management.health.probes.enabled=true spring.cache.jcache.config=classpath:ehcache.xml -logging.level.net.sf.ehcache=info \ No newline at end of file +logging.level.net.sf.ehcache=info diff --git a/src/main/resources/i18n/mailservice.de@informal.json b/src/main/resources/i18n/mailservice.de_informal.json similarity index 100% rename from src/main/resources/i18n/mailservice.de@informal.json rename to src/main/resources/i18n/mailservice.de_informal.json diff --git a/src/test/java/de/caritas/cob/mailservice/api/controller/MailControllerE2EIT.java b/src/test/java/de/caritas/cob/mailservice/api/controller/MailControllerE2EIT.java index 4972ee4..c94b66c 100644 --- a/src/test/java/de/caritas/cob/mailservice/api/controller/MailControllerE2EIT.java +++ b/src/test/java/de/caritas/cob/mailservice/api/controller/MailControllerE2EIT.java @@ -14,7 +14,7 @@ import de.caritas.cob.mailservice.api.model.MailDTO; import de.caritas.cob.mailservice.api.model.MailsDTO; import de.caritas.cob.mailservice.api.model.TemplateDataDTO; -import de.caritas.cob.mailservice.config.apiclient.TranlationMangementServiceApiClient; +import de.caritas.cob.mailservice.config.apiclient.TranslationManagementServiceApiClient; import java.util.List; import java.util.Map; import javax.servlet.http.Cookie; @@ -57,7 +57,7 @@ class MailControllerE2EIT { private JavaMailSender javaMailSender; @MockBean - private TranlationMangementServiceApiClient tranlationMangementServiceApiClient; + private TranslationManagementServiceApiClient translationManagementServiceApiClient; @Captor private ArgumentCaptor mimeMessagePrepCaptor; @@ -67,8 +67,7 @@ class MailControllerE2EIT { @BeforeEach void setUp() { - Mockito.doThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND)).when( - tranlationMangementServiceApiClient).tryFetchTranslationsFromTranslationManagementService( + Mockito.doThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND)).when(translationManagementServiceApiClient).tryFetchTranslationsFromTranslationManagementService( anyString(), anyString(), anyString(), any(Dialect.class)); } diff --git a/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceIT.java b/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceIT.java new file mode 100644 index 0000000..d413fc8 --- /dev/null +++ b/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceIT.java @@ -0,0 +1,105 @@ +package de.caritas.cob.mailservice.api.service; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import de.caritas.cob.mailservice.api.model.Dialect; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.util.ReflectionTestUtils; + +@SpringBootTest +@ActiveProfiles("testing") +class DefaultTranslationsServiceIT { + + @Autowired + private DefaultTranslationsService defaultTranslationsService; + + public final String USE_CUSTOM_RESOURCES_PATH_FIELD_NAME = "useCustomResourcesPath"; + public final String CUSTOM_TRANSLATIONS_PATH_FIELD_NAME = "customTranslationsPath"; + + @BeforeEach + public void setUp() { + defaultTranslationsService = new DefaultTranslationsService(); + ReflectionTestUtils.setField(defaultTranslationsService, CUSTOM_TRANSLATIONS_PATH_FIELD_NAME, System.getProperty("user.dir") + "/src/main/resources/i18n"); + } + + @AfterEach + public void clean() { + ReflectionTestUtils.setField(defaultTranslationsService, USE_CUSTOM_RESOURCES_PATH_FIELD_NAME, false); + } + + @Test + void fetchDefaultTranslations_Should_FetchTranlsationsForInformalGerman() { + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", + Dialect.INFORMAL); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("hat Dir {0} als neuen Ratsuchenden zugewiesen."); + } + + @Test + void fetchDefaultTranslations_Should_FetchTranlsationsForFormalIfDialectNullGerman() { + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", + null); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("hat Ihnen {0} als neuen Ratsuchenden zugewiesen."); + } + + @Test + void fetchDefaultTranslations_Should_FetchTranlsationsForEnglish() { + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "en", + null); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("has assigned you {0} new advice seeker."); + } + + @Test + void fetchDefaultTranslations_Should_fetchExternalTranslationsForFormalIfDialectNullGerman_When_useCustomResourcesPath_is_true() { + + ReflectionTestUtils.setField(defaultTranslationsService, USE_CUSTOM_RESOURCES_PATH_FIELD_NAME, true); + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", + null); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("Sie haben eine neue Nachricht in Ihren Beratungen"); + + } + + @Test + void fetchDefaultTranslations_Should_fetchExternalTranslationsForEnglish_When_useCustomResourcesPath_is_true() { + + ReflectionTestUtils.setField(defaultTranslationsService, USE_CUSTOM_RESOURCES_PATH_FIELD_NAME, true); + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "en", + null); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("You have a new message in your counselings"); + + } + + @Test + void fetchDefaultTranslations_Should_fetchExternalTranslationsForInformalGerman_When_useCustomResourcesPath_is_true() { + + ReflectionTestUtils.setField(defaultTranslationsService, USE_CUSTOM_RESOURCES_PATH_FIELD_NAME, true); + + String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", + Dialect.INFORMAL); + + assertThat(translations).isNotNull(); + assertThat(translations).contains("Du hast eine neue Nachricht in Deinen Beratungen"); + + } + +} diff --git a/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceTest.java b/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceTest.java deleted file mode 100644 index f9554c7..0000000 --- a/src/test/java/de/caritas/cob/mailservice/api/service/DefaultTranslationsServiceTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.caritas.cob.mailservice.api.service; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import de.caritas.cob.mailservice.api.model.Dialect; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; - -@SpringBootTest -@ActiveProfiles("testing") -class DefaultTranslationsServiceTest { - - @Autowired - DefaultTranslationsService defaultTranslationsService; - - @Test - void fetchDefaultTranslations_Should_FetchTranlsationsForInformalGerman() { - - String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", - Dialect.INFORMAL); - - assertThat(translations).isNotNull(); - assertThat(translations).contains("hat Dir {0} als neuen Ratsuchenden zugewiesen."); - } - - @Test - void fetchDefaultTranslations_Should_FetchTranlsationsForFormalIfDialectNullGerman() { - - String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "de", - null); - - assertThat(translations).isNotNull(); - assertThat(translations).contains("hat Ihnen {0} als neuen Ratsuchenden zugewiesen."); - } - - @Test - void fetchDefaultTranslations_Should_FetchTranlsationsForEnglish() { - - String translations = defaultTranslationsService.fetchDefaultTranslations("mailservice", "en", - null); - - assertThat(translations).isNotNull(); - assertThat(translations).contains("has assigned you {0} new advice seeker."); - } - -} \ No newline at end of file diff --git a/src/test/java/de/caritas/cob/mailservice/api/service/TranslationServiceTest.java b/src/test/java/de/caritas/cob/mailservice/api/service/TranslationServiceTest.java new file mode 100644 index 0000000..eea8d00 --- /dev/null +++ b/src/test/java/de/caritas/cob/mailservice/api/service/TranslationServiceTest.java @@ -0,0 +1,100 @@ +package de.caritas.cob.mailservice.api.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.HttpStatus; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.HttpClientErrorException; + +import de.caritas.cob.mailservice.api.model.Dialect; +import de.caritas.cob.mailservice.config.apiclient.TranslationManagementServiceApiClient; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TranslationServiceTest { + + private TranslationService translationService; + + @Mock + private TranslationManagementServiceApiClient translationManagementServiceApiClient; + + @Mock + private DefaultTranslationsService defaultTranslationsService; + + public final String TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_NAME = "translationManagementSystemEnabled"; + + @BeforeEach + public void setUp() { + translationService = new TranslationService(translationManagementServiceApiClient, defaultTranslationsService); + } + + @Test + void fetchTranslations_Should_call_translationManagementServiceApiClient_When_translationManagementSystemEnabled_is_true() { + + // Given + + final boolean TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE = true; + ReflectionTestUtils.setField(translationService, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_NAME, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE); + when(translationManagementServiceApiClient.tryFetchTranslationsFromTranslationManagementService(any(), any(), any(), any())).thenReturn("{\"mail.label.header\": \"Beratung\"}"); + + // When + + translationService.fetchTranslations("test", Dialect.INFORMAL); + + // Then + + verify(translationManagementServiceApiClient).tryFetchTranslationsFromTranslationManagementService(any(), any(), any(), any()); + verifyNoInteractions(defaultTranslationsService); + + } + + @Test + void fetchTranslations_Should_call_fetchDefaultTranslations_When_translationManagementSystemEnabled_is_true_but_translationManagementServiceApiClient_Throws_HttpClientErrorException() { + + // Given + + final boolean TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE = true; + ReflectionTestUtils.setField(translationService, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_NAME, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE); + when(translationManagementServiceApiClient.tryFetchTranslationsFromTranslationManagementService(any(), any(), any(), any())).thenThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND)); + when(defaultTranslationsService.fetchDefaultTranslations(any(), any(), any())).thenReturn("{\"mail.label.header\": \"Beratung\"}"); + + // When + + translationService.fetchTranslations("test", Dialect.INFORMAL); + + // Then + + verify(translationManagementServiceApiClient).tryFetchTranslationsFromTranslationManagementService(any(), any(), any(), any()); + verify(defaultTranslationsService).fetchDefaultTranslations(any(), any(), any()); + verifyNoMoreInteractions(translationManagementServiceApiClient); + + } + + @Test + void fetchTranslations_Should_call_fetchDefaultTranslations_When_translationManagementSystemEnabled_is_false() { + + // Given + + final boolean TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE = false; + ReflectionTestUtils.setField(translationService, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_NAME, TRANSLATION_MANAGEMENT_SYSTEM_ENABLED_FIELD_VALUE); + when(defaultTranslationsService.fetchDefaultTranslations(any(), any(), any())).thenReturn("{\"mail.label.header\": \"Beratung\"}"); + + // When + + translationService.fetchTranslations("test", Dialect.INFORMAL); + + // Then + + verifyNoInteractions(translationManagementServiceApiClient); + verify(defaultTranslationsService).fetchDefaultTranslations(any(), any(), any()); + + } +}