-
Notifications
You must be signed in to change notification settings - Fork 7
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 7109 add support for informal language fix #106
Changes from 5 commits
d40b088
401d53c
74d1e9a
5446588
42cd7a1
08bd471
82b45b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.client.HttpClientErrorException; | ||
import org.springframework.web.client.ResourceAccessException; | ||
|
||
@Service | ||
@Slf4j | ||
|
@@ -35,17 +36,13 @@ public class TranslationService { | |
@Value("${weblate.component}") | ||
private String component; | ||
|
||
private final @NonNull TranlationMangementServiceApiClient tranlationMangementServiceApiClient; | ||
private final @NonNull TranlationMangementServiceApiClient tranlationMangementServiceApiClient; | ||
|
||
public TranslationService(TranlationMangementServiceApiClient tranlationMangementServiceApiClient) { | ||
public TranslationService( | ||
TranlationMangementServiceApiClient tranlationMangementServiceApiClient) { | ||
this.tranlationMangementServiceApiClient = tranlationMangementServiceApiClient; | ||
} | ||
|
||
@Cacheable(value = "translations") | ||
public Map<String, String> fetchTranslations(String languageCode) { | ||
return this.fetchTranslations(languageCode, Dialect.FORMAL); | ||
} | ||
|
||
@Cacheable(value = "translations") | ||
public Map<String, String> fetchTranslations(String languageCode, Dialect dialect) { | ||
try { | ||
|
@@ -63,7 +60,8 @@ public void evictCache() { | |
log.info("Evicting translations cache"); | ||
} | ||
|
||
private Map<String, String> fetchTranslationAsMap(String languageCode, Dialect dialect) throws JsonProcessingException { | ||
private Map<String, String> fetchTranslationAsMap(String languageCode, Dialect dialect) | ||
throws JsonProcessingException { | ||
String translations = fetchTranslationsAsString(languageCode, dialect); | ||
ObjectMapper mapper = new ObjectMapper(); | ||
return mapper.readValue(translations, Map.class); | ||
|
@@ -76,30 +74,41 @@ public Optional<Map<String, String>> tryFetchTranslations(String languageCode, D | |
var result = fetchTranslationAsMap(languageCode, dialect); | ||
return result.isEmpty() ? Optional.empty() : Optional.of(result); | ||
} catch (JsonProcessingException e) { | ||
log.warn("Error while processing json file with translations. Returning empty translations", e); | ||
log.warn("Error while processing json file with translations. Returning empty translations", | ||
e); | ||
return Optional.empty(); | ||
} | ||
} | ||
|
||
private String fetchTranslationsAsString(String languageCode, Dialect dialect) { | ||
try { | ||
return tranlationMangementServiceApiClient.tryFetchTranslationsFromTranslationManagementService(project, component, | ||
return tranlationMangementServiceApiClient.tryFetchTranslationsFromTranslationManagementService( | ||
project, component, | ||
languageCode, dialect); | ||
} catch (HttpClientErrorException e) { | ||
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) { | ||
log.warn("Translations for component {}, language {} not found in weblate, returning default translations", component, | ||
log.warn( | ||
"Translations for component {}, language {} not found in weblate, returning default translations", | ||
component, | ||
languageCode); | ||
return fetchDefaultTranslations(component, languageCode); | ||
return fetchDefaultTranslations(component, languageCode, dialect); | ||
} else { | ||
log.error("Error while fetching translations from translation management service", e); | ||
throw e; | ||
} | ||
} catch (ResourceAccessException ex) { | ||
log.error("ResourceAccessException error while fetching translations from translation management service. Will fallback to resolve default translations."); | ||
log.debug("Exception details: ", ex); | ||
return fetchDefaultTranslations(component, languageCode, dialect); | ||
} | ||
} | ||
|
||
private String fetchDefaultTranslations(String translationComponentName, String languageCode) { | ||
private String fetchDefaultTranslations(String translationComponentName, String languageCode, Dialect dialect) { | ||
String translationFilename = getTranslationFilename( | ||
translationComponentName + "." + languageCode | ||
+ TranlationMangementServiceApiClient.getDialectSuffix(dialect)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this fallback to mailservice.de.json? Or how does it work when its using dialect but we have no translation catalog for dialect stored in project? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the weblate api call it should be fine but we need to check if the configuration is correct. It should automatically fill up non translated strings in dialect with fallback to de. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hi @web-mi , do you want to have fallback logic to DE in case there is informal language setting in consultant profile but no informal file found? Ok, we can build this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes fallback logic if file does not exists locally. What is happening now when there is no informal file? In Frontend we have 2700 lines inside de.json and only some of them have informal Translation. Thats why we have the fallback to de. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hey @web-mi , added the fallback logic in case informal translation file does not exist There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh dear, Marc has touched on an nice topic here. In the context of the mail service, I would be fine to have all translations duplicated and adapted where needed. That's how it would currently work, because it's a new component in Weblate. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For frontend it makes sense to build a merge logic, but I don't see added value for the mailservice. Frontend translations are huge and there are would be many repetitions with duplicated keys. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was also speaking more from the perspective of the user operating Weblate... because they now need to understand how it works and where |
||
var inputStream = TranslationService.class.getResourceAsStream( | ||
getTranslationFilename(translationComponentName + "." + languageCode)); | ||
translationFilename); | ||
if (inputStream == null) { | ||
return "{}"; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package de.caritas.cob.mailservice.api; | ||
|
||
import static org.mockito.Mockito.verify; | ||
|
||
import de.caritas.cob.mailservice.api.model.Dialect; | ||
import de.caritas.cob.mailservice.api.service.TranslationService; | ||
import java.util.Locale; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class TranslationMessageSourceTest { | ||
|
||
private static final String INFORMAL_GERMAL_LANGUAGE_TAG = "de-DE-u-va-posix"; | ||
|
||
@InjectMocks | ||
private TranslationMessageSource translationMessageSource; | ||
|
||
@Mock | ||
private TranslationService translationService; | ||
|
||
@Test | ||
void getMessage_Should_CallFetchTranslations_With_FormalDialect_For_DefaultLocale() { | ||
// given | ||
Locale locale = Locale.getDefault(); | ||
|
||
// when | ||
translationMessageSource.getMessage("translation_key", new Object[]{}, "Message", locale); | ||
|
||
// then | ||
verify(translationService, Mockito.times(1)).fetchTranslations(locale.getLanguage(), Dialect.FORMAL); | ||
} | ||
|
||
@Test | ||
void getMessage_Should_CallFetchTranslations_With_InformalDialect_For_ForLocaleForInformalGerman() { | ||
// given | ||
Locale locale = Locale.forLanguageTag(INFORMAL_GERMAL_LANGUAGE_TAG); | ||
|
||
// when | ||
translationMessageSource.getMessage("translation_key", new Object[]{}, "Message", locale); | ||
|
||
// then | ||
verify(translationService, Mockito.times(1)).fetchTranslations(locale.getLanguage(), Dialect.INFORMAL); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package de.caritas.cob.mailservice.api.service; | ||
|
||
|
||
|
||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat; | ||
|
||
import com.google.common.collect.Lists; | ||
import de.caritas.cob.mailservice.api.exception.TemplateServiceException; | ||
import de.caritas.cob.mailservice.api.mailtemplate.SubjectDescription; | ||
import de.caritas.cob.mailservice.api.mailtemplate.TemplateDescription; | ||
import de.caritas.cob.mailservice.api.model.Dialect; | ||
import de.caritas.cob.mailservice.api.model.LanguageCode; | ||
import de.caritas.cob.mailservice.api.model.MailDTO; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.test.context.ActiveProfiles; | ||
|
||
@SpringBootTest | ||
@AutoConfigureMockMvc | ||
@ActiveProfiles("testing") | ||
class TemplateServiceIntegrationTest { | ||
|
||
@Autowired | ||
private TemplateService templateService; | ||
|
||
@Autowired | ||
private TranslationService translationService; | ||
|
||
@Test | ||
void getProcessedHtmlTemplate_Should_RenderTemplateData_With_InformalDialect() | ||
throws TemplateServiceException { | ||
|
||
Optional<String> renderedHtml = templateService.render( | ||
new TemplateDescription(Map.of(LanguageCode.DE, "message-notification-consultant.html"), | ||
new SubjectDescription("translationKey"), | ||
Lists.newArrayList(), | ||
null), | ||
new MailDTO() | ||
.template("message-notification-consultant") | ||
.language(LanguageCode.DE) | ||
.dialect(Dialect.INFORMAL), | ||
new HashMap<>()); | ||
assertThat(renderedHtml).isPresent(); | ||
assertThat(renderedHtml.get()).contains("Du hast eine neue Nachricht in Deinen Beratungen"); | ||
} | ||
|
||
@Test | ||
void getProcessedHtmlTemplate_Should_RenderTemplateData_With_FormalDialect() | ||
throws TemplateServiceException { | ||
|
||
Optional<String> renderedHtml = templateService.render( | ||
new TemplateDescription(Map.of(LanguageCode.DE, "message-notification-consultant.html"), | ||
new SubjectDescription("translationKey"), | ||
Lists.newArrayList(), | ||
null), | ||
new MailDTO() | ||
.template("message-notification-consultant") | ||
.language(LanguageCode.DE) | ||
.dialect(Dialect.FORMAL), | ||
new HashMap<>()); | ||
assertThat(renderedHtml).isPresent(); | ||
assertThat(renderedHtml.get()).contains("Sie haben eine neue Nachricht in Ihren Beratungen"); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GERMAN :)