Skip to content

Commit

Permalink
Merge pull request #107 from Onlineberatung/OB-8353-externalize-trans…
Browse files Browse the repository at this point in the history
…lations-config

Ob 8353 externalize translations config
  • Loading branch information
tkuzynow authored Jan 18, 2024
2 parents 0870404 + 12d1ef5 commit b7a3a22
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -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 "{}";
}
Expand All @@ -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,
Expand All @@ -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";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,21 @@
@Service
@RequiredArgsConstructor
@Slf4j
public class TranlationMangementServiceApiClient {
public class TranslationManagementServiceApiClient {

@Value("${weblate.api.url}")
private String apiUrl;

@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);
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application-testing.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand All @@ -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
logging.level.net.sf.ehcache=info
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -57,7 +57,7 @@ class MailControllerE2EIT {
private JavaMailSender javaMailSender;

@MockBean
private TranlationMangementServiceApiClient tranlationMangementServiceApiClient;
private TranslationManagementServiceApiClient translationManagementServiceApiClient;

@Captor
private ArgumentCaptor<MimeMessagePreparator> mimeMessagePrepCaptor;
Expand All @@ -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));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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");

}

}

This file was deleted.

Loading

0 comments on commit b7a3a22

Please sign in to comment.