de.frachtwerk.essencium.backend.service.translation.TranslationService Maven / Gradle / Ivy
/*
* Copyright (C) 2024 Frachtwerk GmbH, Leopoldstraße 7C, 76133 Karlsruhe.
*
* This file is part of essencium-backend.
*
* essencium-backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* essencium-backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with essencium-backend. If not, see .
*/
package de.frachtwerk.essencium.backend.service.translation;
import static de.frachtwerk.essencium.backend.service.translation.TranslationFileService.TRANSLATION_FILE_CACHE;
import de.frachtwerk.essencium.backend.model.Translation;
import de.frachtwerk.essencium.backend.repository.TranslationRepository;
import jakarta.validation.constraints.NotNull;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
@Service
public class TranslationService {
private final TranslationRepository translationRepository;
@Autowired
public TranslationService(@NotNull final TranslationRepository translationRepository) {
this.translationRepository = translationRepository;
}
public Collection getTranslations() {
return translationRepository.findAll();
}
public Collection getTranslations(@NotNull final Locale locale) {
return translationRepository.findAllByLocale(locale);
}
public Optional translate(String key, Locale locale) {
return translateVariant(key, locale, 0);
}
// Inspired https://kazupon.github.io/vue-i18n/guide/pluralization.html
public Optional translateVariant(String key, Locale locale, int variantIndex) {
final var translation = translationRepository.findByKeyAndLocale(key, locale);
return translation
.map(Translation::getValue)
.flatMap(s -> Stream.of(s.split("\\|")).skip(variantIndex).findFirst())
.map(String::trim);
}
@CacheEvict(value = TRANSLATION_FILE_CACHE, allEntries = true)
public Translation updateTranslation(@NotNull final Translation translation) {
return translationRepository.save(translation);
}
@CacheEvict(value = TRANSLATION_FILE_CACHE, allEntries = true)
public Collection updateTranslations(
@NotNull final Collection translations) {
return translationRepository.saveAll(translations);
}
@CacheEvict(value = TRANSLATION_FILE_CACHE, allEntries = true)
public Collection updateTranslation(
@NotNull final Locale locale, Map translationObjects) {
final Collection> keyValueList = parseKeyValueList("", translationObjects);
final Collection translations =
keyValueList.stream()
.map(
translationPair ->
new Translation(
locale, translationPair.getFirst(), translationPair.getSecond()))
.collect(Collectors.toCollection(LinkedList::new));
return translationRepository.saveAll(translations);
}
public void deleteTranslation(String key) {
translationRepository.deleteAll(translationRepository.findAllByKey(key));
}
public SortedMap> getTranslationsGroupedByKey() {
return translationRepository.findAll().stream()
.collect(Collectors.groupingBy(Translation::getKey, TreeMap::new, Collectors.toList()));
}
public Map> getTranslationMaps() {
var translations = translationRepository.findAll();
return translations.stream()
.collect(
Collectors.groupingBy(
Translation::getKey,
Collectors.groupingBy(
Translation::getLocale,
Collectors.mapping(
Translation::getValue, Collectors.reducing("", (o1, o2) -> o2)))));
}
public Collection getAvailableLocales() {
return translationRepository.findDistinctLocale();
}
public Map> getTranslatedAvailableLocales() {
Set availableLocales = translationRepository.findDistinctLocale();
return availableLocales.stream()
.flatMap(l1 -> availableLocales.stream().map(l2 -> Pair.of(l1, l2)))
.collect(
Collectors.groupingBy(
Pair::getFirst,
Collectors.toMap(
Pair::getSecond, p -> p.getFirst().getDisplayLanguage(p.getSecond()))));
}
@NotNull
private Collection> parseKeyValueList(
final String headKey, final Map translationObjects) {
final var keyValueList = new LinkedList>();
translationObjects.forEach(
(key, object) -> {
if (object instanceof final String value) {
final String translationKey = headKey + key;
keyValueList.add(Pair.of(translationKey, value));
} else if (object instanceof Map) {
final String newHeadKey = headKey + key + ".";
//noinspection unchecked
final Map translationMap = (Map) object;
keyValueList.addAll(parseKeyValueList(newHeadKey, translationMap));
} else {
throw new IllegalArgumentException(
"Unable to parse translation map. Only Strings are allowed");
}
});
return keyValueList;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy