Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ob 8353 externalize translations config #107

Merged
merged 8 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Leandro13Silva13 marked this conversation as resolved.
Show resolved Hide resolved

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
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
Loading